会员登录|免费注册|忘记密码|管理入口 返回主站||保存桌面
Android 蓝牙开发(三) -- 低功耗蓝牙开发手机外设「Android 蓝牙开发(三) -- 低功耗蓝牙开发」
2025-01-11IP属地 湖北8

Android 蓝牙开发(一) – 传统蓝牙聊天室
Android 蓝牙开发(三) – 低功耗蓝牙开发
项目工程BluetoothDemo

前面已经学习了经典蓝牙开发,学习了蓝牙的配对连接和通信,又通过 配置 A2DP 文件,实现手机和蓝牙音响的连接和播放语音。

这篇,我们来学习蓝牙开发的最后一章,低功耗蓝牙 BLE,也就是我们常说的蓝牙 4.0 。
今天要完成的效果如下

中心设备外围设备

与传统蓝牙不同,低功耗蓝主要为了降低设备功耗,支持更低功耗(如心率检测仪,健身设备)等设备进行通信。

Android 在 4.3(API 18) 后将低功耗蓝牙内置,并提供对应的 API,以便于应用发现设备,查询服务和传输信息

低功耗蓝牙有两个角色,分别是中心设备和外围设备

  • 外围设备:指功耗更低的设备,会不断的发出广播,直到与中心设备连接
  • 中心设备:可以进行扫描,寻找外设广播,并从广播中拿到数据

一般我们的手机会充当中心设备,去搜索周围外设的广播,比如健康设备等,然后健康设备就是外围设备,一直发广播,直到中心设备连接上。在Android 5.0 后,手机也可以充当外围设备。

关于 BLE 的关键术语如下

  • 通用属性配置文件(GATT) : GATT 配置文件是一种通用规范,内容主要针对的是 BLE 通信读写时的简短的数据片段,目前 BLE 的通信均以 GATT 为基础
  • 属性协议(ATT) : ATT 是 GATT 的基础,由它来传输属性和特征服务,这些属性都有一个特定的 UUID来作为唯一标识,为通信的基础。
  • GATT Service : 通常中心设备与外围设备要进行,首先要知道服务的 UUID,并与之建立通信,然后通过特征描述符等进行数据通信,这些等后面我们再来理解

首先,你需要使用 BLUETOOTH 的权限,考虑到 LE 信标通常与位置相关联,还须声明 ACCESS_FINE_LOCATION 权限。没有此权限,扫描将无法返回任何结果。

注意:如果您的应用适配 Android 9(API 级别 28)或更低版本,则您可以声明 ACCESS_COARSE_LOCATION 权限而非 ACCESS_FINE_LOCATION 权限。

 

注意!Android 10 需要你开启gps,否则蓝牙不可用

如果你想要你的设备只支持 BLE ,还可以有以下神明

 

如果设置 required=“false”,你也可以在运行时使用 PackageManager.hasSystemFeature() 确定 BLE 的可用性

 
 

关于蓝牙的开启,请参考 Android 蓝牙开发(一) – 传统蓝牙聊天室

要查找 BLE 设备,在 5.0 之前,使用 startLeScan() 方法,它会返回当前设备和外设的广播数据。不过在 5.0 之后,使用 startScan() 去扫描,这里为了方便手机充当外围设备,统一使用 5.0 之后的方法。

而扫描是耗时的,我们应该在扫描到想要的设备后就立即停止或者在规定时间内停止,扫描代码如下

 

可以看到,在 5.0 之后可以通过 ScanSettings 进行扫描的一些设备,比如设置扫描模式 setScanMode ,在 startScan() 中,也可以过滤自己的 UUID,从而省去一些时间。接着在扫描回调中,把能获取名字的设备通过回调给 recyclerview 去回调。

 

效果如下
在这里插入图片描述

上面说到,Android 5.0 之后,手机也能充当外围设备,这里我们也来实践一下

首先,Android要完成一个外围设备,需要完成以下步骤

  1. 编写广播设置,比如发送实践,发送功率等
  2. 编写广播数据,这个是需要的,需要设置 service 的uuid,或者显示名字等
  3. 编写扫描广播(可选),这个广播当中心设备扫描时,数据能被接受的广播,通常我们会在这里编写一些厂商数据
  4. 添加 Gatt service ,用来跟中心设备通信

在发送广播之前,我们可以先对广播进行一些配置

 

可以看到,这里设置成可连接广播,且广播模式设置为 SCAN_MODE_LOW_LATENCY 高功耗模式 ,它共有三种模式

  • SCAN_MODE_LOW_POWER : 低功耗模式,默认此模式,如果应用不在前台,则强制此模式
  • SCAN_MODE_BALANCED : 平衡模式,一定频率下返回结果
  • SCAN_MODE_LOW_LATENCY 高功耗模式,建议应用在前台才使用此模式

发送功率也是可选的

  • 使用高TX功率级别进行广播:AdvertiseSettings#ADVERTISE_TX_POWER_HIGH
  • 使用低TX功率级别进行广播:AdvertiseSettings#ADVERTISE_TX_POWER_LOW
  • 使用中等TX功率级别进行广播:AdvertiseSettings#ADVERTISE_TX_POWER_MEDIUM
  • 使用最低传输(TX)功率级别进行广播:AdvertiseSettings#ADVERTISE_TX_POWER_ULTRA_LOW

接着,是广播数据包

 

比较好理解,让广播显示手机蓝牙名字,并设置服务的 UUID

扫描广播是当中心设备在扫描时,能够显示出来的广播,它可以添加一些必要数据,如厂商数据,服务数据等,注意!与上面的广播一样不能超过31个字节

 

最后,使用 startAdvertising() 就可以开始发送广播了

 

使用 去监听广播开启成功与否

 

此时,你去搜索,就能搜到你手机的蓝牙名称和对应的广播数据了。

但如果外围设备想要与中心设备通信,还需要启动 Gatt service 才行,上面说到,启动Service 时,我们需要配置特征 Characteristic描述符 Descriptor,这里我们来解释以下。

4.3 特征 Characteristic

Characteristic 是Gatt通信最小的逻辑单元,一个 characteristic 包含一个单一 value 变量 和 0-n个用来描述 characteristic 变量的 描述符 Descriptor。与 service 相似,每个 characteristic 用 16bit或者32bit的uuid作为标识,实际的通信中,也是通过 Characteristic 进行读写通信的。

所以为了方便通信,这里我们要添加读写的 Characteristic。

 

描述符 Descriptor

它的定义就是描述 GattCharacteristic 值已定义的属性,比如指定可读的属性,可接受范围等,比如为写的 特征添加描述符

 

接着,把特征添加到服务中,并使用openGattServer() 去打开 Gatt 服务

 

代码比较简单,接着就可以使用 gattServiceCallbak 去监听数据成功与读写的数据了

 
 

上面已经配置了服务端的代码,接着,通过扫描到的广播,使用 BluetoothDevice 的 connectGatt() 方法,来连接 GATT 服务

 

此时,如果你的配置没有出错的话,就可以通过 BluetoothGattCallback 回调连接到设备了

 

代码应该好看懂,就是 onConnectionStateChange() 中的 newState 为 BluetoothProfile.STATE_CONNECTED 时,表示已经连接上了,这个时候,尝试去发现这个服务,如果也能回调 onServicesDiscovered() 方法,则证明此时 GATT 服务已经成功建立,可以进行通信了。

此时就可以来读取外围设备的数据,这个数据是外围设备给中心设备去读的,所以,外围设备的读回调是这样的

外围设备的BluetoothGattServerCallback

 

很简单,就是发送一个 "this is a test " 的字符传

中心设备读

 

如果找得到 GATT 服务,则通过 getCharacteristic() 拿到 GATT 通信的最小单元 Characteristic,通过 mBluetoothGatt?.readCharacteristic(characteristic) 读取数据,这样就会在 BluetoothGattCallback回调的 onCharacteristicRead 拿到数据

 

同理写也一样,这样我们的 BLE 低功耗蓝牙就学习结束了