我有一个与蓝牙低功耗血糖仪通信的应用程序。
目前,我的应用在Android 4.4.4上运行正常,但在5.1.1上失败
调试我发现执行多次以上时,writeDescriptor()方法失败...
使用调试器,我进入了writeDescriptor()方法,发现它在此行失败:
public boolean writeDescriptor(BluetoothGattDescriptor descriptor) {
...
synchronized(mDeviceBusy) {
if (mDeviceBusy) return false;
mDeviceBusy = true;
}
(BluetoothGatt.java:1029)
我尝试等待onDescriptorWrite()回调,但从未调用过,并且还尝试等待(100 ms,500ms和2s)进行第二次写入,以查看是否已清除mDeviceBusy变量。 ..两次尝试都失败了...
我在问题上用Google搜索,但找不到任何内容,最接近的是这个未回答的问题:Android SensorTag: writeDescriptor failed
注意:如有必要,我可以附加我的代码,但是它非常简单,类似于本文中的代码:Android BLE notifications for Glucose
最佳答案
我发现了问题...在我的代码中,我错误地定义了onDescriptorWrite()回调。解决此问题后,成功编写描述符时我设法接收了回调。
解决了这个问题之后,我发现的解决方案是通过创建一个负责对操作进行排序的类来阻止BTLE操作。
我创建的类非常简单,在一个单独的线程上使用BlockingQueue来排队传入的操作。
通过调用writeDescriptor(),writeCharacteristic()方法使BTLE操作入队,一个单独的线程在空闲时开始执行操作,并且gattCallback在操作完成后通知线程,以便继续进行下一个操作。
队列类:
public BtleAsynchronousOperationThread(SensorAbstract sensor, BluetoothGatt gatt) {
log("Creating Btle Operation thread");
this.gatt = gatt;
this.sensor = sensor;
}
public void enable() {
log("Enabling btle command thread");
queueReadySemaphore.release();
}
public void writeDescriptor(BluetoothGattDescriptor descriptor) throws BTCommunicationException {
BtleAsynchronousCommand command = new BtleAsynchronousCommand(descriptor);
try {
queue.put(command);
} catch (InterruptedException e) {
throw new BTCommunicationException("Error while writing the descriptor");
}
}
public void writeCharacteristic(BluetoothGattCharacteristic characteristic) throws BTCommunicationException {
BtleAsynchronousCommand command = new BtleAsynchronousCommand(
BtleAsynchronousCommand.CommandType.WRITE_CHARACTERISTIC, characteristic);
try {
queue.put(command);
} catch (InterruptedException e) {
throw new BTCommunicationException("Error while writing the characteristic");
}
}
public void readCharacteristic(BluetoothGattCharacteristic characteristic) throws BTCommunicationException {
BtleAsynchronousCommand command = new BtleAsynchronousCommand(
BtleAsynchronousCommand.CommandType.READ_CHARACTERISTIC, characteristic);
try {
queue.put(command);
} catch (InterruptedException e) {
throw new BTCommunicationException("Error while reading the characteristic");
}
}
public void cancel() {
this.interrupt();
}
public void writeCompleted() {
queueReadySemaphore.release();
}
@Override
public void run() {
BtleAsynchronousCommand command;
try {
while (!(Thread.currentThread().isInterrupted())) {
queueReadySemaphore.acquire();
log("Waiting for BTLE command");
command = queue.take();
switch (command.getCommandType()) {
case WRITE_DESCRIPTOR:
log("Starting to write descriptor:" + command.getDescriptor().getUuid());
if (!gatt.writeDescriptor(command.getDescriptor())) {
throw new BTCommunicationException("Error while writing the descriptor");
}
break;
case WRITE_CHARACTERISTIC:
log("Starting to write characteristic:" + command.getCharacteristic().getUuid());
if (!gatt.writeCharacteristic(command.getCharacteristic())) {
throw new BTCommunicationException("Error while writing the characteristic");
}
break;
case READ_CHARACTERISTIC:
log("Starting to read characteristic:" + command.getCharacteristic().getUuid());
if (!gatt.readCharacteristic(command.getCharacteristic())) {
throw new BTCommunicationException("Error while writing the characteristic");
}
break;
default:
log("Unknown command received");
break;
}
}
} catch (InterruptedException e) {
log("Btle thread interrupted, closing.");
} catch (BTCommunicationException e) {
log("Error while reading:" + e.getMessage());
sensor.retry();
}
gatt = null;
queue = null;
queueReadySemaphore = null;
Thread.currentThread().interrupt();
}
}
定义BluetoothCallback时:
mGattCallback = new BluetoothGattCallback() {
//Other methods can be defined around here, such as
//onConnectionStateChange(), etc
@Override
public void onCharacteristicChanged(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic) {
onSensorCharacteristicChangedInner(gatt, characteristic);
}
@Override
public void onDescriptorWrite (BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status){
log("onDescriptorWrite:"+descriptor.getUuid()+ " status:"+status);
btleCommunicationThread.writeCompleted();
}
@Override
public void onCharacteristicWrite(BluetoothGatt gatt,BluetoothGattCharacteristic characteristic, int status) {
log("onCharacteristicWrite:"+characteristic.getUuid()+ " status:"+status);
btleCommunicationThread.writeCompleted();
}