调用readCharacteristic后BLE的onCharacteristicRead回调未触发求助
解决BLE特征读取成功但onCharacteristicRead回调不触发的问题
以下是针对你遇到的问题的排查方向和解决方案:
1. 检查onCharacteristicRead的方法签名
Android BLE回调在不同API版本中有参数差异:
- API 33及以上,回调方法新增
value: ByteArray参数 - API 33以下,方法无
value参数,需从characteristic.getValue()获取数据
如果你的应用兼容低版本系统,或测试设备系统版本低于API 33,系统会调用不带value的旧版方法,而你未重写该方法就会导致回调无法触发。建议同时兼容两个版本的回调:
private val gattCallback = object: BluetoothGattCallback() { // 兼容API 33+ override fun onCharacteristicRead( gatt: BluetoothGatt, characteristic: BluetoothGattCharacteristic, value: ByteArray, status: Int ) { handleReadResult(gatt, characteristic, value, status) } // 兼容API 33以下 override fun onCharacteristicRead( gatt: BluetoothGatt?, characteristic: BluetoothGattCharacteristic?, status: Int ) { gatt?.let { g -> characteristic?.let { c -> handleReadResult(g, c, c.value ?: byteArrayOf(), status) } } } private fun handleReadResult( gatt: BluetoothGatt, characteristic: BluetoothGattCharacteristic, value: ByteArray, status: Int ) { Log.i("Callback", "onCharacteristicRead") with(characteristic) { when (status) { BluetoothGatt.GATT_SUCCESS -> { Log.i("BluetoothGattCallback", "Read characteristic $uuid:\n${value.toHexString()}") } BluetoothGatt.GATT_READ_NOT_PERMITTED -> { Log.e("BluetoothGattCallback", "Read not permitted for $uuid!") } else -> { Log.e("BluetoothGattCallback", "Characteristic read failed for $uuid, error: $status") } } } } }
2. 确认特征对象与当前Gatt实例匹配
确保lpnInfoChar是从当前连接的btGatt实例中获取的,而非旧连接缓存的对象。每次重新连接后,需在onServicesDiscovered回调中重新获取服务和特征:
override fun onServicesDiscovered(gatt: BluetoothGatt?, status: Int) { super.onServicesDiscovered(gatt, status) if (status == BluetoothGatt.GATT_SUCCESS) { val targetService = gatt?.getService(UUID.fromString("你的自定义服务UUID")) lpnInfoChar = targetService?.getCharacteristic(UUID.fromString("你的自定义特征UUID")) } }
3. 重置BLE连接
有时Android系统的BLE操作队列会出现隐性阻塞,即便无可见未处理请求。可尝试断开并重新连接后再读取:
fun resetConnectionAndRead() { btGatt?.let { gatt -> gatt.disconnect() gatt.close() } // 重新扫描连接设备,完成后调用readOneSpecificCharacteristic() }
4. 取消特征通知(若已订阅)
部分BLE设备在特征被订阅通知后,会优先响应通知而非读取请求。可先取消通知再尝试读取:
fun cancelNotifyAndRead() { btGatt?.setCharacteristicNotification(lpnInfoChar, false) val descriptor = lpnInfoChar?.getDescriptor(UUID.fromString("00002902-0000-1000-8000-00805f9b34fb")) descriptor?.let { desc -> desc.value = BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE btGatt?.writeDescriptor(desc) } // 等待Descriptor写入完成后,调用readOneSpecificCharacteristic() }
内容的提问来源于stack exchange,提问作者K K
相关产品推荐
相关产品推荐

