我们正在执行以下过程来与BLE设备配对。
Connect()+ discoverServices()+ Pairing(Bonding)。
有时,Android操作系统会以一种怪异的方式使我们的BT设备无法配对,即:
设备成功配对后,ACTION_BOND_STATE进行如下更改。
[6:19:28 PM] Himen Patel:04-09 18:18:27.325:D/BluetoothGatt(8380):onCharacteristicWrite()-设备= C2:69:E9:57:93:A4 UUID = 860b2c07-e3c5- 11e2-a28f-0800200c9a66状态= 5
04-09 18:18:27.365:E/millisUntilFinished(8380):millisUntilFinished = 15
04-09 18:18:28.105:E/BelwithDeviceActor(8380):绑定(bind)状态已更改为:C2:69:E9:57:93:A4新状态:11上一个:10
04-09 18:18:28.105:E/millisUntilFinished(8380):millisUntilFinished = 20
04-09 18:18:29.135:E/millisUntilFinished(8380):millisUntilFinished = 18
04-09 18:18:30.135:E/millisUntilFinished(8380):millisUntilFinished = 17
04-09 18:18:31.145:E/millisUntilFinished(8380):millisUntilFinished = 16
04-09 18:18:32.145:E/millisUntilFinished(8380):millisUntilFinished = 15
04-09 18:18:33.105:D/BluetoothGatt(8380):onCharacteristicWrite()-设备= C2:69:E9:57:93:A4 UUID = 032a0000-0000-0000-0000-0000-000000000000 Status = 137
04-09 18:18:33.115:E/BelwithDeviceActor(8380):绑定(bind)状态已更改为:C2:69:E9:57:93:A4新状态:12上一个:11
04-09 18:18:33.115:I/System.out(8380):unregisterReceiver true
现在,当操作系统以怪异的方式删除配对时,ACTION_BOND_STATE会进行如下更改。
。
。
。
。
绑定(bind)状态已更改为:C2:69:E9:57:93:A4新状态:10。
我们还会在我们的APP中获得act = android.bluetooth.device.action.ACL_DISCONNECTED flg = 0x4000010的即时事件。
这里重要,在这一点上,我们刚刚失去了配对与设备和保护特性为我们做的工作没有任何更长的时间。
如果我们使用系统设置app或BluetoothAdapter::disable()和enable()重新启动bt,则可以看到我们没有与设备配对。
有趣的是,在未重启bt的情况下,系统设置应用仍会认为并表明我们已与设备配对。
已在运行4.4.2的nexus 4,运行4.4.2的nexus 5以及运行4.3的Samsung galaxy s4上进行了测试。
我们的期望是:
我们还观察到并获取了嗅探到的数据,在这些数据中,当操作系统以奇怪的方式删除了绑定(bind)时,我们的加密设置为0x000000。
最佳答案
我不知道您是否仍然需要帮助,或者您是否最终解决了自己的问题(您知道,因为您确实在4月份发布了此问题),但是我想继续发布我提出的解决方法,因为我知道其他人们有这个问题。
使用Nexus 7,我进行了与您基本相同的测试,并得出了相同的结论:
如果Android平板电脑和远程设备已经绑定(bind),则很有可能调用BluetoothGatt.discoverServices()会断开平板电脑并将其与远程设备解除绑定(bind)。但是,Android OS的某些部分似乎完全没有考虑这种解除绑定(bind);尽管您注册以监听绑定(bind)更改的广播接收器收到通知,表明两个设备之间的绑定(bind)已断开,但其他Android操作系统仍认为该绑定(bind)仍然完好无损。由于操作系统认为平板电脑和远程设备已绑定(bind),因此无论何时尝试写入描述符,平板电脑都无法写入远程设备上的任何加密描述符,写入状态为15(GATT_INSUFFICIENT_ENCRYPTION)。
解决方案
关键是先取消Nexus和远程设备的配对,再将取消配对,然后才有可能以这种奇怪的方式取消配对。我要做的是在我开始进行蓝牙低功耗扫描之前,检查平板电脑和远程设备是否已绑定(bind)。如果它们配对,则使用下面的功能删除键,然后开始扫描。以编程方式取消配对这两个设备可确保Android OS知道它们不再绑定(bind),因此将通过通常的绑定(bind)过程进行操作。
下面的代码用于检查远程设备是否与平板电脑配对,如果配对,则取消配对:
// Get the paired devices and put them in a Set
BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices();
// Loop through the Set of paired devices, checking to see
// if one of the devices is the device you need to unpair
// from. I use the device name, but I'm sure you can find
// another way to determine whether or not its your device
// -- if you need to. :)
for (BluetoothDevice bt : pairedDevices) {
if (bt.getName().contains("String you know has to be in device name")) {
unpairDevice(bt);
}
}
// Function to unpair from passed in device
private void unpairDevice(BluetoothDevice device) {
try {
Method m = device.getClass().getMethod("removeBond", (Class[]) null);
m.invoke(device, (Object[]) null);
} catch (Exception e) { Log.e(TAG, e.getMessage()); }
}
为什么等待错误然后通过重新启动蓝牙解决错误是一个坏主意...
正如您已经在问题中指出的那样,在平板电脑和远程设备神秘地彼此解除绑定(bind)之后,重新启动蓝牙会迫使Android OS意识到它不再与远程设备绑定(bind)。这是我最初使用的解决方法,但很快就发现此“解决方案”存在两个主要问题:
作为最后的选择,我只会重启蓝牙。例如,如果仍然奇迹般地发生了解除绑定(bind)错误,那么您唯一的选择就是重启蓝牙。