我们在《Android蓝牙开发系列文章-策划篇》中计划讲解一下蓝牙BLE,现在开始第一篇:Android蓝牙开发系列文章-玩转BLE开发(一)。计划要写的BLE文章至少分四篇,其他三篇分别讲解:BLE Server端编码(用手机模拟外围设备),BLE Beacon功能,BLE设备通信(利用自有协议实现Client和Server端通信,在Server端信息改变时,自动上报给Client)。

本文主要内容:编码实现BLE Client端,实现手机与蓝牙体重秤之间的通信

所用的设备:华为荣耀7手机,微信小程序,乐心体重秤

目录

1.基本概念

2.先来认识一下我们的设备

3、认识BLE Client编码

3.1 扫描BLE设备

3.2 建立GATT连接

3.3 解析设备支持的characteristic

3.4 读取characteristic值

3.5 写characteristic值

3.6 设置indication

4、总结


1.基本概念

在这里先讲解一下BLE(Bluetooth Low Energy)的一些简单概念。

本文会涉及一个概念叫“GATT连接”,那我们先说一下什么是GATT,GATT(GenericAttribute Profile)译为通用属性配置文件。GATT连接利用的是在外设(体重秤)与中心设备(手机)之间建议一种联系,这种联系利用的是双方之间都能够识别(或者说提前约定好)的协议。这种协议的基础就是GATT。

GATT由service、characteristic、descriptor元素组成。service是一个功能单元的集合,这个集合有SIG标准的,也可以自己定义的。一个service可以包含一个或者多个characteristic,每个characteristic包含一个value和一个或者多个descriptor。descriptor是对characteristic的描述,例如是否支持读取等。

我们说的利用GATT通信就是对characteristic的读、写、或者characteristic的值发生改变时的自动上报(方向为:从蓝牙体重秤到手机)。

一个BLE设备往往支持多个service,即多个功能集合。例如,现在智能电视遥控器也许会支持蓝牙电量的service、蜂鸣的service以及一些自定义的service。

按照我个人的理解,画了一个BLE设备的GATT的结构如下,仅供大家参考。

2.先来认识一下我们的设备

俗话说“知彼知己,百战不殆”,我们在动手码代码前,要先来了解一下我们所用的设备,不然代码写了一半了,才意识到我们这个功能根本完成不了,那不是呵呵了。

我的测试手机是荣耀7,Android版本为Android6,因为BLE是从Android4.3开始支持的,所以我的手机应该可以过关了。

利用微信小程序“BLE蓝牙开发助手”可以搜索到家里的体脂秤,并且可以建立连接。利用该小程序可以看到该款体重秤有4个service,点击中某个service中的characteristic,可以正常读取数据,说明手机与体重秤之间建立通信应该没有问题。

下面我们要做的就是实现微信小程序类似的功能,与体重秤建立通信,并获取数据。

3、认识BLE Client编码

本文以《Android蓝牙开发系列文章-扫不到蓝牙设备,你的姿势对了吗?》中的代码为基础,进行了添加和修改。

3.1 扫描BLE设备

利用微信小程序,我们可以知道体重秤支持UUID为“0000FEE7-0000-1000-8000-00805F9B34FB”的service,所以,我在设备过滤条件里指定了UUID,相关代码如下:

private void startBleScan2() {
//        mBluetoothLeScanner.startScan(mScanCallback);//过滤条件List<ScanFilter> bleScanFilters = new ArrayList<>();
//        ScanFilter filter = new ScanFilter.Builder().setDeviceAddress("08:7C:BE:48:65:AD").setServiceUuid(ParcelUuid.fromString("0000fee7-0000-1000-8000-00805f9b34fb")).build();ScanFilter filter = new ScanFilter.Builder().setServiceUuid(ParcelUuid.fromString("0000FEE7-0000-1000-8000-00805F9B34FB")).build();bleScanFilters.add(filter);//扫描设置ScanSettings scanSetting = new ScanSettings.Builder().setScanMode(SCAN_MODE_LOW_LATENCY).setCallbackType(ScanSettings.CALLBACK_TYPE_ALL_MATCHES).setMatchMode(ScanSettings.MATCH_MODE_STICKY).build();mBluetoothLeScanner.startScan(bleScanFilters, scanSetting, mScanCallback);}

3.2 建立GATT连接

在扫描到目标设备后,我们将BluetoothDevice对象记录下来。先停掉BLE扫描,然后发起GATT连接。

private  ScanCallback mScanCallback = new ScanCallback() {@Overridepublic void onScanResult(int callbackType, ScanResult result) {super.onScanResult(callbackType, result);Log.d(TAG, "onScanResult, result = " + result);Message msg = new Message();msg.what = MSG_FIND_TARGET;msg.obj = result.getDevice();mHandler.sendMessage(msg);}
};mHandler = new Handler(){@NonNull@Overridepublic void dispatchMessage(Message msg) {Log.d(TAG, "dispatchMessage, msg = " + msg.what);switch (msg.what) {case MSG_FIND_TARGET:mTargetDevice = (BluetoothDevice) msg.obj;stopBleScan2();mBluetoothGatt = mTargetDevice.connectGatt(getApplicationContext(), false, mBluetoothGattCallback);break;}}
};

GATT连接调用的是BluetoothDevice::connectGatt(Contextcontext,)方法,先说一下参数的含义。

autoConnect表示是否接着发起gatt连接,若值为false,则表示立即发起连接,若值为true,则表示为等到设备变为available时再发起连接。因为我们这里是扫描到设备后发起连接的,所以直接传入false就OK了。

callback是用于获取连接状态改变的回调,该回调是本文的重点,下面详细讲一下。

/*** Connect to GATT Server hosted by this device. Caller acts as GATT client.* The callback is used to deliver results to Caller, such as connection status as well* as any further GATT client operations.* The method returns a BluetoothGatt instance. You can use BluetoothGatt to conduct* GATT client operations.** @param callback GATT callback handler that will receive asynchronous callbacks.* @param autoConnect Whether to directly connect to the remote device (false) or to* automatically connect as soon as the remote device becomes available (true).* @throws IllegalArgumentException if callback is null*/
public BluetoothGatt connectGatt(Context context, boolean autoConnect,BluetoothGattCallback callback) {return (connectGatt(context, autoConnect, callback, TRANSPORT_AUTO));
}

我摘取了部分BluetoothGattCallback中的方法,进行简单的解释:

/*** This abstract class is used to implement {@link BluetoothGatt} callbacks.*/
public abstract class BluetoothGattCallback {//连接状态改变的回调,status为BluetoothGatt#GATT_SUCCESS表示连接成功,//newState表示连接状态改变后的值,可能值为BluetoothProfile#STATE_DISCONNECTED//或者为BluetoothProfile#STATE_CONNECTEDpublic void onConnectionStateChange(BluetoothGatt gatt, int status,int newState) {
}//调用了BluetoothGatt:: discoverServices()方法的回调public void onServicesDiscovered(BluetoothGatt gatt, int status) {
}
//调用了BluetoothGatt::readCharacteristic()方法的回调,在status值为//BluetoothGatt#GATT_SUCCESS时表示我们想要的值读取成功了public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic,int status) {
}
//调用了BluetoothGatt::writeCharacteristic()方法的回调,在status值为
//BluetoothGatt#GATT_SUCCESS时表示我们对characteristic执行写操作成功了public void onCharacteristicWrite(BluetoothGatt gatt,BluetoothGattCharacteristic characteristic, int status) {
}
//在server端的某个characteristic改变时会回调到这里,当然,前提是设置了//notificationpublic void onCharacteristicChanged(BluetoothGatt gatt,BluetoothGattCharacteristic characteristic) {
}
//在执行了读取descriptor的回调,同样,status值表征了操作是否成功public void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor,int status) {
}
//在执行了修改descriptor的回调,status值为BluetoothGatt#GATT_SUCCESS表示修改成了public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor,int status) {
}
}

3.3 解析设备支持的characteristic

在onConnectionStateChange()回调中,如果status为BluetoothGatt.GATT_SUCCESS且newState为BluetoothProfile.STATE_CONNECTED,则可以发起service扫描,即获取体重秤所支持的service。

如果newState不为BluetoothProfile.STATE_CONNECTED,则释放gatt连接资源,并重新发起连接。

@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {super.onConnectionStateChange(gatt, status, newState);Log.d(TAG, "onConnectionStateChange, status = " + status + ", newState = " + newState);if (status == BluetoothGatt.GATT_SUCCESS) {if (newState == BluetoothProfile.STATE_CONNECTED) {mBluetoothGatt.discoverServices();} else {mBluetoothGatt.close();mBluetoothGatt = mTargetDevice.connectGatt(getApplicationContext(), false, mBluetoothGattCallback);}}
}

在搜索完成体重秤的service后,应用层会收到onServiceDiscovered()回调。我们按照service->characteristic->descriptor层次结构,进行解析。

public void onServicesDiscovered(BluetoothGatt gatt, int status) {Log.d(TAG, "onServicesDiscovered, status = " + status);List<BluetoothGattService> gattServicesList = mBluetoothGatt.getServices();parseService(gattServicesList);}
private void parseService(List<BluetoothGattService> gattServiceList) {Log.d(TAG, "----- start parseServie -----");for (int i = 0; i < gattServiceList.size(); i++) {BluetoothGattService gattService = (BluetoothGattService)gattServiceList.get(i);UUID uuid = gattService.getUuid();Log.d(TAG, "parseService, service uuid = " + uuid);List<BluetoothGattCharacteristic> gattCharacteristics = gattService.getCharacteristics();for (int j = 0; j < gattCharacteristics.size(); j++) {BluetoothGattCharacteristic gattCharacteristic = gattCharacteristics.get(j);int properties = gattCharacteristic.getProperties();int permission = gattCharacteristic.getPermissions();Log.d(TAG, "gattCharacteristic, characteristic uuid = " + gattCharacteristic.getUuid() + " properties = " + properties);if (0 !=  (properties & BluetoothGattCharacteristic.PROPERTY_READ)) {Log.d(TAG, "gattCharacteristic, characteristic uuid = " + gattCharacteristic.getUuid() + " support read");if (gattCharacteristic.getUuid().toString().equals(LeXinUUID.READ_CHARA)) {Message msg = new Message();msg.what = MSG_READ_CHARA;msg.obj = gattCharacteristic;mHandler.sendMessageDelayed(msg, DELAY_TIMES);}//                        mBluetoothGatt.readCharacteristic(gattCharacteristic);}if ((0 !=  (properties & BluetoothGattCharacteristic.PROPERTY_INDICATE))) {Log.d(TAG, "gattCharacteristic, characteristic uuid = " + gattCharacteristic.getUuid() + " support indicate");if (gattCharacteristic.getUuid().toString().equals(LeXinUUID.INDICATE_CHARA)) {Message msg = new Message();msg.what = MSG_INDICATE;msg.obj = gattCharacteristic;mHandler.sendMessageDelayed(msg, 3*DELAY_TIMES);}}if (0 !=  (properties & BluetoothGattCharacteristic.PROPERTY_NOTIFY)) {Log.d(TAG, "gattCharacteristic, characteristic uuid = " + gattCharacteristic.getUuid() + " support notify");}if ((0 !=  (properties & BluetoothGattCharacteristic.PROPERTY_WRITE))) {Log.d(TAG, "gattCharacteristic, characteristic uuid = " + gattCharacteristic.getUuid() + " support write");if (gattCharacteristic.getUuid().toString().equals(LeXinUUID.WRITE_CHARA)) {Message msg = new Message();msg.what = MSG_WRITE_CHARA;msg.obj = gattCharacteristic;mHandler.sendMessageDelayed(msg, 2*DELAY_TIMES);}}List<BluetoothGattDescriptor> gattDescriptors = gattCharacteristic.getDescriptors();for (int k = 0; k < gattDescriptors.size(); k++) {BluetoothGattDescriptor gattDescriptor = (BluetoothGattDescriptor)gattDescriptors.get(k);Log.d(TAG, "gattDescriptors, descriptor uuid = " + gattDescriptor.getUuid());
//                        gattDescriptor.setValue(BluetoothGattDescriptor.ENABLE_INDICATION_VALUE);
//                        mBluetoothGatt.writeDescriptor(gattDescriptor);}}}Log.d(TAG, "----- parseServie end -----");}

在解析的过程中,我们判断了characteristic的properties是否支持read、write、notify、indicate。解析结果如下:

03-22 21:39:10.794 5392-5429/com.atlas.devicefinder D/MainActivity: ----- start parseServie -----
03-22 21:39:10.794 5392-5429/com.atlas.devicefinder D/MainActivity: parseService, service uuid = 00001800-0000-1000-8000-00805f9b34fb
03-22 21:39:10.794 5392-5429/com.atlas.devicefinder D/MainActivity: gattCharacteristic, characteristic uuid = 00002a00-0000-1000-8000-00805f9b34fb properties = 10
03-22 21:39:10.794 5392-5429/com.atlas.devicefinder D/MainActivity: gattCharacteristic, characteristic uuid = 00002a00-0000-1000-8000-00805f9b34fb support read
03-22 21:39:10.794 5392-5429/com.atlas.devicefinder D/MainActivity: gattCharacteristic, characteristic uuid = 00002a00-0000-1000-8000-00805f9b34fb support write
03-22 21:39:10.794 5392-5429/com.atlas.devicefinder D/MainActivity: gattCharacteristic, characteristic uuid = 00002a01-0000-1000-8000-00805f9b34fb properties = 2
03-22 21:39:10.794 5392-5429/com.atlas.devicefinder D/MainActivity: gattCharacteristic, characteristic uuid = 00002a01-0000-1000-8000-00805f9b34fb support read
03-22 21:39:10.794 5392-5429/com.atlas.devicefinder D/MainActivity: gattCharacteristic, characteristic uuid = 00002a02-0000-1000-8000-00805f9b34fb properties = 10
03-22 21:39:10.794 5392-5429/com.atlas.devicefinder D/MainActivity: gattCharacteristic, characteristic uuid = 00002a02-0000-1000-8000-00805f9b34fb support read
03-22 21:39:10.794 5392-5429/com.atlas.devicefinder D/MainActivity: gattCharacteristic, characteristic uuid = 00002a02-0000-1000-8000-00805f9b34fb support write
03-22 21:39:10.794 5392-5429/com.atlas.devicefinder D/MainActivity: gattCharacteristic, characteristic uuid = 00002a04-0000-1000-8000-00805f9b34fb properties = 2
03-22 21:39:10.794 5392-5429/com.atlas.devicefinder D/MainActivity: gattCharacteristic, characteristic uuid = 00002a04-0000-1000-8000-00805f9b34fb support read
03-22 21:39:10.794 5392-5429/com.atlas.devicefinder D/MainActivity: gattCharacteristic, characteristic uuid = 00002a03-0000-1000-8000-00805f9b34fb properties = 14
03-22 21:39:10.794 5392-5429/com.atlas.devicefinder D/MainActivity: gattCharacteristic, characteristic uuid = 00002a03-0000-1000-8000-00805f9b34fb support read
03-22 21:39:10.794 5392-5429/com.atlas.devicefinder D/MainActivity: gattCharacteristic, characteristic uuid = 00002a03-0000-1000-8000-00805f9b34fb support write
03-22 21:39:10.794 5392-5429/com.atlas.devicefinder D/MainActivity: parseService, service uuid = 00001801-0000-1000-8000-00805f9b34fb
03-22 21:39:10.794 5392-5429/com.atlas.devicefinder D/MainActivity: gattCharacteristic, characteristic uuid = 00002a05-0000-1000-8000-00805f9b34fb properties = 34
03-22 21:39:10.795 5392-5429/com.atlas.devicefinder D/MainActivity: gattCharacteristic, characteristic uuid = 00002a05-0000-1000-8000-00805f9b34fb support read
03-22 21:39:10.795 5392-5429/com.atlas.devicefinder D/MainActivity: gattCharacteristic, characteristic uuid = 00002a05-0000-1000-8000-00805f9b34fb support indicate
03-22 21:39:10.797 5392-5429/com.atlas.devicefinder D/MainActivity: gattDescriptors, descriptor uuid = 00002902-0000-1000-8000-00805f9b34fb
03-22 21:39:10.797 5392-5429/com.atlas.devicefinder D/MainActivity: parseService, service uuid = 0000fee7-0000-1000-8000-00805f9b34fb
03-22 21:39:10.797 5392-5429/com.atlas.devicefinder D/MainActivity: gattCharacteristic, characteristic uuid = 0000fec8-0000-1000-8000-00805f9b34fb properties = 32
03-22 21:39:10.797 5392-5429/com.atlas.devicefinder D/MainActivity: gattCharacteristic, characteristic uuid = 0000fec8-0000-1000-8000-00805f9b34fb support indicate
03-22 21:39:10.799 5392-5429/com.atlas.devicefinder D/MainActivity: gattDescriptors, descriptor uuid = 00002902-0000-1000-8000-00805f9b34fb
03-22 21:39:10.799 5392-5429/com.atlas.devicefinder D/MainActivity: gattCharacteristic, characteristic uuid = 0000fec9-0000-1000-8000-00805f9b34fb properties = 2
03-22 21:39:10.799 5392-5429/com.atlas.devicefinder D/MainActivity: gattCharacteristic, characteristic uuid = 0000fec9-0000-1000-8000-00805f9b34fb support read
03-22 21:39:10.799 5392-5429/com.atlas.devicefinder D/MainActivity: gattCharacteristic, characteristic uuid = 0000fec7-0000-1000-8000-00805f9b34fb properties = 8
03-22 21:39:10.799 5392-5429/com.atlas.devicefinder D/MainActivity: gattCharacteristic, characteristic uuid = 0000fec7-0000-1000-8000-00805f9b34fb support write
03-22 21:39:10.799 5392-5429/com.atlas.devicefinder D/MainActivity: parseService, service uuid = 0000180a-0000-1000-8000-00805f9b34fb
03-22 21:39:10.799 5392-5429/com.atlas.devicefinder D/MainActivity: gattCharacteristic, characteristic uuid = 00002a29-0000-1000-8000-00805f9b34fb properties = 2
03-22 21:39:10.799 5392-5429/com.atlas.devicefinder D/MainActivity: gattCharacteristic, characteristic uuid = 00002a29-0000-1000-8000-00805f9b34fb support read
03-22 21:39:10.799 5392-5429/com.atlas.devicefinder D/MainActivity: gattCharacteristic, characteristic uuid = 00002a24-0000-1000-8000-00805f9b34fb properties = 2
03-22 21:39:10.799 5392-5429/com.atlas.devicefinder D/MainActivity: gattCharacteristic, characteristic uuid = 00002a24-0000-1000-8000-00805f9b34fb support read
03-22 21:39:10.799 5392-5429/com.atlas.devicefinder D/MainActivity: gattCharacteristic, characteristic uuid = 00002a25-0000-1000-8000-00805f9b34fb properties = 2
03-22 21:39:10.799 5392-5429/com.atlas.devicefinder D/MainActivity: gattCharacteristic, characteristic uuid = 00002a25-0000-1000-8000-00805f9b34fb support read
03-22 21:39:10.799 5392-5429/com.atlas.devicefinder D/MainActivity: gattCharacteristic, characteristic uuid = 00002a27-0000-1000-8000-00805f9b34fb properties = 2
03-22 21:39:10.799 5392-5429/com.atlas.devicefinder D/MainActivity: gattCharacteristic, characteristic uuid = 00002a27-0000-1000-8000-00805f9b34fb support read
03-22 21:39:10.799 5392-5429/com.atlas.devicefinder D/MainActivity: gattCharacteristic, characteristic uuid = 00002a26-0000-1000-8000-00805f9b34fb properties = 2
03-22 21:39:10.799 5392-5429/com.atlas.devicefinder D/MainActivity: gattCharacteristic, characteristic uuid = 00002a26-0000-1000-8000-00805f9b34fb support read
03-22 21:39:10.799 5392-5429/com.atlas.devicefinder D/MainActivity: gattCharacteristic, characteristic uuid = 00002a28-0000-1000-8000-00805f9b34fb properties = 2
03-22 21:39:10.799 5392-5429/com.atlas.devicefinder D/MainActivity: gattCharacteristic, characteristic uuid = 00002a28-0000-1000-8000-00805f9b34fb support read
03-22 21:39:10.799 5392-5429/com.atlas.devicefinder D/MainActivity: gattCharacteristic, characteristic uuid = 00002a23-0000-1000-8000-00805f9b34fb properties = 2
03-22 21:39:10.799 5392-5429/com.atlas.devicefinder D/MainActivity: gattCharacteristic, characteristic uuid = 00002a23-0000-1000-8000-00805f9b34fb support read
03-22 21:39:10.799 5392-5429/com.atlas.devicefinder D/MainActivity: gattCharacteristic, characteristic uuid = 00002a2a-0000-1000-8000-00805f9b34fb properties = 2
03-22 21:39:10.799 5392-5429/com.atlas.devicefinder D/MainActivity: gattCharacteristic, characteristic uuid = 00002a2a-0000-1000-8000-00805f9b34fb support read
03-22 21:39:10.799 5392-5429/com.atlas.devicefinder D/MainActivity: gattCharacteristic, characteristic uuid = 00002a50-0000-1000-8000-00805f9b34fb properties = 2
03-22 21:39:10.799 5392-5429/com.atlas.devicefinder D/MainActivity: gattCharacteristic, characteristic uuid = 00002a50-0000-1000-8000-00805f9b34fb support read
03-22 21:39:10.799 5392-5429/com.atlas.devicefinder D/MainActivity: parseService, service uuid = 0000fee8-0000-1000-8000-00805f9b34fb
03-22 21:39:10.799 5392-5429/com.atlas.devicefinder D/MainActivity: gattCharacteristic, characteristic uuid = 003784cf-f7e3-55b4-6c4c-9fd140100a16 properties = 16
03-22 21:39:10.800 5392-5429/com.atlas.devicefinder D/MainActivity: gattCharacteristic, characteristic uuid = 003784cf-f7e3-55b4-6c4c-9fd140100a16 support notify
03-22 21:39:10.801 5392-5429/com.atlas.devicefinder D/MainActivity: gattDescriptors, descriptor uuid = 00002902-0000-1000-8000-00805f9b34fb
03-22 21:39:10.801 5392-5429/com.atlas.devicefinder D/MainActivity: gattDescriptors, descriptor uuid = 00002901-0000-1000-8000-00805f9b34fb
03-22 21:39:10.801 5392-5429/com.atlas.devicefinder D/MainActivity: gattCharacteristic, characteristic uuid = 013784cf-f7e3-55b4-6c4c-9fd140100a16 properties = 4
03-22 21:39:10.801 5392-5429/com.atlas.devicefinder D/MainActivity: parseService, service uuid = d618d000-6000-1000-8000-000000000000
03-22 21:39:10.801 5392-5429/com.atlas.devicefinder D/MainActivity: gattCharacteristic, characteristic uuid = d618d002-6000-1000-8000-000000000000 properties = 32
03-22 21:39:10.801 5392-5429/com.atlas.devicefinder D/MainActivity: gattCharacteristic, characteristic uuid = d618d002-6000-1000-8000-000000000000 support indicate
03-22 21:39:10.803 5392-5429/com.atlas.devicefinder D/MainActivity: gattDescriptors, descriptor uuid = 00002902-0000-1000-8000-00805f9b34fb
03-22 21:39:10.803 5392-5429/com.atlas.devicefinder D/MainActivity: gattCharacteristic, characteristic uuid = d618d001-6000-1000-8000-000000000000 properties = 8
03-22 21:39:10.803 5392-5429/com.atlas.devicefinder D/MainActivity: gattCharacteristic, characteristic uuid = d618d001-6000-1000-8000-000000000000 support write
03-22 21:39:10.803 5392-5429/com.atlas.devicefinder D/MainActivity: ----- parseServie end -----

3.4 读取characteristic值

我们根据上面的解析结果,选取了00002a50-0000-1000-8000-00805f9b34fb来做实验,在解析到该characteristic时,我们读取该属性值,代码看3.2部分代码块。在回调onCharacteristicRead()中添加如下的打印,

public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic,int status) {super.onCharacteristicRead(gatt, characteristic, status);Log.d(TAG, "onCharacteristicRead, characteristic = " + characteristic + ", status = " + status + ", value = " + characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT32, 0));
}

实验结果如下,说明我们收到了相应的回调,因为我们没有获取实际的协议,不知道这个值表示的实际含义。

03-24 21:13:09.645 20927-20938/com.atlas.devicefinder D/MainActivity: onCharacteristicRead, characteristic = android.bluetooth.BluetoothGattCharacteristic@2ac9086, status = 0, value = 1027

3.5 写characteristic值

我们选取了"0000fec7-0000-1000-8000-00805f9b34fb"characteristic,在解析到该characteristic时,去读取该属性值。部分代码请查看3.2部分的代码段。
mHandler = new Handler(){@NonNull@Overridepublic void dispatchMessage(Message msg) {Log.d(TAG, "dispatchMessage, msg = " + msg.what);switch (msg.what) {case MSG_WRITE_CHARA:BluetoothGattCharacteristic gattCharacteristic2 = (BluetoothGattCharacteristic) msg.obj;gattCharacteristic2.setValue("0");mBluetoothGatt.writeCharacteristic(gattCharacteristic2);break;}}};
在回调onCharacteristicWrite()中添加如下的打印,
public void onCharacteristicWrite(BluetoothGatt gatt,BluetoothGattCharacteristic characteristic, int status) {super.onCharacteristicWrite(gatt, characteristic, status);Log.d(TAG, "onCharacteristicWrite, characteristic = " + characteristic + ", value = " + characteristic.getStringValue(0) + ", status = " + status);
}
实验结果如下,说明我们成功修改了该属性的值。
03-24 21:32:15.318 25167-25167/com.atlas.devicefinder D/MainActivity: dispatchMessage, msg = 2
03-24 21:32:15.385 25167-25366/com.atlas.devicefinder D/MainActivity: onCharacteristicWrite, characteristic = android.bluetooth.BluetoothGattCharacteristic@78102ba, value = 0, status = 0

3.6 设置indication

我们选取了"d618d002-6000-1000-8000-000000000000"characteristic,其持有的descripotor UUID为"00002902-0000-1000-8000-00805f9b34fb"。

设置方法如下:
mHandler = new Handler(){@NonNull@Overridepublic void dispatchMessage(Message msg) {Log.d(TAG, "dispatchMessage, msg = " + msg.what);switch (msg.what) {case MSG_INDICATE:BluetoothGattCharacteristic gattCharacteristic3 = (BluetoothGattCharacteristic) msg.obj;boolean ret =mBluetoothGatt.setCharacteristicNotification(gattCharacteristic3, true);BluetoothGattDescriptor descriptor = gattCharacteristic3.getDescriptor(UUID.fromString(LeXinUUID.INDICATE_DES));descriptor.setValue(BluetoothGattDescriptor.ENABLE_INDICATION_VALUE);mBluetoothGatt.writeDescriptor(descriptor);break;}}};
在onCharacteristicChanged ()和onDescriptorWrite()中添加如下打印。
public void onCharacteristicChanged(BluetoothGatt gatt,BluetoothGattCharacteristic characteristic) {super.onCharacteristicChanged(gatt, characteristic);Log.d(TAG, "onCharacteristicChanged, characteristic = " + characteristic + ", value = " + characteristic.getValue());
}public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor,int status) {super.onDescriptorWrite(gatt, descriptor, status);Log.d(TAG, "onDescriptorWrite, descriptor = " + descriptor + ", status = " + status);
}

实际运行结果如下,仅有onDescriptorWrite()的打印,没有onCharateristicChanged()的打印,可能是因为我没有触发到该属性值发起改变的缘故(多次尝试体重测量都没有回调)。

设置notification的方法跟设置indication类似,只需要对对应的descriptor设置BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE。

综上,就是BLE Client端编程主要内容。

4、总结

本文重点是开篇的BLE设备的结构,即characteristic是以service为基础的,descriptor是以characteristic为基础的,我们修改某个characteristic时,先要确定好service是那个。

如果想持续关注本博客内容,请扫描关注个人微信公众号,或者微信搜索:万物互联技术。

Android蓝牙开发系列文章-玩转BLE开发(一)相关推荐

  1. Windows Mobile 开发系列文章收藏 - Windows Mobile 6.x

    收集整理一些Windows Mobile 6.x开发相关文章, 文章及相关代码大部分搜集自网络,版权属于原作者! 智能手机      手机词汇      研发手机基本流程 WAP协议分析(1)     ...

  2. Android蓝牙开发系列文章-蓝牙音箱连接

    经过一段时间的折腾,我的Android Studio终于可以正常工作了,期间遇到的坑记录在了文章<创建Android Studio 3.5第一个工程遇到的坑>. 我们在<Androi ...

  3. Android蓝牙开发系列文章-扫不到蓝牙设备,你的姿势对了吗?

    在写<Android蓝牙开发系列文章-蓝牙音箱连接>时,计划细化出两篇文章,分别是: 关于蓝牙设备类型分类的,这个已经完成了,阅读请点击<Android蓝牙开发系列文章-蓝牙设备类型 ...

  4. Android蓝牙开发系列文章-蓝牙设备类型知多少?

    在写<Android蓝牙开发系列文章-蓝牙音箱连接>时,计划细化出一篇讲解蓝牙设备类型的文章,现在它来了~ 阅读其他内容,可以点击<Android蓝牙开发系列文章-策划篇>,或 ...

  5. Android蓝牙开发系列文章-蓝牙mesh(一)

    在<Android蓝牙开发系列文章-策划篇>中我们对蓝牙专题的内容进行整体规划,现在让我们一点点揭开他的面纱~ 本文是关于蓝牙mesh的首篇文章,由好友CSDN博主yk150915提供,在 ...

  6. Android蓝牙开发系列文章-其实你的手机可以变成一个蓝牙音箱

    本文是蓝牙音频相关的第3篇文章,查阅其他内容,请点击<Android蓝牙开发系列文章-策划篇>. 目前a2dp相关的内容有: <Android蓝牙开发系列文章-AudioTrack播 ...

  7. iOS开发系列文章(持续更新……)

    iOS开发系列的文章,内容循序渐进,包含C语言.ObjC.iOS开发以及日后要写的游戏开发和Swift编程几部分内容.文章会持续更新,希望大家多多关注,如果文章对你有帮助请点赞支持,多谢! 为了方便大 ...

  8. 【微信小程序开发•系列文章一】入门

    本系统文章主要有以下几篇: <[微信小程序开发•系列文章一]入门> <[微信小程序开发•系列文章二]视图层> <[微信小程序开发•系列文章三]数据层> <[微 ...

  9. [转载]C# WinForm开发系列 - 文章索引

    该系列主要整理收集在使用C#开发WinForm应用文章及相关代码, 平时看到大家主要使用C#来开发Asp.Net应用,这方面的文章也特别多,而关于WinForm的文章相对少很多,而自己对WinForm ...

最新文章

  1. Spring Cloud(五)断路器监控(Hystrix Dashboard)
  2. SendInput模拟Win(VK_LWIN)键的问题
  3. leetcode算法题--使序列递增的最小交换次数★
  4. orgchart php,最需要的时候遇见你OrgChart
  5. 放置游戏如何成爆款?我们在《最强蜗牛》中找到了答案
  6. linq to object 、linq to sql 、linq to entity 批量 新增、更新、删除功能扩展
  7. GIS宣传片《地理空间信息革命》视频全集
  8. IntelliJ IDEA 默认快捷键大全
  9. 医院设置(信息学奥赛一本通-T1338)
  10. _Linux学习笔记
  11. shiro执行多个过滤器_Shiro 实战(四) - 过滤器机制
  12. 呼吁成立中国FreeType联盟
  13. 王者荣耀是怎样炼成的(三)unity组件与脚本
  14. svn中文路径 权限设定
  15. 用python扑克随机发牌_Python小应用之发扑克牌
  16. Invalid bound statement (not found): com.cwp.study.dao.user.mapper.UserDao.selectByPrimaryKey解决办法
  17. linux进程调度算法,关于嵌入式Linux系统实时进程调度算法系统详解
  18. SLMi334兼容TLP5214 一款兼容光耦带保护功能单通道隔离IGBT栅极驱动器
  19. matlab mic系数_科学网—最大信息系数 (Maximal Information Coefficient, MIC)详解(1) - 彭勇的博文...
  20. 拯救BUG 10五笔输入法Shift键切换中英文问题

热门文章

  1. 810处理器鸿蒙系统,鸿蒙系统华为机9月发布,四摄+麒麟810处理器,售价2000元左右?...
  2. 2024四川大学计算机考研信息汇总
  3. 双目立体匹配 等 算法 论文 综述 全局局部算法 CSCA NLCA SegmentTree树 DoubleBP Belief-Propagation AD-Census SGM
  4. 深度解读:公有云与私有云有哪些区别?
  5. 宝来悬浮车顶图片_自己动手升级悬浮车顶,简单又便宜!
  6. CodeForces700E Cool Slogans
  7. 不抛弃,不放弃.这就叫“钢七连”
  8. 大平台 or 小应用
  9. mysql group by分钟_sql group by hour 按小时分组统计
  10. 如何维系人脉?快点进来看看吧!