Android 5.1上的多个writeDescriptor()调用失败

时间:2016-01-12 16:01:59

标签: android bluetooth bluetooth-lowenergy gatt android-5.1.1-lollipop

我有一个与蓝牙低能量血糖仪通信的应用程序。

目前我的应用程序在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变量被清除......两次尝试都失败了......

我搜索了这个问题但找不到任何内容,最接近的问题是这个未得到解答的问题:Android SensorTag: writeDescriptor failed

注意:我可以在必要时附加我的代码,但它非常简单,与此帖子中的代码类似:Android BLE notifications for Glucose

1 个答案:

答案 0 :(得分:4)

我发现了问题...在我的代码中,我错误地定义了onDescriptorWrite()回调。修复此问题后,我成功地在编写描述符时收到了回调。

解决了这个问题后,我发现解决方案是通过创建一个负责操作排序的类来阻止BTLE操作。

我创建的类非常简单,在一个单独的线程上阻塞传入操作的BlockingQueue。

BTLE操作通过调用writeDescriptor(),writeCharacteristic()方法排队,一个单独的线程在空闲时开始执行操作,并且gattCallback在操作完成时通知线程,以便继续进行下一个操作。 / p>

队列类:

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();
}