Android如何连接已配对的Micro:Bit BBC设备并实现重连与特征读取
嗨,作为踩过不少BLE坑的Android开发者,太懂你现在的感受了——对着官方文档看半天,还是不知道从哪下手写代码!既然你已经能定位到配对好的Micro:Bit设备,那接下来的核心操作其实可以拆成三个关键环节,我给你一步步拆解,还补上你需要的核心代码片段:
第一步:建立BLE连接
首先,你手里应该已经有了配对设备对应的BluetoothDevice对象对吧?接下来要做的就是通过这个对象获取BluetoothGatt,并通过BluetoothGattCallback来监听所有连接、特征交互的状态。
先定义你的Gatt回调类,这是整个BLE交互的核心:
private val gattCallback = object : BluetoothGattCallback() { // 连接状态变化回调(成功/断开都会触发) override fun onConnectionStateChange(gatt: BluetoothGatt?, status: Int, newState: Int) { super.onConnectionStateChange(gatt, status, newState) when(newState) { BluetoothProfile.STATE_CONNECTED -> { // 连接成功!立刻开始发现设备的服务 gatt?.discoverServices() } BluetoothProfile.STATE_DISCONNECTED -> { // 连接断开,这里可以处理重连逻辑 handleReconnect(gatt) } } } // 服务发现完成回调 override fun onServicesDiscovered(gatt: BluetoothGatt?, status: Int) { super.onServicesDiscovered(gatt, status) if (status == BluetoothGatt.GATT_SUCCESS) { // 服务发现成功,现在可以找你要读取的特征了 findTargetCharacteristic(gatt) } } // 特征值读取完成回调 override fun onCharacteristicRead(gatt: BluetoothGatt?, characteristic: BluetoothGattCharacteristic?, status: Int) { super.onCharacteristicRead(gatt, characteristic, status) if (status == BluetoothGatt.GATT_SUCCESS && characteristic != null) { // 这里拿到特征值,比如Micro:Bit的温度是小端字节序,需要转换 val temperatureBytes = characteristic.value val temperature = ByteBuffer.wrap(temperatureBytes).order(ByteOrder.LITTLE_ENDIAN).short.toFloat() / 100f // 处理温度值,比如更新UI(注意要切回主线程) runOnUiThread { textViewTemperature.text = "当前温度:$temperature °C" } } } }
然后发起连接:
// 假设device是你找到的配对Micro:Bit设备 val gatt = device.connectGatt(this, false, gattCallback) // 第二个参数false表示不自动重连,如果需要后台自动重连可以设为true,但重连逻辑建议自己控制
第二步:实现断开后的自动重连
在上面的onConnectionStateChange回调里,当检测到STATE_DISCONNECTED时,你可以实现重连逻辑。这里要注意几个点:
- 不要立刻发起重连,最好加个延迟(比如1-3秒),避免频繁重试消耗资源
- 可以用
Handler或者Coroutine来实现延迟重连 - 如果是Android 12+,要确保你的APP有
BLUETOOTH_CONNECT权限
重连的核心代码示例:
private fun handleReconnect(gatt: BluetoothGatt?) { // 先关闭旧的Gatt连接,避免内存泄漏 gatt?.close() // 用Coroutine实现延迟重连(需要依赖kotlinx-coroutines-android) lifecycleScope.launch { delay(2000) // 重新发起连接,这里的device是你之前保存的配对设备对象 device.connectGatt(this@MainActivity, false, gattCallback) } }
另外,如果你希望APP在后台也能自动重连,可以考虑把connectGatt的第二个参数设为true(自动重连模式),但这种模式的重连时机由系统控制,灵活性不如自己实现的逻辑。
第三步:找到目标特征并读取值
Micro:Bit的BLE服务和特征都有固定的UUID,比如常见的环境温度特征,对应的服务UUID是E95D0753-251D-470A-A062-FA1922DFA9A8,特征UUID是E95D9250-251D-470A-A062-FA1922DFA9A8。你需要根据自己要读取的特征替换对应的UUID。
实现findTargetCharacteristic方法:
private fun findTargetCharacteristic(gatt: BluetoothGatt?) { gatt?.let { // 先找到对应的服务 val environmentService = it.getService(UUID.fromString("E95D0753-251D-470A-A062-FA1922DFA9A8")) environmentService?.let { service -> // 找到目标特征 val temperatureChar = service.getCharacteristic(UUID.fromString("E95D9250-251D-470A-A062-FA1922DFA9A8")) temperatureChar?.let { char -> // 读取特征值,注意BLE操作必须在子线程,这里connectGatt已经在子线程处理了,但保险起见可以确认 it.readCharacteristic(char) } } } }
几个新手必注意的坑
- 权限问题:Android 12+需要申请
BLUETOOTH_SCAN、BLUETOOTH_CONNECT权限,Android 11及以下需要ACCESS_FINE_LOCATION权限才能扫描设备(你已经配对了设备,可能不需要扫描,但连接还是要对应权限) - 主线程限制:所有BLE操作(连接、读写特征)都不能在主线程执行,
BluetoothGatt的回调默认在Binder线程,所以更新UI一定要切回主线程 - 资源释放:当不再需要连接时,一定要调用
gatt.close(),避免内存泄漏和占用BLE资源 - UUID大小写:Micro:Bit的UUID是小写的,注意不要写错大小写
内容的提问来源于stack exchange,提问作者Lechucico
相关产品推荐
相关产品推荐

