Android设备BLE writeCharacteristic始终返回false问题求助
Android BLE writeCharacteristic返回false且无回调的问题排查与修复
核心问题分析
从你的代码来看,导致writeCharacteristic()返回false且不触发onCharacteristicWrite()的关键原因有以下几点:
- 未执行实际写入操作:当前调用的自定义
writeCharacteristic()方法仅设置了特征值,完全没有调用gatt.writeCharacteristic()来发起BLE写入请求,这是最根本的问题。 - 参数传反:调用
writeCharacteristic(uuid, String.valueOf(gattCharacteristic.getUuid()),...)时,把服务UUID和特征UUID的参数顺序传反了,导致无法正确获取目标服务和特征。 - 异常处理失效:自定义方法中
characteristic == null时仅创建了异常但未抛出,代码继续执行空对象操作,无任何实际效果。 - 潜在的MTU限制:你构造的JSON payload长度大概率超过了BLE默认MTU(23字节),超出部分会导致写入失败。
- 权限与写入类型不匹配:Android 12+需要
BLUETOOTH_CONNECT权限,且写入类型需与特征支持的属性匹配。
修复方案与代码示例
修正后的写入方法
直接复用你注释掉的正确流程,补充MTU检查、权限验证和异常处理:
public void writeCommand(BluetoothGatt gatt, int bright_value) { if (bluetoothGatt == null) return; // 验证Android 12+所需的蓝牙连接权限 if (ActivityCompat.checkSelfPermission(activity, Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED) { Log.e("BLE", "缺少BLUETOOTH_CONNECT权限,无法执行写入"); return; } // 遍历服务找到目标特征 List<BluetoothGattService> gattServices = gatt.getServices(); for (BluetoothGattService service : gattServices) { if (service.getUuid().toString().equalsIgnoreCase(SERVICE_GUID)) { BluetoothGattCharacteristic targetChar = service.getCharacteristic(UUID.fromString(TX_CHAR_GUID)); if (targetChar == null) { Log.e("BLE", "未找到目标特征UUID:" + TX_CHAR_GUID); continue; } String jsonString = "{\"i\": 1, \"v\": 1, \"t\": 8, \"s\": \"dbri\", \"n\": "+ bright_value +"}"; byte[] payload = jsonString.getBytes(); // 检查当前MTU是否足够容纳payload(减去3字节BLE协议头) int currentMtu = gatt.getMtu(); if (payload.length > currentMtu - 3) { Log.i("BLE", "Payload过长,请求MTU扩容至:" + (payload.length + 3)); gatt.requestMtu(payload.length + 3); // 在onMtuChanged回调中重新执行写入 return; } // 根据特征支持的属性设置写入类型 if ((targetChar.getProperties() & BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE) != 0) { targetChar.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE); } else { targetChar.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT); } // 设置特征值并执行写入 if (targetChar.setValue(payload)) { boolean writeStatus = gatt.writeCharacteristic(targetChar); Log.i("BLE", "写入请求提交状态:" + writeStatus); } else { Log.e("BLE", "设置特征值失败"); } break; } } }
补充GattCallback回调处理
需要在BluetoothGattCallback中添加MTU协商和写入结果的处理:
@Override public void onMtuChanged(BluetoothGatt gatt, int mtu, int status) { super.onMtuChanged(gatt, mtu, status); if (status == BluetoothGatt.GATT_SUCCESS) { Log.i("BLE", "MTU协商成功,当前MTU:" + mtu); // 重新发起写入(需保存bright_value变量或重新传入) writeCommand(gatt, yourSavedBrightValue); } else { Log.e("BLE", "MTU协商失败,状态码:" + status); } } @Override public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) { super.onCharacteristicWrite(gatt, characteristic, status); if (status == BluetoothGatt.GATT_SUCCESS) { Log.i("BLE", "特征写入成功"); } else { Log.e("BLE", "特征写入失败,状态码:" + status); } }
额外注意事项
- 确保BLE连接处于活跃状态,未断开或重连中。
- 避免同时发起多个BLE操作(如同时读特征+写特征),BLE操作需要串行执行。
- 验证自定义开发板的BLE特征属性,确认其支持你设置的写入类型。
内容的提问来源于stack exchange,提问作者Hayjyo
相关产品推荐
相关产品推荐

