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

BLE设备三个特征值仅第一个显示,如何修复另外两个的显示问题?

问题分析与解决方案

核心问题

你的代码中最关键的错误是连续调用gatt.writeDescriptor()。Android BLE的GATT操作是串行队列式的,不支持并行执行。连续写入三个Descriptor会导致后续的写入请求被系统丢弃,最终只有第一个特征的通知配置成功,另外两个的通知并未真正开启,所以无法收到回调。

修复步骤与优化代码

1. 定义UUID常量(避免重复创建与拼写错误)

先将常用的UUID定义为类常量,提升代码可读性与维护性:

// 自定义服务UUID
private static final UUID SERVICE_UUID = UUID.fromString("082b91ae-e83c-11e8-9f32-f2801f1b9fd1");
// 三个特征UUID
private static final UUID CHAR1_UUID = UUID.fromString("082b9438-e83c-11e8-9f32-f2801f1b9fd1");
private static final UUID CHAR2_UUID = UUID.fromString("082b9622-e83c-11e8-9f32-f2801f1b9fd1");
private static final UUID CHAR3_UUID = UUID.fromString("082b976c-e83c-11e8-9f32-f2801f1b9fd1");
// 客户端特征配置Descriptor UUID(标准BLE通知描述符)
private static final UUID CCC_DESCRIPTOR_UUID = UUID.fromString("00002902-0000-1000-8000-00805f9b34fb");

// 保存特征引用,用于后续回调
private BluetoothGattCharacteristic mChar1, mChar2, mChar3;

2. 串行执行Descriptor写入

通过onDescriptorWrite回调确保前一个写入操作完成后,再执行下一个:

@Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
    if (status == BluetoothGatt.GATT_SUCCESS) {
        mChar1 = gatt.getService(SERVICE_UUID).getCharacteristic(CHAR1_UUID);
        mChar2 = gatt.getService(SERVICE_UUID).getCharacteristic(CHAR2_UUID);
        mChar3 = gatt.getService(SERVICE_UUID).getCharacteristic(CHAR3_UUID);

        if (mChar1 != null && mChar2 != null && mChar3 != null) {
            // 先开启第一个特征的通知并写入Descriptor
            gatt.setCharacteristicNotification(mChar1, true);
            BluetoothGattDescriptor desc1 = mChar1.getDescriptor(CCC_DESCRIPTOR_UUID);
            if (desc1 != null) {
                desc1.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
                gatt.writeDescriptor(desc1);
            }
        }
    }
}

// 实现Descriptor写入完成的回调,串行处理后续写入
@Override
public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
    super.onDescriptorWrite(gatt, descriptor, status);
    if (status == BluetoothGatt.GATT_SUCCESS) {
        UUID charUuid = descriptor.getCharacteristic().getUuid();
        if (charUuid.equals(CHAR1_UUID)) {
            // 第一个写入成功,处理第二个特征
            gatt.setCharacteristicNotification(mChar2, true);
            BluetoothGattDescriptor desc2 = mChar2.getDescriptor(CCC_DESCRIPTOR_UUID);
            if (desc2 != null) {
                desc2.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
                gatt.writeDescriptor(desc2);
            }
        } else if (charUuid.equals(CHAR2_UUID)) {
            // 第二个写入成功,处理第三个特征
            gatt.setCharacteristicNotification(mChar3, true);
            BluetoothGattDescriptor desc3 = mChar3.getDescriptor(CCC_DESCRIPTOR_UUID);
            if (desc3 != null) {
                desc3.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
                gatt.writeDescriptor(desc3);
            }
        }
    } else {
        Log.e("BLE_ERROR", "Descriptor写入失败: " + descriptor.getCharacteristic().getUuid() + ", 状态码: " + status);
    }
}

3. 优化特征变更回调

指定明确的字符编码(避免默认编码导致的乱码/显示异常),并添加日志调试:

@Override
public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
    UUID charUuid = characteristic.getUuid();
    byte[] data = characteristic.getValue();
    // 明确指定UTF-8编码(根据设备实际发送的编码调整)
    String value = new String(data, StandardCharsets.UTF_8);
    Log.d("BLE_DATA", "收到特征数据: " + charUuid + ", 值: " + value);

    runOnUiThread(() -> {
        if (charUuid.equals(CHAR1_UUID)) {
            mDataTextView1.setText(value);
        } else if (charUuid.equals(CHAR2_UUID)) {
            mDataTextView2.setText(value);
        } else if (charUuid.equals(CHAR3_UUID)) {
            mDataTextView3.setText(value);
        }
    });
}

额外检查点

  • 确认BLE设备的另外两个特征支持通知属性(特征属性需包含PROPERTY_NOTIFY或PROPERTY_INDICATE)。
  • 检查设备端是否正确配置了这两个特征的广播触发逻辑,确保设备确实在发送通知。
  • 确保BluetoothGatt对象在整个连接周期内未被提前释放。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 19:53:17