Android低功耗蓝牙(BLE)开发(二)

这篇具有很好参考价值的文章主要介绍了Android低功耗蓝牙(BLE)开发(二)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

在上一篇文章Android低功耗蓝牙(BLE)开发(一)中我们了解了BLE的相关概念,这里我们来实际用代码演示安卓进行BLE连接和通讯的功能。本文代码基于Android5.0以上(API 21)

1.声明权限

在AndroidManifest.xml文件中添加BLE相关的权限声明。

<!-- 蓝牙权限 -->
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />

<!-- 安卓12开始需要下列权限 compileSDK 32+ -->
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />

<!--安卓6.0以及以上版本需要添加定位的权限 (需要在代码中动态申请)-->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-feature android:name="android.hardware.location.gps" />
    
<!--如果你的app只为具有BLE的设备提供,请声明-->
<uses-feature android:name="android.hardware.bluetooth_le" android:required="true"/>

2.判断设备是否支持BLE以及蓝牙是否打开

/**
  *  判断设备是否支持BLE
  */
fun checkSupportBLE(context: Context):Boolean{
    val packageManager: PackageManager = context.packageManager
    return packageManager.hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)
}

/**
  * 判断蓝牙是否打开
  */
fun isBluetoothEnabled(context: Context):Boolean{
    val bluetoothManager = BluetoothAdapter.getDefaultAdapter()
    return bluetoothAdapter == null || bluetoothAdapter?.isEnabled == false
}

3.进行扫描

val scanCallback: ScanCallback = object : ScanCallback() {
    override fun onScanResult(callbackType: Int, result: ScanResult?) {
         val device= result?.getDevice()
          // 处理扫描到的设备
    }
}

val bluetoothAdapter = BluetoothAdapter.getDefaultAdapter()
bluetoothAdapter.bluetoothLeScanner.startScan(scanCallback)

4.建立连接并监听

在BluetoothGattCallback进行监听相关回调

val gattCallback = object : BluetoothGattCallback() {

    override fun onConnectionStateChange(gatt: BluetoothGatt?, status: Int, newState: Int) {
        if (newState == BluetoothProfile.STATE_CONNECTED) {
            // 连接成功,进行服务发现
            gatt?.discoverServices()
        } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
            // 连接断开,处理断开逻辑
        }
    }

    override fun onServicesDiscovered(gatt: BluetoothGatt?, status: Int) {
        if (status == BluetoothGatt.GATT_SUCCESS) {
            // 服务发现成功,处理服务和特征值
            val services = gatt?.services
            services?.let {
                for (service in it) {
                    // 处理服务和特征值
                }
            }
        } else {
            // 服务发现失败
        }
    }

    override fun onCharacteristicRead(
        gatt: BluetoothGatt,
        characteristic: BluetoothGattCharacteristic,
        value: ByteArray,
        status: Int
    ) {
        if (status == BluetoothGatt.GATT_SUCCESS) {
            Log.i(TAG, "读取特征值")
            // 从特征值读取数据
            // characteristic 是特征值,而特征值是用 16bit 或者 128bit,16bit 是官方认证过的,128bit 是可以自定义的
            val sucString = characteristic.value
        }
    }

    override fun onCharacteristicWrite(
        gatt: BluetoothGatt?,
        characteristic: BluetoothGattCharacteristic?,
        status: Int
    ) {
        super.onCharacteristicWrite(gatt, characteristic, status)
        if (status == BluetoothGatt.GATT_SUCCESS) {
            Log.i(TAG, "写入特征值")
        }
    }

    override fun onCharacteristicChanged(
        gatt: BluetoothGatt,
        characteristic: BluetoothGattCharacteristic,
        value: ByteArray
    ) {
        Log.i(TAG, "特征值${characteristic.uuid.toString()}变化")
    }

    override fun onDescriptorRead(
        gatt: BluetoothGatt,
        descriptor: BluetoothGattDescriptor,
        status: Int,
        value: ByteArray
    ) {
        Log.i(TAG, "描述符${descriptor.uuid.toString()}读取")
        Log.i(TAG, "描述符值:${String(descriptor.value)}")
    }

    override fun onDescriptorWrite(
        gatt: BluetoothGatt?,
        descriptor: BluetoothGattDescriptor?,
        status: Int
    ) {
        Log.i(TAG, "描述符${descriptor?.uuid.toString()}写入")
    }

    override fun onReadRemoteRssi(gatt: BluetoothGatt?, rssi: Int, status: Int) {
        super.onReadRemoteRssi(gatt, rssi, status)
        //rssi值是蓝牙的信号值,离得越远信号越小
        Log.i(TAG, "蓝牙信号值:$rssi")
    }
}

val gatt: BluetoothGatt = bluetoothDevice.connectGatt(context, false, gattCallback)

5.读取特征值

 /**
   * 读取特征值,读取成功后将回调在BluetoothGattCallback的onCharacteristicRead方法中
   */
fun readCharacteristic(characteristic: BluetoothGattCharacteristic){
    //设置特征值变化通知,必须设置,否则无法监听特征值变化情况
    bluetoothGatt?.setCharacteristicNotification(characteristic, true)
    //读取特征值
    bluetoothGatt?.readCharacteristic(characteristic)
}

6.写入特征值

/**
  *  写入特征值,完成后将回调在BluetoothGattCallback的onCharacteristicWrite方法中
  */
fun writeCharacteristic(characteristic: BluetoothGattCharacteristic){
    bluetoothGatt?.writeCharacteristic(characteristic)
}

7.断开连接

fun disconnect(){
    bluetoothGatt?.disconnect()
    bluetoothGatt?.close()
}

8.分包

在Android BLE通信中,如果要发送的数据大小超过MTU(最大传输单元)的限制,就需要进行数据分包处理。BLE蓝牙一包数据最多为20字节,因此安卓系统下最好不要使用BLE蓝牙传输大量数据。以下是一种常见的方法来实现BLE数据分包发送:

(1)获取MTU大小:首先,通过调用BluetoothGatt对象的requestMtu()方法来请求MTU大小,例如:

val mtu = 20// 设置期望的MTU大小
bluetoothGatt.requestMtu(mtu)

注意:requestMtu设置不一定会成功,每个版本的蓝牙都有不同的最大值,设置时尽量小一点,一般在onConnectionStateChange中判断连接设备成功后调用这个方法,然后再去搜索Service

(2)监听MTU更新:在BluetoothGattCallback中的onMtuChanged()回调方法中处理MTU更新结果:

override fun onMtuChanged(gatt: BluetoothGatt, mtu: Int, status: Int) {
    if (status == BluetoothGatt.GATT_SUCCESS) {
        // MTU更新成功,可以开始发送数据
        sendData(bluetoothGatt, data, mtu)
    } else {
        // MTU更新失败,处理失败逻辑
    }
}

(3)数据分包发送:根据MTU大小将要发送的数据拆分成多个分包,并通过BluetoothGattCharacteristicsetValue()writeCharacteristic()方法进行发送。以下是一个简单的示例:

/**
  * 往指定特征值写数据,分包
  */
fun sendData(characteristic: BluetoothGattCharacteristic, data: ByteArray, mtu: Int) {
    Thread {
        val packetSize = mtu - 3 // 减去3个字节的包头
        // 将数据拆分为分包并发送
        var offset = 0
        while (offset < data.size) {
        val packet = data.sliceArray(offset until minOf(offset + packetSize, data.size))
            characteristic?.value = packet
            bleClient?.bluetoothGatt?.writeCharacteristic(characteristic)
            offset += packet.size
        }
        Log.d(BleClient.TAG, "发送完毕..")
    }.start()
}

在这个示例中,我们使用MTU大小减去3个字节(包头),得到每个分包的大小。然后,将要发送的数据按照分包大小拆分成多个分包,并通过setValue()方法设置分包数据,再通过writeCharacteristic()方法发送分包。

需要注意的是,每个分包的大小应该小于或等于MTU减去3个字节。另外,数据的接收端也需要对分包进行合并和处理,以确保正确接收和还原原始数据。文章来源地址https://www.toymoban.com/news/detail-486715.html

到了这里,关于Android低功耗蓝牙(BLE)开发(二)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Android -BLE 蓝牙模块开发

    Android-Ble蓝牙开发Demo示例–扫描,连接,发送和接收数据,分包解包(附源码) - 简书 前言 万物互联的物联网时代的已经来临,ble蓝牙开发在其中扮演着举重若轻的角色。最近刚好闲一点,抽时间梳理下这块的知识点。 涉及ble蓝牙通讯的客户端(开启、扫描、连接、发送... https://

    2024年02月09日
    浏览(42)
  • windows+python+bleak+BLE低功耗蓝牙通讯连接

    1.为什么选bleak   参考这篇知乎:https://zhuanlan.zhihu.com/p/577687336   windows端使用python连接常规的BLE设备(蓝牙4.0),仅考虑bleak模块(排除pybluez、pybluez2、pygatt)。 2.本文主要参考   本文主要参考bleak的官方文档:https://github.com/hbldh/bleak 3.本文所用设备   应事先学习蓝

    2024年02月02日
    浏览(41)
  • 深入浅出蓝牙低功耗音频BLE Audio--4-3 CIS

            为了掌握核心规范中ISO新特性,先介绍单播且可连接的ISO流,即CIS,CIS的结构框架相当复杂,但是其建立在一些非常的原则之上。本节首先描述CIS如何被设计,解释组成模块如何配合工作,然后学习广播模式的不同之处,为学习蓝牙低功耗音频方案奠定基础。  

    2023年04月14日
    浏览(51)
  • 深入浅出蓝牙低功耗音频BLE Audio --4-2 ISO流和角色

    核心规范V5.2中增加ISO流特性是低功耗蓝牙协议中一个全新的概念。熟悉A2DP和HFP协议的读者都知道其拓扑结构局限不灵活。HFP具有双向一对一的链路,典型场景是电话和耳机或免提设备之间。A2DP是一个更简单的单播链路,定义Source设备产生音频数据,Sink设备通常是耳机,扬声

    2023年04月11日
    浏览(75)
  • 【STM32备忘录】【STM32WB系列的BLE低功耗蓝牙】一、测试广播配置搜不到信号的注意事项

    WB系列是双核单片机,用户写M4,无线协议栈使用M0 新买到手的单片机,需要自己刷入使用的无线协议栈 刷入无线协议栈的途径是通过一个叫FUS的东东,类似于bootloader,这个FUS新买的芯片通常已经刷好,但版本不一定是最新的(如果没有需要自己刷入) 刷入FUS和无线协议栈需要

    2024年03月16日
    浏览(55)
  • android 实现ble蓝牙自动配对连接

    蓝牙自动配对,即搜索到其它蓝牙设备之后直接进行配对,不需要弹出配对确认框或者密钥输入框。 本文章用来连接蓝牙设备ai-thinker,如果你要连接其他蓝牙设备,注意修改相关名字以及修改设备初试pin值。 将Demo安装在Android手机上,点击按钮,可以实现与目标蓝牙设备的

    2023年04月24日
    浏览(50)
  • Android Ble蓝牙App(一)扫描

      关于低功耗的蓝牙介绍我已经做过很多了,只不过很多人不是奔着学习的目的去的,拿着源码就去运行,后面又发现连接设备后马上断开,然后不会自己看问题,这个现象就是快餐式的,你不了解里面的知识内容,自然就不知道是怎么回事,重复的问题我回答了好多次了

    2024年02月08日
    浏览(39)
  • Android Ble蓝牙App(七)扫描过滤

      在上一篇文章中了解了MTU的相关知识以及对于设备操作信息的展示,本篇文章中将增加扫描设备的过滤功能让你更方便的扫描想要找的低功耗蓝牙设备。 Ble蓝牙App(一)扫描 Ble蓝牙App(二)连接与发现服务 Ble蓝牙App(三)特性和属性 Ble蓝牙App(四)UI优化和描述符 Bl

    2024年02月09日
    浏览(44)
  • Android Ble蓝牙App(五)数据操作

      关于低功耗蓝牙的服务、特性、属性、描述符都已经讲清楚了,而下面就是使用这些知识进行数据的读取、写入、通知等操作。 Ble蓝牙App(一)扫描 Ble蓝牙App(二)连接与发现服务 Ble蓝牙App(三)特性和属性 Ble蓝牙App(四)UI优化和描述符 Ble蓝牙App(五)数据操作  

    2024年02月13日
    浏览(43)
  • Android Ble蓝牙App(三)特性和属性

      在上一篇中我们完成了连接和发现服务两个动作,那么再发现服务之后要做什么呢?发现服务只是让你知道设备有什么服务,可以做什么事情。 Ble蓝牙App(一)扫描 Ble蓝牙App(二)连接与发现服务 Ble蓝牙App(三)特性和属性 Ble蓝牙App(四)UI优化和描述符 Ble蓝牙App(五

    2024年02月14日
    浏览(36)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包