如何通过读/写BLE Gatt特性实现最大的线程安全性? [英] How could i achieve maximum thread safety with a read/write BLE Gatt Characteristic?

查看:208
本文介绍了如何通过读/写BLE Gatt特性实现最大的线程安全性?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在与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;

  1. 创建一个HandlerThread
  2. 在您的HandlerThread
  3. 上创建一个Handler附件
  4. 将您的Handler传递到BluetoothDevice.connectGatt()中-恭喜,当收到通知时,setValue()onCharacteristicChanged()将会在您的HandlerThread上被调用.
  5. 要编写特征时,请通过处理程序将setValue()writeCharacteristic()发布到HandlerThread
  1. Create a HandlerThread
  2. Create a Handler attached to your HandlerThread
  3. Pass your Handler into BluetoothDevice.connectGatt() - congratulations, when a notify is received the setValue() and onCharacteristicChanged() will be called on your HandlerThread.
  4. When you want to write to the characteristic, post your setValue() and writeCharacteristic() to your HandlerThread 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆