低功耗蓝牙官方文档
本文章是参考官网,而后加入本身实践中的理解完成!没有看上一篇的读者,能够先阅读一下前一篇,这是一个系列。 官网地址:https://developer.android.com/guide/topics/connectivity/bluetooth-le java
Android 4.3 (API 18 )引入了低功耗蓝牙,应用能够查询周围设备、查询设备的服务、传输信息。android
关键术语和概念
-
通用属性配置文件(GATT Generic Attribute Profile)git
GATT 配置文件是一种传输数据规范,用于在 BLE 链路上发送和接受被称为属性的短数据的通用规范。目前全部低功耗应用配置文件基本都是基于 GATTgithub
-
Bluetooth SIG (蓝牙技术联盟)服务器
是为低功耗设备定义了许多配置文件。配置文件是设备在特定应用程序中的工做方式的规范。设备能够实现多个配置文件。例如,设备能够包含心率监测器和电池水平检测器。并发
定义规范的框架
-
属性协议(ATT Attribute Protocol)ide
GATT 是创建在属性协议(ATT)之上的。也被称为 GATT/ATT 。ATT 通过优化,可在 BLE 设备上使用。为此,它使用了尽量少的字节。每一个属性由通用惟一标识符(UUID)来惟一标识。ATT 传输的属性被格式化为 特征 和 服务优化
-
特征ui
特征包含单个值和描述特征值的 0 ~ n 个描述符。特征值能够被称为类型。相似于类。(是在和 BLE 设备进行通讯的时候主要的操做内容)
-
描述符
是用来定义特征值的已定义属性。用来描述特征值的。例如:描述符能够指定人类可读的描述,特征值的可接受范围或者特征值特定的度量单位
-
服务
服务中包含一系列的特征值。例如,咱们可使用名为 “心率监测器”的服务,其中包括"心率测量"等特征。能够在 bluetooh.org 上找到基于 GATT 的现有配置文件的服务的列表。
角色和责任
Android 设备和 BLE 设备交互时应用的角色和职责
- 中央与外围设备。
- GATT 服务器和 GATT 客户端。肯定了两个设备创建链接后如何进行相互通讯
BLE 权限
应用在使用蓝牙设备的时候必需要声明蓝牙权限 BLUETOOTH
须要这个权限才能够进行蓝牙通讯,例如:请求链接、接受链接、和传输数据。
若是还须要发现或者操做蓝牙设置,则须要声明 BLUETOOTH_ADMIN
权限。使用这个权限的前提是要有 BLUETOOTH
权限。
若是要声明咱们的应用仅适用于支持 BLE 的设备,须要清单文件中作以下声明
<uses-feature android:name = "android.hardware.bluetooth_le" android:required = true />
若是咱们但愿咱们的应用程序在不支持 BLE 的设备上也能够运行的时候,只须要将 true 修改为 false 就能够了。
还能够在代码中做出判断
if(!getPackageManager().hasSystemFeature(PackgeManger.FEATURE_BLUETOOTH_LE)){ // 不支持 BLE 设备 }
BLE 一般和位置有关系,所以还须要声明位置权限 ACCESS_COARSE_LOCATION
或者 ACCESS_FINE_LOCATION
没有这些权限扫描将不会返回任何结果。
设置 BLE
-
得到 BluetoothAdapter
BluetoothAdapter 表明设备本身的蓝牙适配器,整个系统只有一个蓝牙适配器,咱们的应用程序可使用此对象与其交互。
这里的获取方法是经过 BluetoothManager 来获取的
BluetoothManager bluetoothManger = getSystemSerive(Context.BULETOOTH_SERVIcE); BluetoothAdapter bluetoothAdapter = bluetoothManager.getAdapter();
-
启用蓝牙设备
其实这些和普通蓝牙的启动都是同样的。
isEnable()
查看当前是否启用了蓝牙经过 BluetoothAdapter.ACTION_REQUEST_ENABLE 来启动
-
查找 BLE 设备
这一点和发现普通的蓝牙设备是不同的
// 经过 Adapter 的 startLeScan(callBack); 方法来开启扫描 // 若是咱们有指定的蓝牙设备可使用 sartLeScan(UUID[],BluetoothAdapter.LeScanCallBakc) 经过 UUID 来指定 BLe // 这个方法已通过时了,官方文档最新支持的扫描蓝牙的方法是经过一个专门的对象 BluetoothLeScanner 用来开启扫描低功耗蓝牙 BluetoothLeScanner scanner = bluetoothAdapter.getBluetoothLeScanner(); // 这个方法能够有参数,用来过滤要扫描的低功耗蓝牙的,具体的后面讲 scanner.startScan();
只能单独扫描普通蓝牙设备或者 BLE 设备,没有方法同时执行
链接到 GATT 服务器
与 BLE 设备通讯,第一步就是要链接到它,就是链接到该设备的 GATT 服务。使用方法 connectGatt()
有三个参数:Context 对象 autoConnect (表示是否在可用的时候本身链接到 BLE 设备) 还有一个回调,全部的交互都在这个回调里面完成。
调用这个方法会返回一个 BluetoothGatt
对象,经过这个对象进行和 BLE 设备的交互。交互的结果会在回调方法中触发。
public class BluetoothLeService extends Service{ private final static String TAG = BluetoothLeService.class.getSimpleName(); private BluetoothManger bluetoothManger; private BluetoothAdapter bluetoothAdapter; private String bluetoothDeviceAddress; private BluetoothGatt bluetoothGatt; private int connectionState = STATE_DISCONNECTED; private static final int STATE_DISCONNECTED = 0; private static final int STATE_CONNETING = 1; private static final int STATE_CONNECTED = 2; public final static String ACTION_GATT_CONNECTED = "com.example.bluetooth.le.ACTION_GATT_CONNECTED"; public final static String ACTION_GATT_DISCONNECTED = "com.example.bluetooth.le.ACTION_GATT_DISCONNECTED"; public final static String ACTION_GATT_SERVICES_DISCOVERED = "com.example.bluetooth.le.ACTION_GATT_SERVICES_DISCOVERED"; public final satic String ACTION_DATA_AVAILABLE = "com.example.bluetooth.le.ACTION_DATA_AVAILABLE"; public final static String EXTRA_DATA = "com.example.bluetooth.le.EXTRA_DATA"; public final static UUID UUID_HEART_RATE_MEASUREMENT = UUID.formString(SampleGattAttributes.HEART_RATE_MEASURMENT); private final BluetoothGattCallback gattCallback = new BluetoothGattCallback(){ // 你的中央设备链接上 ble 设备后,会回调这个这方法。 @Override public viod onConnectionStateChange(BluetoothGatt gatt,int status,int newState){ String intenAction; if(newState == BluetoothProfile.STATE_CONNECTED){ intentaction = ACTION_GATT_CONNECTED; connectionState = STATE_CONNECTED; broadcastUpdate(intentAction); // 链接上后,紧接着就是要寻找里面 Service bluetoothGatt.discoverServices(); }else if(newState = BluetoothProfile.STATE_STATE_DISCONNECTED{ intentAction = ACTION_GATT_DISCONNECTED; connectionState = STATE_DISCONNECTED; broadcastUpdate(intentAction); } } @Override // service 发现后就会触发这个方法,而后你就须要找到你和 ble 约定好的 service public void onServicesDiscovered(BluetoothGatt gatt,int status){ if(status == BluetoothGatt.GATT_SUCCESS){ broadcastUpdate(ACTION_GATT_SERVICES_DISCOVERED); } } public void onCharacteristicREad(。。。){ } ....... } }
当触发特定的回调的时候,会调用适当的 broadcastUpdate() 辅助方法并向其传递操做。具体的数据解析格式是根据配置文件规范执行的(是你和你的BLE 设备共同约定好的规范)
大致的过程当中:开启链接,而后会触发对应的链接回调,而后发现服务,触发发现服务回调,获取服务内部的特征值,对其读写命令(和 BLE 共同约束的规范)。就是这么一个过程,很简单。
读 BLE 属性
一旦咱们的 Android 设备链接到了 GATT 服务器并发现了服务,咱们就能够在支持的位置读取或者写入属性了。
完成后要记得关闭设备 bluetoothGatt.close();
关于蓝牙框架的一个库:https://github.com/Alex-Jerry/Android-BLE