我们正在进行以下处理与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() - Device = 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):债券状态改为: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() - Device = C2:69:E9:57:93:A4 UUID = 032a0000-0000-0000-0000-000000000000 Status = 137 04-09 18:18:33.115:E / BelwithDeviceActor(8380):债券状态改为:C2:69:E9:57:93:A4新状态:12上一个:11
04-09 18:18:33.115:I / System.out(8380):unregisterReceiver true
现在,当操作系统以奇怪的方式删除配对时,ACTION_BOND_STATE会发生如下变化。 。 。 。 。 债券状态改为:C2:69:E9:57:93:A4新州:10。
我们也在我们的APP中立即获得了act = android.bluetooth.device.action.ACL_DISCONNECTED flg = 0x4000010的事件。
这里有什么重要的,在这一点上,我们失去了与设备的配对,受保护的特性不再为我们工作。 如果我们使用系统设置应用程序或BluetoothAdapter :: disable()和enable()重新启动bt,我们可以看到我们没有与设备配对。
有趣的是,如果没有重启,系统设置应用程序仍会认为并显示我们已与设备配对。
使用运行4.4.2的nexus 4,运行4.4.2的nexus 5以及运行4.3的三星galaxy s4进行测试。
我们的期望是:
我们还观察并获取了嗅探数据,我们发现当操作系统以奇怪的方式删除我们的绑定时,我们的加密设置为0x000000。
答案 0 :(得分:11)
我不知道你是否还需要帮助,或者你是否最终解决了自己的问题(你知道,因为你在四月份发布了这个问题),但我想继续发布我提出的解决方法,因为我知道其他人都有这个问题。
使用Nexus 7,我运行的测试基本相同,得出了相同的结论: 如果Android平板电脑和远程设备已经绑定,那么调用BluetoothGatt.discoverServices()的机会很可能会断开和取消平板电脑与远程设备的连接。但是,Android操作系统的某些部分似乎完全忘记了没有绑定;虽然您注册监听绑定更改的广播接收器被通知两个设备之间的绑定已被破坏,但其他Android操作系统认为绑定仍然完好无损。由于操作系统认为平板电脑和远程设备需要绑定,因此平板电脑无法写入远程设备上的任何加密描述符,每当尝试描述符写入时,写入状态为15(GATT_INSUFFICIENT_ENCRYPTION)。
解决方案
关键是要取消配对Nexus和远程设备之前他们有机会以这种奇怪的方式取消配对。我所做的是在开始蓝牙低功耗扫描之前检查平板电脑和远程设备是否正确绑定。如果它们已配对,我使用下面的功能删除粘合,然后开始扫描。以编程方式取消配对这两个设备可确保Android操作系统意识到它们已不再绑定,因此将经历通常的绑定过程。
以下代码用于检查远程设备是否与平板电脑配对,如果是,则取消配对:
// 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()); }
}
为什么要等待错误然后通过重新启动蓝牙来解决它是一个坏主意......
正如您在问题中已经指出的那样,在平板电脑和远程设备相互神奇地脱钩之后重新启动蓝牙会迫使Android操作系统意识到它已不再与远程设备绑定。这是我使用的原始解决方法,但很快就发现这个“解决方案”带来了两个主要问题:
我只会重新启动蓝牙作为最后的手段。例如,如果仍然奇迹般地发生了未绑定错误,那么您唯一的选择就是重新启动蓝牙。
答案 1 :(得分:0)
我们遇到了同样的问题,我们已经发现“connectGatt”有一个新的“传输”参数(它定义了连接的传输协议),从SDK v 23开始。 因此,如果您想要配对设备,则应使用“TRANSPORT_BREDR”,如果您只想连接到外围设备而不进行绑定 - 请使用“TRANSPORT_LE” 文档:https://developer.android.com/reference/android/bluetooth/BluetoothDevice.html#connectGatt(android.content.Context,boolean,android.bluetooth.BluetoothGattCallback,int)