You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

解决方法
  1. 纠正回调方法的使用
    你配置的是通知/指示功能,对应的自动触发回调是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);
    }
    
  2. 确认Characteristic属性
    打印JDY-23模块Characteristic的属性值,确认是否包含PROPERTY_NOTIFY(0x10)或PROPERTY_INDICATE(0x20):

    Log.d(TAG, "Characteristic properties: " + Integer.toHexString(read.getProperties()));
    

    如果不包含对应属性,需要通过AT指令调整模块配置,开启通知功能。

  3. 调整read方法的执行顺序
    当前代码重复调用setCharacteristicNotification,且顺序不合理。正确流程是:先配置描述符值→写入描述符→在描述符写入成功后开启通知。将gatt.setCharacteristicNotification(characteristic, true)移到onDescriptorWrite的成功分支中:

    // 在onDescriptorWrite的status == GATT_SUCCESS分支内添加
    gatt.setCharacteristicNotification(parentCharacteristic, true);
    
  4. 验证JDY-23的工作模式
    JDY-23默认可能为透传模式,需确认模块是否配置为主动上报数据的模式。可通过串口向模块发送数据,测试是否会触发onCharacteristicChanged回调。


内容的提问来源于stack exchange,提问作者Vita

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 10:10:56