使用RxAndroidBle读取特征时触发GATT 137异常的原因排查
首先,GATT状态码137(0x89)对应的通常是权限不足或连接状态不稳定相关的问题,结合你的代码和异常信息,我整理了几个可能的原因和对应的解决思路:
可能的原因及解决方案
1. 目标特征需要认证/授权才能读取
很多BLE设备会对敏感特征设置访问权限,要求连接必须经过配对、绑定或者加密,否则会返回权限相关的GATT错误。比如有些设备的只读特征需要先完成配对,并且在加密连接下才能读取。
解决思路:
- 先确保设备已经和手机完成配对(在系统蓝牙设置里确认配对状态);
- 建立连接时明确启用加密,RxAndroidBle中可以通过配置连接参数实现,或者在连接前触发配对流程;
- 使用
device.establishConnection(false)时,确保连接是加密的(部分设备会自动触发加密,但有些需要手动处理)。
2. 连接状态判断存在竞态条件
你的代码中直接判断device.connectionState == CONNECTED,但RxAndroidBle的连接状态是异步更新的——当你执行到readCharacteristic时,连接可能已经断开或者处于不稳定状态,导致读取失败。这种状态判断的窗口问题在异步操作中很常见。
解决思路:
改用RxJava的流式操作来管理连接和读取,让RxAndroidBle自动处理连接生命周期,避免手动判断状态:
device.establishConnection(false) // false表示不自动重连,根据需求调整 .flatMap { connection -> connection.readCharacteristic(ConstantsBle.deviceUUIDCharacteristic) } .subscribe( { characteristic -> Log.e(TAG, "read characteristic task is success: ${characteristic.value}") }, { error -> error.printStackTrace() } )
这种方式会确保在连接稳定的情况下执行读取操作,连接断开时会自动触发错误回调。
3. 特征UUID错误或特征不支持读操作
有可能你使用的ConstantsBle.deviceUUIDCharacteristic和设备实际提供的特征UUID不匹配,或者该特征本身不支持读操作(特征的属性中没有READ权限)。
解决思路:
- 使用BLE调试工具(比如nRF Connect)扫描目标设备,确认特征的UUID和属性,确保你要读取的特征确实具备
READ权限; - 核对代码中的UUID是否和设备端的一致(注意UUID的大小写、短UUID和长UUID的转换)。
4. Android蓝牙栈或设备兼容性问题
部分旧版本的Android系统蓝牙栈存在bug,或者目标BLE设备和手机的蓝牙芯片兼容性不好,也会出现这种“非预期”的GATT错误(状态码137也被定义为GATT_ERROR_UNLIKELY,即非预期错误)。
解决思路:
- 重启手机蓝牙和目标设备,重新连接尝试;
- 测试其他Android设备看是否出现同样问题,排查是设备端还是手机端的问题;
- 尝试更新手机系统到最新版本,修复蓝牙栈的已知bug。
你的代码片段和异常信息
代码片段:
if (device.connectionState == RxBleConnection.RxBleConnectionState.CONNECTED) { rxConnection.readCharacteristic(ConstantsBle.deviceUUIDCharacteristic) .subscribe( { Log.e(TAG, "read characteristic task is success") }, { it.printStackTrace() } ) }
异常详情:
W/System.err: com.polidea.rxandroidble.exceptions.BleGattCharacteristicException: GATT exception from MAC address 0C:F3:EE:2A:ED:49, status 137, type BleGattOperation{description='CHARACTERISTIC_READ'}. (Look up status 0x89 here https://android.googlesource.com/platform/external/bluetooth/bluedroid/+/android-5.1.0_r1/stack/include/gatt_api.h )
W/System.err: at com.polidea.rxandroidble.internal.connection.RxBleGattCallback.propagateErrorIfOccurred(RxBleGattCallback.java:227)
W/System.err: at com.polidea.rxandroidble.internal.connection.RxBleGattCallback.access$800(RxBleGattCallback.java:32)
W/System.err: at com.polidea.rxandroidble.internal.connection.RxBleGattCallback$2.onCharacteristicRead(RxBleGattCallback.java:108)
at android.bluetooth.BluetoothGatt$1.onCharacteristicRead(BluetoothGatt.java:286)
W/System.err: at android.bluetooth.IBluetoothGattCallback$Stub.onTransact(IBluetoothGattCallback.java:117)
W/System.err: at android.os.Binder.execTransact(Binder.java:565)
内容的提问来源于stack exchange,提问作者yusufonderd

