【发布时间】:2016-08-12 16:27:53
【问题描述】:
我正在与通过一个特性向我发送大量数据的 BLE 设备通信。相同的 Characteristic 用于向设备发送数据。
在Androids BluetoothGattCharacteristic里面有方法
public byte[] getValue() {
return mValue;
}
public boolean setValue(byte[] value) {
mValue = value;
return true;
}
但是,执行发生在不同的线程中。 Android 运行大约 5 个不同的活页夹线程,它们调用
onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic)
我现在尝试获取数组作为回调中的第一个操作,但不能保证另一个线程(不受我控制)同时设置数组。
虽然上述方法似乎可以解决问题,但更复杂的问题是“针对传入的数据流”发送数据。
我必须使用相同的特性将数据向下发送到设备,所以我先setValue(),然后BluetoothGatt.writeCharacteristic。
public boolean writeCharacteristic(BluetoothGattCharacteristic characteristic) {
// some null checks etc
//now it locks the device
synchronized(mDeviceBusy) {
if (mDeviceBusy) return false;
mDeviceBusy = true;
}
//the actual execution
return true;
}
然后我会在某个时候收到来自某个线程的回调
onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status)
但是,当我获取该值并尝试检查它是否是我想要发送的内容时,有时它已经是一个刚刚从其他线程更新的接收包。
如何在不访问 Android BLE API 或堆栈等的情况下使其更加线程安全?
【问题讨论】:
-
非常好的问题。我只能说,当我几年前测试这个时(但只在一个方向:通知)我测试了在 onCharacteristicChanged 处理程序中做一个线程睡眠,发现它实际上一次只做一个回调,即它等待为了完成直到下一个被调用。尽管我注意到回调总是在不同的线程上。
-
据我在 BluetoothGatt 源代码中看到的,导致 onCharacteristicChanged 的 onNotify 不查看 mDeviceBusy 锁,只是覆盖删除任何全双工功能的特征值
-
我发现“Binder”机制确保每个 BluetoothGatt 对象一次只执行一个回调。这意味着不存在获取通知流的问题。但是,如果从另一个线程完成写入并且在同一特性上同时收到通知,则仍然存在竞争条件。
-
而正是这种竞争条件才是危险的。我只是无法确定我发送/接收的内容是否真实,或者它是否是我在收到内容时刚刚写入缓冲区的内容。
-
有人解决了这个问题吗?
标签: android multithreading bluetooth-lowenergy