Android BLE API: GATT Notification not received

前端 未结 10 1427
执笔经年
执笔经年 2020-11-29 16:31

Device used for testing: Nexus 4, Android 4.3

Connection is working fine but the onCharacteristicChangedMethod of my callback is never called. However I

10条回答
  •  青春惊慌失措
    2020-11-29 17:25

    @Boni2k - I have the same issues. In my case, I have 3 notifying characteristics and a handful of read/write characteristics.

    What I did find is that there is some dependency between writeGattDescriptor and readCharacteristic. All of the writeGattDescriptors must come first and complete before you issue any readCharacteristic calls.

    Here is my solution using Queues. Now I am getting notifications and everything else works fine:

    Create two Queues like this:

    private Queue descriptorWriteQueue = new LinkedList();
    private Queue characteristicReadQueue = new LinkedList();
    

    Then write all of your descriptors immediately after discovery with this method:

    public void writeGattDescriptor(BluetoothGattDescriptor d){
        //put the descriptor into the write queue
        descriptorWriteQueue.add(d);
        //if there is only 1 item in the queue, then write it.  If more than 1, we handle asynchronously in the callback above
        if(descriptorWriteQueue.size() == 1){   
            mBluetoothGatt.writeDescriptor(d);      
        }
    }
    

    and this callback:

    public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {         
            if (status == BluetoothGatt.GATT_SUCCESS) {
                Log.d(TAG, "Callback: Wrote GATT Descriptor successfully.");           
            }           
            else{
                Log.d(TAG, "Callback: Error writing GATT Descriptor: "+ status);
            }
            descriptorWriteQueue.remove();  //pop the item that we just finishing writing
            //if there is more to write, do it!
            if(descriptorWriteQueue.size() > 0)
                mBluetoothGatt.writeDescriptor(descriptorWriteQueue.element());
            else if(readCharacteristicQueue.size() > 0)
                mBluetoothGatt.readCharacteristic(readQueue.element());
        };
    

    The method for reading a characteristic normally then looks like this:

    public void readCharacteristic(String characteristicName) {
        if (mBluetoothAdapter == null || mBluetoothGatt == null) {
            Log.w(TAG, "BluetoothAdapter not initialized");
            return;
        }
        BluetoothGattService s = mBluetoothGatt.getService(UUID.fromString(kYourServiceUUIDString));
        BluetoothGattCharacteristic c = s.getCharacteristic(UUID.fromString(characteristicName));
        //put the characteristic into the read queue        
        readCharacteristicQueue.add(c);
        //if there is only 1 item in the queue, then read it.  If more than 1, we handle asynchronously in the callback above
        //GIVE PRECEDENCE to descriptor writes.  They must all finish first.
        if((readCharacteristicQueue.size() == 1) && (descriptorWriteQueue.size() == 0))
            mBluetoothGatt.readCharacteristic(c);              
    }
    

    and my read callback:

    public void onCharacteristicRead(BluetoothGatt gatt,
                                         BluetoothGattCharacteristic characteristic,
                                         int status) {
            readCharacteristicQueue.remove();
            if (status == BluetoothGatt.GATT_SUCCESS) {
                broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);                                
            }
            else{
                Log.d(TAG, "onCharacteristicRead error: " + status);
            }
    
            if(readCharacteristicQueue.size() > 0)
                mBluetoothGatt.readCharacteristic(readCharacteristicQueue.element());
        }
    

提交回复
热议问题