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

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层级图如下(图片来自蓝牙官网)

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);
网友评论