如何通过读/写BLE Gatt特性实现最大的线程安全性? [英] How could i achieve maximum thread safety with a read/write BLE Gatt Characteristic?
问题描述
我正在与BLE设备通信,该设备通过一个特征向我发送大量数据.相同的CH用于将数据发送到设备.
I am communicating with a BLE device that sends me lots of data via one characteristic. The same CH is used to send data to the device.
在Android内部BluetoothGattCharacteristic
中有方法
Inside Androids BluetoothGattCharacteristic
there are the methods
public byte[] getValue() {
return mValue;
}
public boolean setValue(byte[] value) {
mValue = value;
return true;
}
但是,执行是从不同的线程进行的. Android运行大约5种不同的绑定线程,它们调用
However, the execution happens from different threads. Android runs about 5 different binder-threads and they call
onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic)
我现在尝试将数组作为回调中的第一个操作,但不能保证另一个线程(不在我的控制之下)正在同时设置数组.
I now try to grab the array as first operation in the callback, but it is NOT guaranteed that another thread (not under my control) is setting the array at the same time.
虽然上面的方法似乎可以解决问题,但更复杂的事情是针对传入的数据流"发送数据.
While above seems to do the trick, a more complicated matter is sending data 'against an incoming stream of data'.
我必须使用相同的CH将数据向下发送到设备,所以我setValue()
然后是BluetoothGatt.writeCharacteristic
.
I have to use the same CH to send data down to the device, so i setValue()
and then 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;
}
然后我会在某个时候收到某个线程的回叫
I will then at some point receive a callback from some thread
onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status)
但是,当我获取值并尝试检查它是否是我要发送的内容时,有时它已经是一个刚刚从其他线程更新过的已接收包.
However, when i grab the value and try to check if it is what i wanted to send, sometimes it already is a received package that has just been updated from some other thread.
如何在不访问Android BLE API或堆栈等的情况下使它更具线程安全性?
How could i make this more thread-safe without having access to Androids BLE API or the stack etc ?
推荐答案
在SDK27中, BluetoothGatt.java 中的onNotify()
回调函数已更新为调用BOTH < Runnable的 run()
中的c5>和BluetoothGattCallback.onCharacteristicChanged()
.
In SDK27, the onNotify()
callback function in BluetoothGatt.java was updated to call BOTH BluetoothGattCharacteristic.setValue()
and BluetoothGattCallback.onCharacteristicChanged()
in the Runnable's run()
.
此更改使我们能够将对BluetoothGattCharacteristic.setValue()
的所有调用(用于我们向特征的出站写入和入站通知)强制到同一线程上,从而消除了竞争条件破坏了BluetoothGattCharacteristic.mValue
;
This change allows us to force all calls to BluetoothGattCharacteristic.setValue()
- both for our outbound writing to the characteristic and the inbound notifications - onto the same thread, which eliminates the race condition corrupting the BluetoothGattCharacteristic.mValue
;
- 创建一个
HandlerThread
- 在您的
HandlerThread
上创建一个 - 将您的
Handler
传递到BluetoothDevice.connectGatt()
中-恭喜,当收到通知时,setValue()
和onCharacteristicChanged()
将会在您的HandlerThread
上被调用. - 要编写特征时,请通过处理程序将
setValue()
和writeCharacteristic()
发布到HandlerThread
Handler
附件
- Create a
HandlerThread
- Create a
Handler
attached to yourHandlerThread
- Pass your
Handler
intoBluetoothDevice.connectGatt()
- congratulations, when a notify is received thesetValue()
andonCharacteristicChanged()
will be called on yourHandlerThread
. - When you want to write to the characteristic, post your
setValue()
andwriteCharacteristic()
to yourHandlerThread
via your Handler
现在,竞争条件中涉及的所有函数调用都在同一线程上执行,从而消除了竞争条件.
Now all the function calls that were involved in the race condition are being executed on the same thread, eliminating the race condition.
这篇关于如何通过读/写BLE Gatt特性实现最大的线程安全性?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!