Android 5.1 上的多个 writeDescriptor() 调用失败
Posted
技术标签:
【中文标题】Android 5.1 上的多个 writeDescriptor() 调用失败【英文标题】:Multiple writeDescriptor() calls fail on Android 5.1 【发布时间】:2016-01-12 16:01:59 【问题描述】:我有一个与蓝牙低功耗血糖仪通信的应用程序。
目前我的应用程序在 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 毫秒、500 毫秒和 2 秒)进行第二次写入,以查看 mDeviceBusy 变量是否已清除...两次尝试均失败...
我用谷歌搜索了这个问题,但找不到任何东西,最接近的是这个未回答的问题:Android SensorTag: writeDescriptor failed
注意:如果需要我可以附上我的代码,但它非常简单,类似于这篇文章中的代码:Android BLE notifications for Glucose
【问题讨论】:
【参考方案1】:我发现了问题...在我的代码中,我错误地定义了 onDescriptorWrite() 回调。修复此问题后,我在编写描述符成功时设法接收回调。
解决了这个问题,我找到的解决方案是通过创建一个负责对操作进行排序的类来阻止 BTLE 操作。
我创建的类非常简单,一个单独线程上的 BlockingQueue 用于对传入操作进行排队。
BTLE 操作通过调用 writeDescriptor()、writeCharacteristic() 方法入队,一个单独的线程在空闲时开始执行操作,并且当操作完成时 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();
定义蓝牙回调时:
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();
【讨论】:
以上是关于Android 5.1 上的多个 writeDescriptor() 调用失败的主要内容,如果未能解决你的问题,请参考以下文章
有啥办法可以在 Mac 上的 android studio 3.5.1 中修复这个错误