Android BLE 读写开发回顾
这里主要记录BLE的通讯方面的笔记
1.发现BluetoothGattService
回调
BLE 调用gatt.connect()
连接成功之后调用:
gatt.discoverServices()
触发回调void onServicesDiscovered(BluetoothGatt gatt, int status)
通过硬件规定的uuid
获取对应的BluetoothGattService
:
BluetoothGattService service = gatt.getService(mServiceUuid);
在BluetoothGattService
中包含一个或多个BluetoothGattCharacteristic
,这些特征字将是后续用来读写数据的载体,而
通过硬件给定的uuid
筛选出对应的特征字,譬如有些特征字用于收发简单命令,而有些特征字用于批量发送数据:
if (characteristic.getUuid().equals(UUID.fromString(String.format(MEDTRUM_BASE_UUID, MEDTRUM_UUID_CHARACTERISTIC_BULK)))) {
//获取批量发送数据特征字
mBulkCharacteristics = characteristic;
} else if (characteristic.getUuid().equals(UUID.fromString(String.format(MEDTRUM_BASE_UUID, MEDTRUM_UUID_CHARACTERISTIC_CTRLPT)))) {
//获取收发命令特征字
mCommandCharacteristics = characteristic;
}
在拿到特征字之后并不能直接使用,如果特征字具有通知功能,那么还需要对其进行设置:
Log.d(TAG, "setCharacteristicNotification: "+gatt.setCharacteristicNotification(characteristic, true));
当然,这还不够,你会发现这个特征字可以正常的发送数据,但是接受不到返回数据,划重点,这里别忘了对特征字描述符BluetoothGattDescriptor
进行设置:
BluetoothGattDescriptor descriptor = characteristic.getDescriptor(UUID.fromString(CLIENT_CHARACTERISTIC_CONFIG));
if ((characteristic.getProperties() & BluetoothGattCharacteristic.PROPERTY_NOTIFY) > 0) {
descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
mBluetoothGatt.writeDescriptor(descriptor);
} else if ((characteristic.getProperties() & BluetoothGattCharacteristic.PROPERTY_INDICATE) > 0) {
descriptor.setValue(BluetoothGattDescriptor.ENABLE_INDICATION_VALUE);
mBluetoothGatt.writeDescriptor(descriptor);
}
设置描述符调用了mBluetoothGatt.writeDescriptor(descriptor)
方法,对应的回调为:
void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status)
在回调中可以对对应的描述符进行验证是否设置成功,然后就可以正常的使用特征字收发命令了;
注意,通常BluetoothGattService
并不只包含一个特征字,而对特征字的设置动作底层其实也是一个写的命令,理论上也会触发:
void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic)
但是在开发过程中通常并不能在这一步接收到回调,这里的原因我还不是很清楚,大牛看到请,烦请指点一二,嘻嘻。
既然是写的操作,就必须遵循串行操作的原则,有序的写,设置一个特征字之后延迟一段时间,再设置下一个。
这里的延迟时间比较讲究,Android手机厂家众多,所以需要给定的延迟时间也各不相同,开发经验发现如果间隔时间超过250ms SAMSUNG 2s内连接不上会被动断开,最终测试结果定在了700ms,可以适配目前所有的测试机型,如果有大牛有更好的解决办法,烦请指点一二,嘻嘻。
2.读写数据
在拿到了特征字之后,就可以进行读写操作了,写:
if (mCommandCharacteristics != null) {
if (value.length > 0) {
mCommandCharacteristics.setValue(value);
mBluetoothGatt.writeCharacteristic(mCommandCharacteristics);
}
}
发送数据之后,可以通过回调:
onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status)
接收反馈,判断命令是否发送成功。
对于数据的读取,通过回调:
void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic)
来获取到反馈的内容,可以看到这个回调中包含了特征字BluetoothGattCharacteristic
很显然,我么您可以通过特征字的uuid
来判断反馈的数据是命令返回,或者是通知消息;
注意,在读写交互中,请一定遵守串行传输的准则,有序的收发命令,避免出现奇奇怪怪的bug;