内容提要
本文介绍在Flutter中使用flutter_blue_plus包实现蓝牙低功耗(BLE)通信。内容涵盖平台权限配置、设备扫描、连接与MTU协商、服务发现、数据读写、通知订阅、字节编解码、配对绑定、断线重连、后台运行及错误处理。文章强调理解GATT层级结构,并推荐将BLE逻辑封装为服务类,通过流管理状态,同时提供测试调试技巧和性能优化建议,帮助开发者构建可靠的BLE应用。
延伸解读
GATT层级是理解BLE的关键
文章强调,BLE数据模型基于GATT层级:设备包含服务,服务包含特征,特征可能包含描述符。理解这一结构是编写BLE代码的前提。开发者需要先发现服务,再定位特征,然后进行读写或订阅。这种层级关系与传统的流式通信不同,需要适应。
平台差异与权限配置
Android和iOS在BLE权限配置上差异显著。Android 12以上需声明BLUETOOTH_SCAN和BLUETOOTH_CONNECT权限,并可通过neverForLocation避免请求位置权限;而iOS只需在Info.plist中提供用途描述。开发者需根据目标平台仔细配置,否则应用可能崩溃或被应用商店拒绝。
MTU协商与数据分块
默认MTU为23字节,有效载荷仅20字节。Android可通过requestMtu(512)请求更大MTU,iOS则自动协商。发送大数据时,需按MTU-3字节分块,并使用带响应的写入以确保可靠传输。忽略MTU限制可能导致数据发送失败或性能下降。
通知订阅与资源管理
通知机制允许外设主动推送数据,避免轮询,但需正确管理订阅生命周期。订阅前应检查特征是否支持通知,并先设置监听再启用通知,以免错过首个数据。断开连接时需取消订阅,防止资源泄漏和电池消耗。
Q&A
Flutter中如何配置Android的蓝牙权限?
在AndroidManifest.xml中添加BLUETOOTH_SCAN、BLUETOOTH_CONNECT、BLUETOOTH_ADVERTISE(Android 12+),以及BLUETOOTH、BLUETOOTH_ADMIN、ACCESS_FINE_LOCATION(Android 11及以下,需设置maxSdkVersion="30")。同时设置minSdkVersion至少为21。
iOS上使用蓝牙需要哪些配置?
在Info.plist中添加NSBluetoothAlwaysUsageDescription和NSBluetoothPeripheralUsageDescription描述字符串,若需后台运行则添加UIBackgroundModes并包含bluetooth-central。
flutter_blue_plus中如何扫描BLE设备?
调用FlutterBluePlus.startScan,可设置超时和过滤条件(如withServices、withNames),并监听onScanResults流获取结果。扫描前需检查蓝牙适配器状态和请求权限。
如何连接BLE设备并协商MTU?
先停止扫描,然后调用device.connect()连接,连接成功后使用device.requestMtu(512)(Android)或读取device.mtu(iOS)协商MTU。注意MTU默认23字节,减去3字节开销后有效载荷为20字节。
如何读取和写入BLE特征值?
读取前检查特征是否可读,调用c.read()获取字节列表。写入时根据特征属性选择write(带响应)或writeWithoutResponse(无响应),大块数据需按MTU-3字节分块写入。
如何订阅BLE通知以接收实时数据?
先检查特征是否支持notify或indicate,然后监听c.onValueReceived流,最后调用c.setNotifyValue(true)启用通知。取消订阅时调用setNotifyValue(false)并取消流订阅。
BLE中GATT、服务和特征是什么关系?
GATT是BLE的数据模型,设备暴露一个层级数据库:服务(Service)包含特征(Characteristic),特征有属性(如读、写、通知)和描述符(如CCCD)。手机作为GATT客户端读写这些数据。
如何处理BLE连接断开和重连?
监听device.connectionState流,当状态变为disconnected时,可获取断开原因。重连需重新调用connect(),并重新发现服务。建议封装重连逻辑,并处理错误。