使用 Android 12 设备进行测试时,每当我的蓝牙设备断开连接时,无论我是以编程方式断开连接还是设备超出范围,我都会收到状态 0。根据我对以前 Android 版本的理解,状态 0 是以编程方式断开连接,状态 8 表示设备超出范围。
return object : BluetoothGattCallback() {
override fun onConnectionStateChange(gatt: BluetoothGatt, status: Int, newState: Int) {
val name = gatt.device.name
Log.i("onConnectionStateChange", name + "\t" + status + "\t" + newState)
when (newState) {
BluetoothGatt.STATE_CONNECTED -> {
gatt.discoverServices()
}
BluetoothGatt.STATE_CONNECTING -> {
}
BluetoothGatt.STATE_DISCONNECTED -> {
}
BluetoothGatt.STATE_DISCONNECTING -> {
// status 0 (Programmatically disconnected)
if (status == BluetoothGatt.GATT_SUCCESS) {
// Always going in here
...
}
// Deivce went out of range
else if(status == 8){
// Never in here
...
}
}
}
}
override fun onServicesDiscovered(gatt: BluetoothGatt?, status: Int) {
super.onServicesDiscovered(gatt, status)
}
}
是否有人面临同样的问题并弄清楚如何正确显示状态或找到另一种方法来确定设备是否超出范围或以编程方式断开连接?
我确认您对 Android 12 的说法:在 BLE 断开连接时,传入
onConnectionStateChange()
的状态参数值为 0(即 BluetoothGatt.GATT_SUCCESS
),无论断开连接是通过编程方式完成还是因为设备超出范围或关闭电动下降。
与以前的 Android 版本相比,这是一个缺点,当设备超出范围(或被电气关闭)时,它会传递状态 8
(0x08 = GATT CONN TIMEOUT)
,而当以编程方式成功关闭连接时,会传递状态 0。
不幸的是,在 Android 12 更新后,我在 Pixel 3 上也出现了同样的行为,这有点令人难过。他们有意或无意地改变了这一点。在任何情况下,状态代码应包含的内容都没有在任何地方记录,除了如果“操作成功”则应使用 GATT_SUCCESS (0),而没有定义“成功”的含义。我认为您应该向 AOSP 提交错误报告。
更新2023-12-04:
在 Android 14 中,Google 已修复此问题。 OnePlus(可能还有其他公司)已经在后来的一些 Android 13 安全更新中修复了这个问题。
原答案:
这是 Android 12、12L 和 13 DP 上的常见问题/更改:( 我已就此问题向 AOSP 提交了错误报告,但 Google 并未提供任何反馈。 https://issuetracker.google.com/issues/207323675
如果您查看 HCI 日志,您仍然可以看到断开连接的原因,但您也发现它不再传递给应用程序。 直接连接超时时状态=133 除外。
那么也许谷歌已经开始清理内部状态代码(如 133)与 BLE 断开原因混合的混乱情况? 那么问题当然是:哪里可以找到断开连接的原因?