本文简要介绍如何在Android中进行BLE device的读写,实验平台Android 7, 编译SDK 28(android 9).
本文说明在Android BLE Connect connect到device后继续进行数据读写.
获取读写对象 链接到标题
Characteristic 链接到标题
通过UUID从service中找到要读写的Characteristic,例如我这里打算读温度
private static final UUID TEMPE_CHARACTERISTIC_UUID = UUID.fromString("00002A6E-0000-1000-8000-00805f9b34fb");
BluetoothGattCharacteristic mSchr;
for(BluetoothGattService ser: mServiceList){
mSchr = ser.getCharacteristic(TEMPE_CHARACTERISTIC_UUID);
}
Descriptor 链接到标题
通过UUID从Characteristic中找到要读写的Descriptor,例如我这里打算读温度传感器测量的Trigger方式
private static final UUID EST_DESCRIPTOR_UUID = UUID.fromString("0000290d-0000-1000-8000-00805f9b34fb");
BluetoothGattDescriptor mSdes;
for(BluetoothGattService ser: mServiceList){
List<BluetoothGattCharacteristic> chrs = ser.getCharacteristics();
for(BluetoothGattCharacteristic chr:chrs){
mSdes = chr.getDescriptor(EST_DESCRIPTOR_UUID);
break;
}
}
读&写 链接到标题
值得注意的是无论读写都是异步的,在调用读/写API后需要等到回调执行后才能再调用读/写API,如果回调发生之前调用读/写API无效
Characteristic 链接到标题
读 链接到标题
//发起读
mGatt.readCharacteristic(mSchr);
//mGattCallback(BluetoothGattCallback) 中重写onCharacteristicRead
//当读完成后,会回调中重写onCharacteristicRead,使用getXXXValue取回数据
@Override
public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
super.onCharacteristicRead(gatt, characteristic, status);
if (status == BluetoothGatt.GATT_SUCCESS) {
mStr = " ";
if (characteristic.getUuid().equals(TEMPE_CHARACTERISTIC_UUID)) {
//温度是以u16_t传输,因此按照FORMAT_UINT16读
mStr = "Temp: " + characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT16, 0);
}
mShowString.add(mStr);
}
}
回调中通过getValue有下面几种方式,这个需要根据使用的GATT profiles定义或自定义的Characteristic 的Value格式来决定给用那种
- byte[] getValue()
- Integer getIntValue(int formatType, int offset)
- Float getFloatValue(int formatType, int offset)
- String getStringValue(int offset)
写 链接到标题
Characteristic的写和Descriptor类似,见后面Descriptor的说明,步骤大致如下:
//写入
mStr.setValue(xxx);
mGatt.writeCharacteristic(mStr);
//等待回调通知完成写入
@Override
public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
super.onCharacteristicWrite(gatt, characteristic, status);
if (status == BluetoothGatt.GATT_SUCCESS) {
//写入完成
}
}
和getXXXValue,写入也有对应的一组
- boolean setValue(byte[] value)
- boolean setValue(int value, int formatType, int offset)
- boolean setValue(int mantissa, int exponent, int formatType, int offset)
- boolean setValue(String value)
Descriptor 链接到标题
读 链接到标题
//发起读
mGatt.readDescriptor(mSdes);
//mGattCallback(BluetoothGattCallback) onDescriptorRead
//当读完成后,会回调中重写onDescriptorRead,使用getValue取回数据
@Override
public void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
super.onDescriptorRead(gatt, descriptor, status);
if (status == BluetoothGatt.GATT_SUCCESS) {
mStr = " ";
if(descriptor.getUuid().equals(EST_DESCRIPTOR_UUID)){
byte[] x = descriptor.getValue();
mStr = "Name: " + x[0];
}
mShowString.add(mStr);
}
}
与Characteristic不一样Descriptor的读取数据只有byte[] getValue() ,那回的是ram数据完全靠自己解析
写 链接到标题
//写入
byte[] x = new byte[]{2};
mSdes.setValue(x);
mGatt.writeDescriptor(mSdes);
//mGattCallback(BluetoothGattCallback) onDescriptorWrite
//当写完成后,会回调中重写onDescriptorWrite,之后方可进行下一次读写
@Override
public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
super.onDescriptorWrite(gatt, descriptor, status);
if (status == BluetoothGatt.GATT_SUCCESS) {
if(descriptor.getUuid().equals(EST_DESCRIPTOR_UUID)){
mHandler.post(new Runnable() {
@Override
public void run() {
Toast.makeText(MainActivity.this, "Write Des done", Toast.LENGTH_SHORT).show();
}
});
}
}
}
和Descriptor读一样,写入也只有boolean setValue(byte[] value),需要又使用者自己控制raw数据
参考 链接到标题
https://developer.android.com/guide/topics/connectivity/bluetooth-le#read