Android BLE开发求助:已连接骑行传感器但无法读取Characteristic
问题分析与解决方案
核心结论:骑行速度传感器优先用Notify方式获取数据
你日志中出现的特征UUID 00002a5b-0000-1000-8000-00805f9b34fb 是标准的骑行速度/踏频测量特征,这类实时动态数据的传输场景,Notify是最优选择——传感器会主动推送更新数据;Read仅适合单次拉取静态数据,不适合速度这种高频更新的场景。
你的代码存在的关键问题
- 未配置CCCD描述符:仅调用
setCharacteristicNotification(true)不足以触发传感器推送,必须写入Client Characteristic Configuration Descriptor(UUID:00002902-0000-1000-8000-00805f9b34fb),明确告知传感器需要主动推送数据。 - Toast未触发显示:
Toast.makeText(...)后缺少.show()调用,即使收到数据变化也无法看到反馈。 - 冗余调用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
相关产品推荐
相关产品推荐

