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

Android BLE开发求助:已连接骑行传感器但无法读取Characteristic

问题分析与解决方案

核心结论:骑行速度传感器优先用Notify方式获取数据

你日志中出现的特征UUID 00002a5b-0000-1000-8000-00805f9b34fb 是标准的骑行速度/踏频测量特征,这类实时动态数据的传输场景,Notify是最优选择——传感器会主动推送更新数据;Read仅适合单次拉取静态数据,不适合速度这种高频更新的场景。

你的代码存在的关键问题

  1. 未配置CCCD描述符:仅调用setCharacteristicNotification(true)不足以触发传感器推送,必须写入Client Characteristic Configuration Descriptor(UUID:00002902-0000-1000-8000-00805f9b34fb),明确告知传感器需要主动推送数据。
  2. Toast未触发显示:Toast.makeText(...)后缺少.show()调用,即使收到数据变化也无法看到反馈。
  3. 冗余调用readCharacteristic:既然要实时获取数据,无需额外调用readCharacteristic,Notify会自动推送更新。

修正后的代码示例

private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
    @Override
    public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
        super.onConnectionStateChange(gatt, status, newState);
        if (newState == BluetoothProfile.STATE_CONNECTED) {
            gatt.discoverServices();
        } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
            ScanningEnd = false;
        }
    }

    @Override
    public void onServicesDiscovered(BluetoothGatt gatt, int status) {
        super.onServicesDiscovered(gatt, status);
        if (status != BluetoothGatt.GATT_SUCCESS) {
            Log.e(TAG, "服务发现失败,状态码:" + status);
            return;
        }

        // 遍历服务和特征,确认目标特征存在(调试用)
        List<BluetoothGattService> services = gatt.getServices();
        Log.e("onServicesDiscovered", "Services count: "+services.size());
        for (BluetoothGattService service : services) {
            Log.d(TAG, "Found Service " + service.getUuid().toString());
            for(BluetoothGattCharacteristic characteristic : service.getCharacteristics()) {
                Log.d(TAG, "Found Characteristic " + characteristic.getUuid().toString());
            }
        }

        // 获取目标特征(骑行速度/踏频测量)
        BluetoothGattCharacteristic speedCharacteristic = gatt.getService(NOTIF_SERVICE)
                .getCharacteristic(NOTIF_CHARACTERESTIC);
        if (speedCharacteristic == null) {
            Log.e(TAG, "未找到目标特征");
            return;
        }

        // 1. 开启特征通知开关
        gatt.setCharacteristicNotification(speedCharacteristic, true);
        // 2. 写入CCCD描述符,触发传感器主动推送
        BluetoothGattDescriptor descriptor = speedCharacteristic.getDescriptor(
                UUID.fromString("00002902-0000-1000-8000-00805f9b34fb"));
        if (descriptor != null) {
            descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
            gatt.writeDescriptor(descriptor);
        }
    }

    @Override
    public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
        super.onCharacteristicChanged(gatt, characteristic);
        if (characteristic.getUuid().equals(NOTIF_CHARACTERESTIC)) {
            // 按BLE标准解析速度数据
            byte[] data = characteristic.getValue();
            if (data != null && data.length >= 6) {
                boolean hasWheelRevData = (data[0] & 0x01) != 0;
                if (hasWheelRevData) {
                    // 解析累计车轮转数和事件时间
                    long wheelRevolutions = ((long)(data[1] & 0xFF) | ((long)(data[2] & 0xFF) << 8) |
                            ((long)(data[3] & 0xFF) << 16) | ((long)(data[4] & 0xFF) << 24));
                    int wheelEventTime = ((data[5] & 0xFF) | ((data[6] & 0xFF) << 8));
                    Log.d(TAG, "车轮转数:" + wheelRevolutions + ",事件时间:" + wheelEventTime);
                }
            }

            // 显示更新提示(必须调用show())
            runOnUiThread(() -> 
                Toast.makeText(MainActivity.this, "收到速度数据更新", Toast.LENGTH_SHORT).show()
            );
        }
    }

    @Override
    public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
        super.onDescriptorWrite(gatt, descriptor, status);
        if (status == BluetoothGatt.GATT_SUCCESS) {
            Log.d(TAG, "CCCD写入成功,已开启数据推送");
        } else {
            Log.e(TAG, "CCCD写入失败,状态码:" + status);
        }
    }

    @Override
    public void onScanFailed(int errorCode) {
        super.onScanFailed(errorCode);
        Log.e(TAG, "扫描失败,错误码:" + errorCode);
    }
};

额外调试建议

  • 确认NOTIF_SERVICE的UUID正确性:骑行速度传感器的标准服务UUID是00001816-0000-1000-8000-00805f9b34fb,如果你的自定义UUID不符,需修正。
  • 检查权限:Android 12+需单独申请BLUETOOTH_SCAN、BLUETOOTH_CONNECT权限,低版本需申请BLUETOOTH、BLUETOOTH_ADMIN权限。
  • 若非要用Read方式:需重写onCharacteristicRead回调,才能获取读取结果——你的代码未实现该方法,所以调用readCharacteristic后无法看到数据。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 10:30:58