Android GATT客户端如何在回调内获取服务器通知数据?
解决GATT客户端无需广播直接处理通知数据的问题
嘿,我明白你的困扰了!其实你之前的核心误区是找错了回调方法,而且误解了getValue()的作用——咱们一步步来解决:
首先,找对触发通知的回调方法
当GATT服务器发送通知时,不会触发onCharacteristicRead(这个回调是你主动调用readCharacteristic()读取特征值时才会触发的),真正对应通知的回调是BluetoothGattCallback里的onCharacteristicChanged方法!
然后,直接在回调里获取实时通知数据
你之前以为getValue()是读取发现特征时的静态数据,这是错的——当设备推送通知时,系统会把最新的通知数据更新到对应的BluetoothGattCharacteristic对象里,此时调用characteristic.getValue()拿到的就是刚收到的那23字节实时数据,完全可以当场处理,不需要广播转发。
代码示例
这里给你一个完整的实现片段:
1. 重写onCharacteristicChanged回调处理数据
private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() { // 其他回调方法(比如onConnectionStateChange、onServicesDiscovered)... @Override public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) { super.onCharacteristicChanged(gatt, characteristic); // 获取通知的字节数组 byte[] receivedBytes = characteristic.getValue(); if (receivedBytes != null && receivedBytes.length == 23) { // 把字节数组转成char数组(注意编码格式,根据你的设备协议选,比如ASCII/UTF-8) char[] charData = new char[receivedBytes.length]; for (int i = 0; i < receivedBytes.length; i++) { charData[i] = (char) receivedBytes[i]; } // 在这里直接处理你的char数组或者原始字节数据 // 比如打印日志或者执行业务逻辑 Log.d("GATT_NOTIFICATION", "收到的char数据: " + new String(charData)); } } };
2. 别忘了开启特征的通知功能
要让回调触发,你必须先给目标特征开启通知权限,还要配置对应的描述符:
// 假设你已经获取到了要监听的特征characteristic BluetoothGattCharacteristic targetCharacteristic = ...; // 第一步:开启特征通知 mBluetoothGatt.setCharacteristicNotification(targetCharacteristic, true); // 第二步:配置Client Characteristic Configuration描述符(必须做!) BluetoothGattDescriptor descriptor = targetCharacteristic.getDescriptor( UUID.fromString("00002902-0000-1000-8000-00805f9b34fb") ); if (descriptor != null) { // 设置为启用通知的值 descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE); // 写入描述符到设备 mBluetoothGatt.writeDescriptor(descriptor); }
最后再强调一遍
- 通知触发的是
onCharacteristicChanged,不是onCharacteristicRead characteristic.getValue()在这个回调里拿到的是实时的通知数据,不是静态的初始值- 一定要配置好描述符,否则通知不会触发回调
这样你就完全不需要用广播,直接在回调里当场处理收到的23字节数据啦!
内容的提问来源于stack exchange,提问作者Miko
相关产品推荐
相关产品推荐

