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

我们在《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() {
    @Override
    public 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
    @Override
    public 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_CONNECTED
    public 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改变时会回调到这里,当然,前提是设置了//notification
    public 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
            @Override
            public 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
            @Override
            public 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是那个。

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

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值