安卓BLE开发

作者: 空_欢喜 | 来源:发表于2018-10-15 21:27 被阅读211次

    一、BLE基础

    1.基本概念

    BLE(Bluetooth low energy)蓝牙低功耗是蓝牙4.0新增的子规范,其具有低能耗、低成本、低延迟、传输距离长等特点,自安卓4.3(api level 18)起,安卓开始支持BLE。BLE与经典蓝牙对比如下图(图片来自网络):


    BLE和经典蓝牙对比.png

    2.GATT及相关概念

    • GATT: Generic Attribute Profile,即通用属性配置文件,GATT是一种用于收发短片段数据(属性)的通用规范,当前所有的BLE应用配置文件都是基于GATT

    对于BLE,蓝牙SIG组织(Special Interest Group)已定义并采纳了很多基于GATT的配置文件。配置文件(Profile)是一种规定设备在一个特定应用中如何工作的规范,当然,一个设备可实现多种配置文件,比如一台设备可包含心率监测与电量监控等

    • ATT: Attribute Profile,属性协议,GATT就建立在ATT之上。通常二者合称为GATT/ATT。ATT使用尽可能少的字节且每一个属性都被UUID唯一标志
    • Chracteristic:特征,可理解成一种类型,BLE设备间通信主要就使用它。Chracteristic包含一个值(Value)、0-n个描述符(Descriptor)、一系列属性(Property,表明该特征所支持的操作)、一些列与安全相关的Permission等。
    • Descriptor:描述符,描述特征值(Chracteristic中的value)的定义属性。比如特征值的范围、单位等
    • Service:服务,包含一系列Chracteristic。比如心率服务,包含心跳检测特征一个profile可包含n个服务

    GATT层级图如下(图片来自蓝牙官网)

    GATT Profile Hierarchy.png

    3.BLE中角色与职责

    • Central vs. Peripheral:中心设备-外围设备,中心设备和外围设备的概念针对的是BLE连接本身,中心设备负责扫描广播,而外围设备负责发出广播。

    注意:
    1.只有一方支持Central另一方支持Peripheral才能通信
    2.Android 4.3开始支持BLE,但只支持作为中心设备(Central)模式,
    Android 5.0开始两种模式都支持

    • GATT server vs. GATT client:这两种角色取决于BLE连接成功后,两个设备间通信的方式。若A需从B请求数据,则A是client,B是server;反之A是server,B是client

    4.BLE设备间交互方式

    • 完全基于广播
      设备间无需连接而只需外设广播数据即可。该方式主要是让外设把自己的信息发送给多个中心设备。使用该方式的应用叫作Beacon。该方式下有Broadcaster(广播者)和Observer(Scanner扫描者)两种角色。使用该方式最典型的应用就是苹果的 iBeacon,可实现广告推送和室内定位
    • 基于GATT连接
      设备连接后通过GATT来进行通信

    注意:GATT 连接是独占的。即一个 外设同时只能被一个中心设备连接。一旦外设被连接,它就会马上停止广播,这样它就对其他设备不可见了。当连接断开,它又开始广播

    二、安卓BLE通信开发

    用系统api开发参见安卓BLE开发官方文档
    这里介绍使用第三方库EasyBle快速开发BLE

    1.Gradle依赖

    在项目根gradle中添加

    allprojects {
        repositories {
            maven { url 'https://jitpack.io' }
        }
    }
    

    在具体module的gradle中添加

    dependencies {
        implementation 'com.github.Ficat:EasyBle:v1.0.2'
    }
    

    2.使用

    以下是BLE开发常用到的一些基础api

            //是否支持BLE
            BleManager.supportBle(context);
    
            //蓝牙是否打开
            BleManager.isBluetoothOn();
            
            //打开或关闭蓝牙,不显示请求用户授权dialog(一些特殊设备如大部分国产手机除外)
            BleManager.toggleBluetooth(true); 
            
            //显示dialog请求用户打开蓝牙,需在传入的activity的onActivityResult中处理请求结果
            BleManager.enableBluetooth(activity,requestCode);
    

    1)获取BleManager对象

            //获取管理器对象
            BleManager bleManager = BleManager.getInstance(this.getApplication());
    
            //设置ble选项,可多次设置,EasyBle将使用最新的options。比如本次扫描周期
            //为10s,但你想要下一次扫描周期更长一些,则再次调用本方法去设置即可
            BleManager.Options options = new BleManager.Options();
            options.loggable = true; //是否打印日志
            options.connectTimeout = 10000; //连接超时时间
            options.scanPeriod = 12000; //扫描周期
            options.scanDeviceName = "targetDeviceName"; //扫描的目标设备名
            options.scanDeviceAddress = "targetDeviceAddress"; //扫描目标设备地址如"DD:0D:30:00:0D:9B"
            options.scanServiceUuids = serviceUuidArray; //扫描含该服务UUID的目标设备
            bleManager.option(options);
    

    2)扫描

    安卓版本不小于6.0的,扫描必须要有定位权限

            bleManager.startScan(new BleScanCallback() {
                @Override
                public void onLeScan(BleDevice device, int rssi, byte[] scanRecord) {
                    String name = device.name;
                    String address = device.address;
                }
    
                @Override
                public void onStart(boolean startScanSuccess, String info) {
                    if (startScanSuccess) {
                        //开始扫描成功
                    } else {
                        //未能成功开始扫描,可通过info查看详情
                        String failReason = info;
                    }
                }
    
                @Override
                public void onFinish() {
                   
                }
            });
    

    当需要结束扫描时用以下方法结束扫描,建议在扫描到目标设备后停止扫描

            bleManager.stopScan();
    

    3)连接

    
           BleConnectCallback bleConnectCallback = new BleConnectCallback() {
                @Override
                public void onStart(boolean startConnectSuccess, String info, BleDevice device) {
                    if (startConnectSuccess) {
                        //开始连接
                    } else {
                        //未能成功开始连接,可通过info查看详情
                        String failReason = info;
                    }
                }
    
                @Override
                public void onTimeout(BleDevice device) {
    
                }
    
                @Override
                public void onConnected(BleDevice device) {
    
                }
    
                @Override
                public void onDisconnected(BleDevice device) {
    
                }
            };
    
           //通过BleDevice对象连接设备
           bleManager.connect(bleDevice, bleConnectCallback);
    
           //直接通过mac地址连接
           bleManager.connect(address, bleConnectCallback)
    

    当需要断开与设备的连接时可使用以下任一方法断开设备连接

           //断开与指定设备的连接
           bleManager.disconnect(bleDevice);
           
           //传入目标的mac地址断开与该设备的连接
           bleManager.disconnect(address);
    
           //断开所有已连接设备
           bleManager.disconnectAll();
    

    4)设置通知(notify或indicate)

    notify和indicate都使用以下方法

           bleManager.notify(bleDevice, serviceUuid, notifyUuid, new BleNotifyCallback() {
                @Override
                public void onCharacteristicChanged(byte[] data, BleDevice device) {
                  
                }
                
                @Override
                public void onNotifySuccess(String notifySuccessUuid, BleDevice device) {
    
                }
    
                @Override
                public void onFail(int failCode, String info, BleDevice device) {
                 
                }
            });
    

    当需要取消notify或indicate时调用以下方法

           bleManager.cancelNotify(bleDevice, notifyUuid);
    

    5)写入特征数据

           bleManager.write(bleDevice, serviceUuid, writeUuid, data, new BleWriteCallback() {
                @Override
                public void onWrite(byte[] data, BleDevice device) {
    
                }
    
                @Override
                public void onFail(int failCode, String info, BleDevice device) {
    
                }
            });
    

    如果一次性写入的数据长度大于MTU即最大传输单元(默认是20字节),则可以使用下列方法进行分批写入

           bleManager.writeByBatch(bleDevice, serviceUuid, writeUuid, data, lengthPerPackage, new  BleWriteByBatchCallback() {
                @Override
                public void writeByBatchSuccess(byte[] data, BleDevice device) {
    
                }
    
                @Override
                public void onFail(int failCode, String info, BleDevice device) {
    
                }
            });
    

    6)Destroy

    当结束BLE通信时不要忘了调用destroy

           bleManager.destroy();
    

    其他api

           //获取设备支持的服务信息,如果设备尚未连接上则返回值为null
           bleManager.getDeviceServices(bleDevice);
        
           //读取已连接的远程设备信号
           bleManager.readRssi(bleDevice, bleRssiCallback);
    
           //设置MTU
           bleManager.setMtu(bleDevice, mtu, bleMtuCallback);
    
           //读取特征数据
           bleManager.read(bleDevice, serviceUuid, readUuid, bleReadCallback);
    
           //获取当前连接的设备
           bleManager.getConnectedDevices(); 
    
           //判断是否已连接上某台设备
           bleManager.isConnected(address);
    

    相关文章

      网友评论

        本文标题:安卓BLE开发

        本文链接:https://www.haomeiwen.com/subject/sjxtzftx.html