Android通过BLE调节设备亮度:返回成功但设备无响应求助
我在Android平台通过BLE调节设备亮度,调用writeCharacteristic后返回操作成功,但设备实际亮度没有变化。相关代码如下:
public void sendCommands(BluetoothGatt gatt) throws JSONException { if (bluetoothGatt != null) { List<BluetoothGattService> gattServices = bluetoothGatt.getServices(); if (2 == BluetoothProfile.STATE_CONNECTED) // BLE Is connected after provision as ghatt is connected. { if (ActivityCompat.checkSelfPermission(activity, Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED) { return; } gatt.requestMtu(512); for (int i = 0; i < gattServices.size(); i++) { String serviceUUID = gattServices.get(i).getUuid().toString(); if (serviceUUID.equalsIgnoreCase(SERVICE_GUID)) { List<BluetoothGattCharacteristic> gattCharacteristics = gattServices.get(i).getCharacteristics(); for (BluetoothGattCharacteristic gattCharacteristic : gattCharacteristics) { final String uuid = gattCharacteristic.getUuid().toString(); if (uuid.equalsIgnoreCase(TX_CHAR_GUID)) { String jsonString = "{'i': 1, 'v': 1, 't': 8, 's': 'dbri', 'n': 70}"; byte[] payload = jsonString.getBytes(); gattCharacteristic.setValue(payload+"\r\n"); if (ActivityCompat.checkSelfPermission(activity, Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED) { // TODO: Consider calling // ActivityCompat#requestPermissions // here to request the missing permissions, and then overriding // public void onRequestPermissionsResult(int requestCode, String[] permissions, // int[] grantResults) // to handle the case where the user grants the permission. See the documentation // for ActivityCompat#requestPermissions for more details. return; } gatt.writeCharacteristic(gattCharacteristic); } } } } }
期望实现设备亮度调节功能,求技术帮助。
排查与修复要点
1. 修复字节数组拼接错误
代码中gattCharacteristic.setValue(payload+"\r\n");存在错误:payload是byte[]类型,直接和字符串"\r\n"拼接会将字节数组转为默认字符串表示(如[B@xxxx),再转成字节数组发送,导致设备收到错误数据格式。
修复方式:
将"\r\n"转为字节数组后与原payload合并:
String jsonString = "{\"i\": 1, \"v\": 1, \"t\": 8, \"s\": \"dbri\", \"n\": 70}"; byte[] jsonBytes = jsonString.getBytes(); byte[] lineEnd = "\r\n".getBytes(); byte[] payload = new byte[jsonBytes.length + lineEnd.length]; System.arraycopy(jsonBytes, 0, payload, 0, jsonBytes.length); System.arraycopy(lineEnd, 0, payload, jsonBytes.length, lineEnd.length); gattCharacteristic.setValue(payload);
2. 使用标准JSON格式
代码中JSON使用单引号',部分设备仅支持符合RFC规范的双引号"格式,会导致设备无法解析指令。
修复方式:
将JSON字符串中的单引号替换为双引号,如上述修复代码所示。
3. 等待MTU设置完成后再发送数据
gatt.requestMtu(512)是异步操作,调用后不会立即生效,直接发送数据可能使用默认MTU(23字节),若指令长度超过默认值会被截断。
修复方式:
重写BluetoothGattCallback的onMtuChanged方法,在MTU设置成功后再发送指令:
@Override public void onMtuChanged(BluetoothGatt gatt, int mtu, int status) { super.onMtuChanged(gatt, mtu, status); if (status == BluetoothGatt.GATT_SUCCESS) { // MTU设置成功,发送亮度调节指令 try { sendCommands(gatt); } catch (JSONException e) { e.printStackTrace(); } } }
同时移除sendCommands方法中gatt.requestMtu(512)的代码,改为在BLE连接成功后先调用requestMtu。
4. 确认特征的写入属性
检查TX_CHAR_GUID对应的BluetoothGattCharacteristic是否支持写入操作,需确保特征包含PROPERTY_WRITE或PROPERTY_WRITE_NO_RESPONSE属性:
int properties = gattCharacteristic.getProperties(); if ((properties & BluetoothGattCharacteristic.PROPERTY_WRITE) != 0 || (properties & BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE) != 0) { // 支持写入,执行发送逻辑 }
5. 监听写入回调确认操作结果
gatt.writeCharacteristic返回true仅代表指令被加入发送队列,不代表设备已成功接收并处理。需重写BluetoothGattCallback的onCharacteristicWrite方法,确认写入状态:
@Override public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) { super.onCharacteristicWrite(gatt, characteristic, status); if (status == BluetoothGatt.GATT_SUCCESS) { // 写入成功 } else { // 写入失败,可重试或排查原因 } }
6. 统一BluetoothGatt实例
代码中同时使用参数gatt和成员变量bluetoothGatt,可能导致实例不一致。需确认两者为同一个对象,或统一使用其中一个实例。
内容的提问来源于stack exchange,提问作者Hayjyo

