Android ble理解
好的,我们来系统地梳理一下 Android BLE(蓝牙低功耗)的基础概念。理解这些核心概念是进行 BLE 应用开发的第一步。
核心角色:Central(中心设备) 和 Peripheral(外围设备)
BLE 通信基于一种不对称的客户端-服务器模型:
1. Central(中心设备 / 客户端 / 主机)
· 角色:主动扫描、发现并连接到其他设备。通常是手机、平板等功能强大的设备。
· 在 Android 中的体现:你的 Android 应用就是 Central。
· 类比:像在商场里购物的顾客,主动寻找店铺。
2. Peripheral(外围设备 / 服务器 / 从机)
· 角色:被动广播自身的存在,等待被连接。通常是传感器、手环、智能门锁等功耗很低的设备。
· 在 Android 中的体现:从 Android 5.0(API 21)开始,设备也可以作为 Peripheral,但相对复杂,不如 iOS 方便。
· 类比:像商场的店铺,不断播放广告(广播)来吸引顾客。
关键点:在绝大多数 Android BLE 开发场景中,你的手机是 Central,你要连接的智能设备(如手环、心率带)是 Peripheral。
---
核心架构:GATT(通用属性协议)
一旦 Central 和 Peripheral 建立连接,它们之间的所有通信都通过 GATT 协议进行。GATT 定义了一个基于服务(Service) 和特征(Characteristic) 的分层数据结构。
你可以把它想象成一个文件系统:
· Profile(配置文件):一个标准的应用场景规范。例如心率 Profile。它本身不是一个实体,而是定义了一个设备为了实现某种功能(如心率监测)必须包含哪些服务。一个设备可以实现多个 Profile。
· Service(服务):一个独立的功能单元。例如电池服务、设备信息服务。它就像一个文件夹,里面包含了一系列相关的数据。
· Characteristic(特征):服务内部的实际数据点。它是 GATT 通信的基础实体。一个 Characteristic 包含一个值(Value) 和多个描述符(Descriptor)。它就像一个文件。
· Value(值):特征所代表的数据本身,比如电池电量80%,设备名称MyTracker。
· Properties(属性):定义了可以对 Characteristic 进行什么操作。例如:
· READ:可以读取这个值。
· WRITE:可以写入这个值(发送命令)。
· NOTIFY:当值改变时,Peripheral 会主动通知 Central(最常用、最节能的通信方式)。
· INDICATE:类似 NOTIFY,但需要 Central 确认,更可靠。
· Descriptor(描述符):用于描述 Characteristic 的元数据。最重要的一个是 CCCD(客户端特征配置描述符),它用于开启或关闭某个 Characteristic 的 NOTIFY 或 INDICATE 功能。
关系总结:
Profile-> 包含多个 Service -> 包含多个 Characteristic -> 包含一个 Value 和多个 Descriptor(最重要的是 CCCD)。
---
Android BLE 开发关键类
这些类位于 android.bluetooth 包中,是与上述概念的直接映射。
1. BluetoothAdapter
· 代表设备本身的蓝牙硬件。
· 通过 BluetoothManager 获取:(BluetoothManager) getSystemService(BLUETOOTH_SERVICE).getAdapter()。
· 核心操作:检查蓝牙是否开启、开启/关闭蓝牙、开始扫描设备。
2. BluetoothDevice
· 代表一个远端的蓝牙设备(即 Peripheral)。
· 通常在扫描回调中获取。
· 核心操作:获取设备名称、MAC 地址,最重要的方法是 connectGatt(),用于建立 GATT 连接。
3. BluetoothGatt
· 这是 BLE 通信的核心类。一旦通过 BluetoothDevice.connectGatt() 成功连接,你就会得到一个 BluetoothGatt 实例。
· 它代表了与 Peripheral 的 GATT 连接。所有后续的服务发现、读写、通知等操作都通过它来完成。
· 核心操作:discoverServices(), readCharacteristic(), writeCharacteristic(), setCharacteristicNotification()。
4. BluetoothGattService
· 代表一个 GATT 服务。
· 通过 BluetoothGatt.getService(UUID) 获取。
5. BluetoothGattCharacteristic
· 代表一个 GATT 特征。
· 包含其 value, properties, descriptors。
· 通过 BluetoothGattService.getCharacteristic(UUID) 获取。
6. BluetoothGattDescriptor
· 代表一个描述符。
· 最重要的操作是向 CCCD 写入 BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE 来开启通知。
7. BluetoothLeScanner 和 ScanCallback(API 21+ 推荐)
· 用于扫描 BLE 设备。
· BluetoothLeScanner 通过 BluetoothAdapter.getBluetoothLeScanner() 获取。
· 扫描结果在 ScanCallback 中返回。
---
典型 BLE 交互流程(Central 端)
1. 权限检查
· 在 AndroidManifest.xml 中声明 BLUETOOTH, BLUETOOTH_ADMIN, 以及(对于 Android 12+)BLUETOOTH_CONNECT, BLUETOOTH_SCAN。对于定位相关的权限(ACCESS_FINE_LOCATION 等)在旧版本中也是必须的,因为扫描设备可以用于定位。
2. 扫描设备
· 获取 BluetoothLeScanner。
· 创建 ScanSettings 和 ScanFilter(可选)。
· 启动扫描,在 ScanCallback.onScanResult 中获取到的 ScanResult 里包含 BluetoothDevice。
3. 连接设备
· 调用 bluetoothDevice.connectGatt(context, autoConnect, bluetoothGattCallback)。
· autoConnect 设为 false 表示直接连接,设为 true 表示在设备可用时自动连接(更耗电)。
· 连接状态回调在 BluetoothGattCallback 中。
4. 发现服务
· 在 BluetoothGattCallback.onConnectionStateChange 中,当状态变为 STATE_CONNECTED 时,调用 bluetoothGatt.discoverServices()。
· 服务发现完成后,会触发 BluetoothGattCallback.onServicesDiscovered。
5. 读写操作和开启通知
· 在 onServicesDiscovered 之后,通过 bluetoothGatt 获取对应的 Service 和 Characteristic。
· 读:bluetoothGatt.readCharacteristic(characteristic),结果在 onCharacteristicRead 回调中。
· 写:bluetoothGatt.writeCharacteristic(characteristic),写入完成在 onCharacteristicWrite 回调中。
· 开启通知:
a. bluetoothGatt.setCharacteristicNotification(characteristic, true) // 启用本地通知
b. 获取该 Characteristic 的 CCCD 描述符。
c. 向 CCCD 写入 ENABLE_NOTIFICATION_VALUE 或 ENABLE_INDICATION_VALUE。
d. 当 Peripheral 的数据发生变化时,会触发 onCharacteristicChanged 回调。
6. 断开连接
· 调用 bluetoothGatt.disconnect() 然后调用 bluetoothGatt.close() 释放资源。
---
重要注意事项
· 异步操作:所有 BLE 操作(连接、读、写等)都是异步的。调用一个方法后,你必须在对应的 BluetoothGattCallback 方法中等待结果,不要在主线程执行耗时操作。
· 线程安全:BluetoothGatt 的方法不是线程安全的,建议使用队列来序列化你的 BLE 命令。
· UUID:服务、特征、描述符都由唯一的 128 位 UUID 标识。蓝牙技术联盟定义了一些标准的 UUID(如 0x180D 代表心率服务),它们有简短的 16 位格式。自定义的服务和特征则使用完整的 128 位 UUID。
· API 级别:不同 Android 版本对 BLE 的支持有所不同,特别是 Android 6.0(权限)、Android 8.0(后台限制)和 Android 10/12(权限模型更新)带来了很多变化。
掌握这些基础概念后,你就可以开始着手编写你的第一个 Android BLE 应用了。建议从官方示例和文档开始,逐步实践。
