1. 程式人生 > >Android BLE中心裝置的onCharacteristicChanged()方法沒有回撥

Android BLE中心裝置的onCharacteristicChanged()方法沒有回撥

描述:當裝置為 Indication 模式時,裝置的值有變化時會主動返回給App,App在 onCharacteristicChanged() 方法中能收到返回的值。

Indication: 從機會先向主機發送一條通知,主機接收到通知後去讀取從機資料
Notification:從機直接傳送給主機資料

問題:在App中通過如下程式碼註冊監聽,註冊成功後就能接收到裝置主動反饋的值了。然而以下程式碼執行後依舊收不到反饋。但是對裝置的讀寫都是可行的,並且iOS端可以接收到通知。

bluetoothGatt.setCharacteristicNotification(characteristic, true)

解決: 當上面的方法執行返回true後,還要執行如下的程式碼才能註冊成功。

for(BluetoothGattDescriptor dp: characteristic.getDescriptors()){
    if (dp != null) {
        if ((characteristic.getProperties() & BluetoothGattCharacteristic.PROPERTY_NOTIFY) != 0) {
            dp.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
        } else if ((characteristic.getProperties() & BluetoothGattCharacteristic.PROPERTY_INDICATE) != 0) {
            dp.setValue(BluetoothGattDescriptor.ENABLE_INDICATION_VALUE);
        }
        gatt.writeDescriptor(dp);
    }
}

完整的程式碼如下:

public boolean enableNotification(BluetoothGatt gatt, UUID serviceUUID, UUID characteristicUUID) {
    boolean success = false;
    BluetoothGattService service = gatt.getService(serviceUUID);
    if (service != null) {
        BluetoothGattCharacteristic characteristic = findNotifyCharacteristic(service, characteristicUUID);
        if (characteristic != null) {
            success = gatt.setCharacteristicNotification(characteristic, true);
            if (success) {
                // 來源:http://stackoverflow.com/questions/38045294/oncharacteristicchanged-not-called-with-ble
                for(BluetoothGattDescriptor dp: characteristic.getDescriptors()){
                    if (dp != null) {
                        if ((characteristic.getProperties() & BluetoothGattCharacteristic.PROPERTY_NOTIFY) != 0) {
                            dp.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
                        } else if ((characteristic.getProperties() & BluetoothGattCharacteristic.PROPERTY_INDICATE) != 0) {
                            dp.setValue(BluetoothGattDescriptor.ENABLE_INDICATION_VALUE);
                        }
                        gatt.writeDescriptor(dp);
                    }
                }
            }
        }
    }
    return success;
}

private BluetoothGattCharacteristic findNotifyCharacteristic(BluetoothGattService service, UUID characteristicUUID) {
    BluetoothGattCharacteristic characteristic = null;
    List<BluetoothGattCharacteristic> characteristics = service.getCharacteristics();
    for (BluetoothGattCharacteristic c : characteristics) {
        if ((c.getProperties() & BluetoothGattCharacteristic.PROPERTY_NOTIFY) != 0
                && characteristicUUID.equals(c.getUuid())) {
            characteristic = c;
            break;
        }
    }
    if (characteristic != null)
        return characteristic;
    for (BluetoothGattCharacteristic c : characteristics) {
        if ((c.getProperties() & BluetoothGattCharacteristic.PROPERTY_INDICATE) != 0
                && characteristicUUID.equals(c.getUuid())) {
            characteristic = c;
            break;
        }
    }
    return characteristic;
}