如何通过读/写BLE Gatt特性实现最大线程安全性?

Nik*_*kyD 9 multithreading android bluetooth-lowenergy

我正在与BLE设备通信,该设备通过一个特征向我发送大量数据.相同的CH用于向设备发送数据.

在机器人内部BluetoothGattCharacteristic有方法

public byte[] getValue() {
    return mValue;
}

public boolean setValue(byte[] value) {
    mValue = value;
    return true;
}
Run Code Online (Sandbox Code Playgroud)

但是,执行发生在不同的线程中.Android运行大约5个不同的绑定线程,他们调用

onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic)

我现在尝试在回调中抓取数组作为第一个操作,但不能保证另一个线程(不在我的控制下)同时设置数组.

虽然上面似乎可以解决这个问题,但更复杂的问题是针对传入的数据流发送数据.

我必须使用相同的CH将数据发送到设备,所以我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;
}
Run Code Online (Sandbox Code Playgroud)

然后我会在某个时候从某个线程接收回调

onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) 
Run Code Online (Sandbox Code Playgroud)

但是,当我抓住该值并尝试检查它是否是我想要发送的内容时,有时它已经是一个刚刚从其他线程更新的已接收包.

如果不访问Androids BLE API或堆栈等,我怎样才能使这更安全?

小智 3

在 SDK27 中,BluetoothGatt.javaonNotify()中的回调函数已更新为同时调用Runnable.BluetoothGattCharacteristic.setValue()BluetoothGattCallback.onCharacteristicChanged() run()

此更改允许我们将所有调用BluetoothGattCharacteristic.setValue()(无论是对特征的出站写入还是入站通知)强制到同一线程上,从而消除了破坏 ; 的竞争条件BluetoothGattCharacteristic.mValue

  1. 创建一个HandlerThread
  2. 创建一个Handler附件到您的HandlerThread
  3. 将您的信息传递HandlerBluetoothDevice.connectGatt()- 恭喜,当收到通知时setValue()onCharacteristicChanged()将在您的 上调用HandlerThread
  4. 当您想写入特征时,请通过您的处理程序将您的setValue()和发送writeCharacteristic()给您HandlerThread

现在,竞争条件中涉及的所有函数调用都在同一线程上执行,从而消除了竞争条件。