Android BLE中onCharacteristicRead未自动触发问题求助
我使用JDY-23蓝牙模块,该模块仅有一个支持读写的BluetoothGattCharacteristic。我编写了BtleConnectedClass类用于管理设备连接与Characteristic操作,其中包含public void read(BluetoothGattCharacteristic characteristic)方法来配置通知。在BleSelectServiceDialog类中实例化该类并调用read方法后,onDescriptorWrite回调显示配置成功,但向模块发送数据时,onCharacteristicRead并未自动触发。手动调用readManual方法里的gatt.readCharacteristic()时,onCharacteristicRead能正常执行,请问该如何解决自动触发的问题?
相关代码
实例化与调用代码
bTLegatt=BtleConnectedClass.createInstance(pairedDev,context,udpadeSpinHandler); BluetoothGattService service= (BluetoothGattService) spinnerSelectService.getSelectedItem(); BluetoothGattCharacteristic read = (BluetoothGattCharacteristic)spinnerSelectRead.getSelectedItem(); BluetoothGattCharacteristic write = (BluetoothGattCharacteristic)spinnerSelectWrite.getSelectedItem(); bTLegatt.setService(service); bTLegatt.setRead(read); bTLegatt.setWrite(write); bTLegatt.read(read); //for read Characteristic
BtleConnectedClass的read方法
public void read(BluetoothGattCharacteristic characteristic) { Log.d(TAG, "read characteristic: " + characteristic.getUuid().toString()); gatt.setCharacteristicNotification(characteristic, true); byte[] value; int properties = characteristic.getProperties(); final BluetoothGattDescriptor descriptor = characteristic.getDescriptor(CHARACTERISTIC_UPDATE_NOTIFICATION_DESCRIPTOR_UUID); int connectedState; device = gatt.getDevice(); manager = (BluetoothManager) context.getSystemService(Context.BLUETOOTH_SERVICE); connectedState = manager.getConnectionState(device, BluetoothProfile.GATT); Log.d(TAG, "connectedState " + connectedState); if (connectedState == STATE_CONNECTED) { if ((properties & PROPERTY_NOTIFY) > 0) { Log.d(TAG, "read: " + "PROPERTY_NOTIFY"); value = BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE; descriptor.setValue(value); Log.d(TAG, "value: " + value.toString()); } else if ((properties & PROPERTY_INDICATE) > 0) { Log.d(TAG, "read: " + "PROPERTY_INDICATE"); value = BluetoothGattDescriptor.ENABLE_INDICATION_VALUE; descriptor.setValue(value); } else { Log.e(TAG, String.format("ERROR: Characteristic %s does not have notify or indicate property", characteristic.getUuid())); } gatt.writeDescriptor(descriptor); Log.d(TAG, "setCharacteristicNotification: " + characteristic.getUuid().toString()); gatt.setCharacteristicNotification(characteristic, true); Log.d(TAG, "setCharacteristicNotification: "+gatt.setCharacteristicNotification(characteristic, true)); Log.d(TAG, "descriptor: " + characteristic.getDescriptor(CHARACTERISTIC_UPDATE_NOTIFICATION_DESCRIPTOR_UUID).getUuid().toString()); } }
onDescriptorWrite回调
public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) { super.onDescriptorWrite(gatt, descriptor, status); final BluetoothGattCharacteristic parentCharacteristic = descriptor.getCharacteristic(); if (status != GATT_SUCCESS) { Log.d(TAG, "onDescriptorWrite: failed"); } if (descriptor.getUuid().equals((CHARACTERISTIC_UPDATE_NOTIFICATION_DESCRIPTOR_UUID))) { Log.d(TAG, "onDescriptorWrite: " + descriptor.getUuid().toString()); if (status == GATT_SUCCESS) { byte[] value = descriptor.getValue(); if (value != null) { if (value[0] != 0) { Log.d(TAG, "onDescriptorWrite: Notify set to on"); } } else { Log.d(TAG, "onDescriptorWrite: Notify was turned off"); } } } else { Log.d(TAG, "onDescriptorWrite: " + "// This was a normal descriptor write.."); } }
手动读取方法
public void readManual(BluetoothGattCharacteristic characteristic){ characteristic = gatt.getService(service.getUuid()).getCharacteristic(characteristic.getUuid()); gatt.readCharacteristic(characteristic); BluetoothManager manager = (BluetoothManager)context.getSystemService(Context.BLUETOOTH_SERVICE); Log.d(TAG, "readManual: " + manager.getConnectionState(gatt.getDevice(), BluetoothProfile.GATT)); Log.d(TAG, "readManual: " +characteristic.getUuid().toString()); }
onCharacteristicRead回调
public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status){ String value=characteristic.getStringValue(0); Log.d(TAG, "onCharacteristicRead: " + value); }
纠正回调方法的使用
你配置的是通知/指示功能,对应的自动触发回调是onCharacteristicChanged,而非onCharacteristicRead。onCharacteristicRead仅在主动调用gatt.readCharacteristic()时触发(即手动读取场景)。需要在BluetoothGattCallback中重写onCharacteristicChanged来接收模块主动推送的数据:@Override public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) { super.onCharacteristicChanged(gatt, characteristic); String value = characteristic.getStringValue(0); Log.d(TAG, "onCharacteristicChanged: " + value); }确认Characteristic属性
打印JDY-23模块Characteristic的属性值,确认是否包含PROPERTY_NOTIFY(0x10)或PROPERTY_INDICATE(0x20):Log.d(TAG, "Characteristic properties: " + Integer.toHexString(read.getProperties()));如果不包含对应属性,需要通过AT指令调整模块配置,开启通知功能。
调整read方法的执行顺序
当前代码重复调用setCharacteristicNotification,且顺序不合理。正确流程是:先配置描述符值→写入描述符→在描述符写入成功后开启通知。将gatt.setCharacteristicNotification(characteristic, true)移到onDescriptorWrite的成功分支中:// 在onDescriptorWrite的status == GATT_SUCCESS分支内添加 gatt.setCharacteristicNotification(parentCharacteristic, true);验证JDY-23的工作模式
JDY-23默认可能为透传模式,需确认模块是否配置为主动上报数据的模式。可通过串口向模块发送数据,测试是否会触发onCharacteristicChanged回调。
内容的提问来源于stack exchange,提问作者Vita

