Flutter BLE开发避坑指南:从权限申请到设备连接,我踩过的那些坑(flutter_blue_plus实战)

张开发
2026/4/7 2:58:38 15 分钟阅读

分享文章

Flutter BLE开发避坑指南:从权限申请到设备连接,我踩过的那些坑(flutter_blue_plus实战)
Flutter BLE开发避坑指南从权限申请到设备连接我踩过的那些坑flutter_blue_plus实战在物联网设备遍地开花的今天蓝牙低功耗BLE技术已经成为移动开发者的必备技能。作为Flutter开发者我们既享受着跨平台开发的高效又不得不面对原生平台差异带来的各种惊喜。本文将分享我在实际项目中积累的Flutter BLE开发经验特别是那些官方文档不会告诉你的坑和解决方案。1. 权限配置Android 12的新战场很多开发者第一次接触Flutter BLE开发时往往会在权限配置这个看似简单的环节栽跟头。特别是Android 12引入的蓝牙权限分级管理让不少老项目在系统升级后突然罢工。1.1 Android权限的进化史Android的蓝牙权限管理经历了三个阶段Android 11及之前只需要BLUETOOTH和BLUETOOTH_ADMIN两个基本权限Android 12引入BLUETOOTH_CONNECT、BLUETOOTH_SCAN和BLUETOOTH_ADVERTISE三个新权限Android 13进一步收紧位置权限要求关键点从Android 12开始即使只是连接已配对的设备也需要BLUETOOTH_CONNECT权限。而扫描设备则需要BLUETOOTH_SCAN和位置权限。1.2 正确的AndroidManifest配置manifest !-- 基础蓝牙权限 -- uses-permission android:nameandroid.permission.BLUETOOTH / uses-permission android:nameandroid.permission.BLUETOOTH_ADMIN / !-- Android 12新增权限 -- uses-permission android:nameandroid.permission.BLUETOOTH_CONNECT / uses-permission android:nameandroid.permission.BLUETOOTH_SCAN / uses-permission android:nameandroid.permission.BLUETOOTH_ADVERTISE / !-- 位置权限扫描必需 -- uses-permission android:nameandroid.permission.ACCESS_FINE_LOCATION / uses-permission android:nameandroid.permission.ACCESS_COARSE_LOCATION / !-- Android 10需要声明前台服务权限 -- uses-permission android:nameandroid.permission.FOREGROUND_SERVICE / /manifest提示对于Android 13设备如果只使用蓝牙连接功能而不需要扫描可以添加以下属性避免位置权限请求uses-permission android:nameandroid.permission.BLUETOOTH_SCAN android:usesPermissionFlagsneverForLocation /1.3 iOS权限的特殊性iOS的权限管理看似简单实则暗藏玄机dict keyNSBluetoothAlwaysUsageDescription/key string我们需要访问蓝牙来连接您的设备/string keyNSBluetoothPeripheralUsageDescription/key string我们需要访问蓝牙来连接您的设备/string keyNSLocationWhenInUseUsageDescription/key string我们需要位置权限来发现附近的蓝牙设备/string /dict特别注意从iOS 13开始即使用户拒绝了位置权限应用仍然可以扫描蓝牙设备但无法获取设备的RSSI信号强度值。这会影响基于信号强度的距离判断功能。2. 设备连接的艺术超时与重连策略连接BLE设备可能是整个开发过程中最令人抓狂的环节。设备无响应、连接不稳定、服务发现失败...这些问题我都遇到过。2.1 连接超时设置flutter_blue_plus默认的连接超时是30秒这在实际应用中显然太长了。合理的做法是Futurebool connectWithTimeout(BluetoothDevice device, {Duration timeout const Duration(seconds: 8)}) async { try { await device.connect(timeout: timeout, autoConnect: false); return true; } catch (e) { print(连接超时: $e); await device.disconnect(); return false; } }经验值室内环境8-10秒复杂环境15秒首次配对可适当延长至20秒2.2 自动重连的陷阱很多开发者喜欢启用autoConnect参数但这在实际应用中往往适得其反// 不推荐的做法 await device.connect(autoConnect: true); // 更好的做法 Futurevoid smartReconnect(BluetoothDevice device) async { int retryCount 0; while (retryCount 3) { try { await device.connect(timeout: Duration(seconds: 5)); return; } catch (e) { retryCount; await Future.delayed(Duration(seconds: 1)); } } throw Exception(重连失败); }为什么避免autoConnect无法控制重试间隔无法获取重试状态可能造成电池快速耗尽2.3 服务发现的坑即使连接成功服务发现环节也可能失败。这是我在项目中总结的健壮性方案FutureListBluetoothService discoverServicesWithRetry( BluetoothDevice device) async { ListBluetoothService services []; int retry 0; while (services.isEmpty retry 3) { try { services await device.discoverServices(); if (services.isEmpty) { await device.disconnect(); await device.connect(); } } catch (e) { await device.disconnect(); await device.connect(); } retry; await Future.delayed(Duration(milliseconds: 500)); } if (services.isEmpty) { throw Exception(无法发现服务); } return services; }3. 跨平台差异iOS和Android的那些不同Flutter的魅力在于跨平台但BLE的实现却因平台而异。以下是主要差异对比特性AndroidiOS后台扫描需要前台服务受系统严格限制连接保持相对稳定容易被系统断开扫描间隔可设置较短建议不低于2秒设备识别支持MAC地址只能获取UUID配对绑定支持程序化配对需要用户手动确认3.1 扫描策略优化针对平台差异我们需要实现不同的扫描策略Futurevoid startSmartScan() async { if (Platform.isAndroid) { // Android可以设置更积极的扫描参数 await FlutterBluePlus.startScan( timeout: Duration(seconds: 10), androidScanMode: AndroidScanMode.lowLatency ); } else { // iOS需要更保守的设置 await FlutterBluePlus.startScan( timeout: Duration(seconds: 15), allowDuplicates: false ); } }3.2 连接状态监听iOS和Android的连接状态监听也有差异StreamSubscriptionBluetoothConnectionState? _connectionSubscription; void listenToConnection(BluetoothDevice device) { _connectionSubscription device.connectionState.listen((state) { if (Platform.isAndroid) { // Android的连接状态变化更及时 _handleAndroidState(state); } else { // iOS可能需要额外的处理 _handleIOSState(state); } }); } void _handleAndroidState(BluetoothConnectionState state) { // Android特有的状态处理 } void _handleIOSState(BluetoothConnectionState state) { // iOS可能需要额外的超时判断 if (state BluetoothConnectionState.connected) { _startIOSConnectionTimer(); } }4. 数据通信的可靠性保障BLE通信不像TCP那样可靠数据包可能丢失、乱序或重复。以下是确保通信可靠的关键点。4.1 数据分包策略当发送超过20字节的数据时需要实现分包逻辑Futurevoid sendLargeData(BluetoothCharacteristic characteristic, Listint data) async { const chunkSize 20; // BLE单包最大长度 for (var i 0; i data.length; i chunkSize) { final end (i chunkSize data.length) ? i chunkSize : data.length; final chunk data.sublist(i, end); try { await characteristic.write(chunk); await Future.delayed(Duration(milliseconds: 20)); // 包间隔 } catch (e) { throw Exception(发送失败: $e); } } }4.2 数据接收的完整性检查建议为数据包添加简单的协议头// 发送端 Futurevoid sendPacket(BluetoothCharacteristic characteristic, Listint payload) async { final header [ 0xAA, 0xBB, // 起始标志 payload.length, // 长度 ]; final checksum _calculateChecksum(payload); final packet [...header, ...payload, checksum]; await characteristic.write(packet); } // 接收端 Listint _buffer []; void onDataReceived(Listint value) { _buffer.addAll(value); while (_buffer.length 4) { // 最小包长度 if (_buffer[0] 0xAA _buffer[1] 0xBB) { final length _buffer[2]; if (_buffer.length 3 length 1) { // 头数据校验 final payload _buffer.sublist(3, 3 length); final checksum _buffer[3 length]; if (_calculateChecksum(payload) checksum) { _handleCompletePacket(payload); _buffer _buffer.sublist(3 length 1); } else { _buffer.removeAt(0); // 校验失败跳过第一个字节 } } else { break; // 数据不完整等待更多数据 } } else { _buffer.removeAt(0); // 无效起始字节跳过 } } }4.3 通知订阅的最佳实践订阅通知是BLE通信的核心但有几个容易忽略的点Futurevoid setupNotification(BluetoothCharacteristic characteristic) async { // 先取消可能存在的旧订阅 try { await characteristic.setNotifyValue(false); await Future.delayed(Duration(milliseconds: 100)); } catch (_) {} // 设置新的订阅 await characteristic.setNotifyValue(true); // 监听数据 characteristic.value.listen((data) { if (data.isNotEmpty) { _handleIncomingData(data); } }); // iOS可能需要额外的激活操作 if (Platform.isIOS) { await characteristic.read(); } }5. 实战中的性能优化BLE通信对性能敏感不当的实现会导致连接不稳定、高延迟和高耗电。5.1 连接参数优化BLE连接参数直接影响通信质量和功耗参数推荐值说明连接间隔15-30ms平衡响应速度和功耗从机延迟0除非有特殊省电需求超时时间2000-4000ms防止意外断开在Android上可以通过反射调整这些参数Futurevoid updateConnectionParameters(BluetoothDevice device) async { if (Platform.isAndroid) { try { final method await device.methodChannel .invokeMethod(updateConnectionParameters, { intervalMin: 16, // 16*1.2520ms intervalMax: 24, // 24*1.2530ms latency: 0, timeout: 200, // 200*102000ms }); print(参数更新成功); } catch (e) { print(参数更新失败: $e); } } }5.2 后台处理策略应用进入后台时BLE行为会受到限制Android方案void _handleAppLifecycle(AppLifecycleState state) { if (state AppLifecycleState.paused) { // 启动前台服务 FlutterBluePlus.startForegroundService( title: 蓝牙连接保持中, content: 正在与设备保持连接 ); } else if (state AppLifecycleState.resumed) { // 停止前台服务 FlutterBluePlus.stopForegroundService(); } }iOS方案在Xcode中启用Background Modes - Uses Bluetooth LE accessories实现适当的后台任务处理5.3 功耗优化技巧扫描间歇扫描10秒暂停5秒连接后立即降低扫描频率使用autoConnect: false虽然看起来矛盾但实际更省电及时释放不再使用的特征值和描述符引用void optimizePowerUsage() { // 连接后调整扫描策略 if (_isConnected) { FlutterBluePlus.stopScan(); _updateConnectionInterval(_device, 30); // 增大连接间隔 } // 定期检查连接状态 _timer Timer.periodic(Duration(minutes: 5), (_) { if (!_isConnected) { _reconnectWithBackoff(); } }); }6. 调试技巧与问题排查当BLE不按预期工作时系统化的排查方法能节省大量时间。6.1 常见问题检查清单设备不可见确认设备未被其他应用连接检查设备是否处于可发现模式验证设备广播间隔是否合适建议20-100ms连接不稳定检查周围WiFi和蓝牙干扰尝试调整连接参数验证天线位置和方向数据传输错误确认MTU大小检查特征值的属性writeWithResponse/noResponse验证数据分包逻辑6.2 实用调试工具Androidadb shell dumpsys bluetooth_manager adb logcat -v time -s BluetoothAdapteriOSXcode - Window - Devices and Simulators - 查看设备日志使用LightBlue等专业工具验证蓝牙通信6.3 Flutter调试技巧在main.dart中添加全局错误捕获void main() { FlutterBluePlus.setLogLevel(LogLevel.verbose); FlutterError.onError (details) { if (details.stack ! null) { _logBleError(details.exception, details.stack!); } }; runApp(MyApp()); } void _logBleError(dynamic error, StackTrace stack) { final message BLE Error: ${error.toString()} Stack Trace: ${stack.toString()} ; debugPrint(message); // 也可以发送到服务器或保存到文件 }7. 用户体验优化建议技术实现只是基础优秀的用户体验才能让产品脱颖而出。7.1 连接状态可视化建议在UI中明确显示以下状态enum ConnectionState { disconnected, connecting, authenticating, discoveringServices, ready, disconnecting } // 在UI中 Widget buildConnectionState(ConnectionState state) { final colors { ConnectionState.disconnected: Colors.red, ConnectionState.connecting: Colors.orange, // ...其他状态 }; return Container( width: 12, height: 12, decoration: BoxDecoration( color: colors[state], shape: BoxShape.circle, ), ); }7.2 智能重连机制结合指数退避算法的重连策略class SmartReconnector { final BluetoothDevice device; int _attempt 0; Timer? _timer; SmartReconnector(this.device); Futurevoid reconnect() async { _attempt; final delay Duration(seconds: min(_attempt * 2, 30)); // 最大30秒 try { await device.connect(timeout: Duration(seconds: 5)); _attempt 0; // 重置尝试计数 } catch (e) { _timer Timer(delay, reconnect); } } void cancel() { _timer?.cancel(); _attempt 0; } }7.3 用户引导设计在关键节点提供清晰的引导void checkPermissions() async { final missing await _checkMissingPermissions(); if (missing.isNotEmpty) { showDialog( context: context, builder: (ctx) PermissionGuideDialog(missing), ); } } class PermissionGuideDialog extends StatelessWidget { final ListString permissions; const PermissionGuideDialog(this.permissions, {super.key}); override Widget build(BuildContext context) { return AlertDialog( title: Text(需要权限), content: Column( children: permissions.map((p) _buildPermissionItem(p)).toList(), ), actions: [ TextButton( onPressed: () Navigator.pop(context), child: Text(取消), ), TextButton( onPressed: () _openAppSettings(), child: Text(去设置), ), ], ); } Widget _buildPermissionItem(String permission) { final info { BLUETOOTH_CONNECT: 用于连接蓝牙设备, LOCATION: 用于发现附近的蓝牙设备, // 其他权限说明 }; return ListTile( leading: Icon(Icons.bluetooth), title: Text(permission), subtitle: Text(info[permission] ?? ), ); } }8. 进阶话题与未来展望随着Flutter和BLE技术的不断发展一些新特性值得关注。8.1 多设备连接管理实现稳定可靠的多设备连接需要考虑class DeviceManager { final MapString, BluetoothDevice _devices {}; final MapString, StreamSubscription _subscriptions {}; Futurevoid addDevice(BluetoothDevice device) async { final id device.remoteId.str; if (_devices.containsKey(id)) return; _devices[id] device; _subscriptions[id] device.connectionState.listen((state) { _handleDeviceState(id, state); }); await device.connect(); } Futurevoid removeDevice(String deviceId) async { final sub _subscriptions[deviceId]; await sub?.cancel(); final device _devices[deviceId]; await device?.disconnect(); _devices.remove(deviceId); _subscriptions.remove(deviceId); } void _handleDeviceState(String deviceId, BluetoothConnectionState state) { // 统一处理所有设备状态变化 } }8.2 蓝牙Mesh网络虽然flutter_blue_plus目前不支持Mesh但可以通过平台通道实现// Dart端 Futurevoid joinMeshNetwork() async { try { await MethodChannel(ble_mesh).invokeMethod(joinMesh); } on PlatformException catch (e) { print(Mesh网络错误: ${e.message}); } } // Android端 Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); GeneratedPluginRegistrant.registerWith(this); new MethodChannel(getFlutterView(), ble_mesh).setMethodCallHandler( (call, result) - { if (call.method.equals(joinMesh)) { // 实现Mesh网络加入逻辑 } } ); }8.3 与系统蓝牙设置的深度集成提供更好的系统集成体验Futurevoid openBluetoothSettings() async { if (Platform.isAndroid) { await IntentLauncher.launchIntent( action: android.settings.BLUETOOTH_SETTINGS ); } else if (Platform.isIOS) { await UIApplication.sharedApplication.openUrl( NSURL.URLWithString(App-Prefs:rootBluetooth) ); } }9. 项目架构建议良好的架构能显著提升BLE应用的维护性和扩展性。9.1 分层架构示例lib/ ├── bluetooth/ │ ├── ble_core/ # 核心蓝牙操作 │ ├── ble_service/ # 业务服务 │ ├── models/ # 数据模型 │ └── utils/ # 工具类 ├── pages/ # 界面层 └── main.dart9.2 状态管理方案使用Riverpod的推荐方案final bleDeviceProvider StateNotifierProviderBleDeviceNotifier, BleState((ref) { return BleDeviceNotifier(); }); class BleDeviceNotifier extends StateNotifierBleState { BleDeviceNotifier() : super(BleState.disconnected()); Futurevoid connect(String deviceId) async { state BleState.connecting(); try { final device await _connectToDevice(deviceId); state BleState.connected(device); } catch (e) { state BleState.error(e.toString()); } } } class BleState { final bool isConnected; final bool isLoading; final String? error; final BluetoothDevice? device; BleState._(this.isConnected, this.isLoading, this.error, this.device); factory BleState.disconnected() BleState._(false, false, null, null); factory BleState.connecting() BleState._(false, true, null, null); factory BleState.connected(BluetoothDevice device) BleState._(true, false, null, device); factory BleState.error(String message) BleState._(false, false, message, null); }9.3 测试策略针对BLE模块的测试方案void main() { group(BLE连接测试, () { late MockFlutterBluePlus mockBlue; late BleManager bleManager; setUp(() { mockBlue MockFlutterBluePlus(); bleManager BleManager(mockBlue); }); test(成功连接设备, () async { when(mockBlue.connect(any)) .thenAnswer((_) Future.value()); final result await bleManager.connect(device1); expect(result, true); }); test(连接超时处理, () async { when(mockBlue.connect(any)) .thenThrow(TimeoutException()); final result await bleManager.connect(device1); expect(result, false); }); }); }10. 真实案例智能家居控制应用分享一个实际项目中的架构设计该项目需要控制多种智能家居设备。10.1 设备抽象层设计abstract class BleDevice { final BluetoothDevice device; final MapString, BluetoothCharacteristic characteristics; BleDevice(this.device, this.characteristics); Futurevoid connect(); Futurevoid disconnect(); Futurevoid sendCommand(Listint command); StreamListint get responseStream; } class SmartBulb extends BleDevice { SmartBulb(super.device, super.characteristics); Futurevoid setColor(Color color) async { final command _buildColorCommand(color); await sendCommand(command); } Listint _buildColorCommand(Color color) { return [ 0x01, // 命令头 color.red, color.green, color.blue, _calculateChecksum([color.red, color.green, color.blue]) ]; } }10.2 设备工厂模式class DeviceFactory { static FutureBleDevice? createDevice(BluetoothDevice device) async { final services await device.discoverServices(); final characteristics _findCharacteristics(services); if (_isSmartBulb(characteristics)) { return SmartBulb(device, characteristics); } else if (_isThermostat(characteristics)) { return Thermostat(device, characteristics); } return null; } static bool _isSmartBulb(MapString, BluetoothCharacteristic chars) { return chars.containsKey(color_control); } }10.3 场景联动实现class SceneManager { final MapString, BleDevice _devices; SceneManager(this._devices); Futurevoid executeScene(String sceneId) async { final scene _loadScene(sceneId); await _executeParallel(scene.commands); } Futurevoid _executeParallel(ListSceneCommand commands) async { await Future.wait(commands.map((cmd) { final device _devices[cmd.deviceId]; return device?.sendCommand(cmd.data); })); } }11. 性能监控与优化持续监控应用性能可以提前发现潜在问题。11.1 关键指标监控class BleMetrics { static final _connectTimes int[]; static final _transferRates double[]; static void recordConnectTime(int milliseconds) { _connectTimes.add(milliseconds); _trimList(_connectTimes); } static void recordTransferRate(double bytesPerSecond) { _transferRates.add(bytesPerSecond); _trimList(_transferRates); } static void _trimList(List list) { if (list.length 100) { list.removeRange(0, list.length - 100); } } static double get averageConnectTime { return _connectTimes.isEmpty ? 0 : _connectTimes.reduce((a, b) a b) / _connectTimes.length; } }11.2 内存泄漏预防常见的BLE相关内存泄漏点class ConnectionHandler { StreamSubscription? _connectionSub; StreamSubscription? _dataSub; void init(BluetoothDevice device) { _connectionSub device.connectionState.listen(_handleState); _dataSub device.charactersitic?.value.listen(_handleData); } void dispose() { _connectionSub?.cancel(); _dataSub?.cancel(); } // 在Widget的dispose方法中调用 override void dispose() { _connectionHandler.dispose(); super.dispose(); } }11.3 自动化性能测试使用flutter_driver进行性能测试void main() { group(BLE性能测试, () { late FlutterDriver driver; setUpAll(() async { driver await FlutterDriver.connect(); }); tearDownAll(() async { await driver.close(); }); test(连接时间基准测试, () async { final timeline await driver.traceAction(() async { await driver.tap(find.byValueKey(connectButton)); await driver.waitFor(find.text(已连接)); }); final summary TimelineSummary.summarize(timeline); await summary.writeTimelineToFile(ble_connect, pretty: true); expect(summary.computeAverageFrameBuildTimeMillis, lessThan(16)); }); }); }12. 安全最佳实践BLE通信虽然方便但也存在安全风险。12.1 基础安全措施class SecureBleManager { final _encryptionKey your_encryption_key; FutureListint encryptData(Listint data) async { // 实现简单的加密逻辑 return data.map((byte) byte ^ _encryptionKey.codeUnitAt(0)).toList(); } FutureListint decryptData(Listint data) async { return encryptData(data); // 异或加密解密相同 } Futurevoid secureWrite( BluetoothCharacteristic characteristic, Listint data) async { final encrypted await encryptData(data); await characteristic.write(encrypted); } }12.2 配对绑定策略Android上的安全配对示例Futurevoid securePair(BluetoothDevice device) async { if (Platform.isAndroid) { try { final bonded await device.methodChannel.invokeMethod( createBond, {secure: true} ); if (bonded) { print(安全配对成功); } } catch (e) { print(配对失败: $e); } } }12.3 特征值权限验证Futurevoid verifyCharacteristic(BluetoothCharacteristic characteristic) async { if (!characteristic.properties.read) { throw Exception(特征值不可读); } if (!characteristic.properties.write) { throw Exception(特征值不可写); } if (characteristic.properties.indicate) { print(支持Indicate更可靠); } }13. 异常处理与恢复健壮的异常处理是BLE应用稳定的关键。13.1 常见异常分类enum BleError { deviceNotFound, connectionLost, serviceDiscoveryFailed, invalidData, permissionDenied, platformSpecific } BleError classifyError(dynamic error) { if (error is PlatformException) { switch (error.code) { case device_not_found: return BleError.deviceNotFound; case connection_lost: return BleError.connectionLost; default: return BleError.platformSpecific; } } // 其他错误分类逻辑 }13.2 异常恢复策略class ErrorHandler { static Futurevoid handle(BleError error) async { switch (error) { case BleError.connectionLost: await _reconnect(); break; case BleError.permissionDenied: await _requestPermissions(); break; // 其他错误处理 } } static Futurevoid _reconnect() async { // 实现智能重连逻辑 } }13.3 用户友好的错误提示Widget buildErrorWidget(BleError error) { final messages { BleError.deviceNotFound: 设备未找到请确保设备已开启并可被发现, BleError.connectionLost: 连接断开正在尝试重新连接..., // 其他错误消息 }; return Column( children: [ Icon(Icons.error, color: Colors.red), Text(messages[error] ?? 发生未知错误), ], ); }14. 平台特定优化针对不同平台的优化可以显著提升用户体验。14.1 Android特定优化后台限制处理void handleAndroidBackground() { if (Platform.isAndroid) { Workmanager().registerPeriodicTask( ble_keepalive, bleBackgroundTask, frequency: Duration(minutes: 15), constraints: Constraints( networkType: NetworkType.connected, ), ); } }14.2 iOS特定优化后台模式配置keyUIBackgroundModes/key array stringbluetooth-central/string stringbluetooth-peripheral/string /array恢复连接处理void restoreCentralManager() { if (Platform.isIOS) { FlutterBluePlus.setRestoreIdentifier(your_app_unique_id); } }14.3 平台通道高级用法实现平台特定功能Futureint getAndroidBleSdkVersion() async { if (Platform.isAndroid) { try { return await MethodChannel(ble_advanced) .invokeMethod(getSdkVersion); } catch (e) { return -1; } } return 0; }15. 社区资源与进阶学习Flutter BLE生态在不断进化以下资源可以帮助持续提升。15.1 优质开源项目参考flutter_blue_plus当前最活跃的Flutter BLE插件flutter_reactive_ble另一种实现思路的BLE插件ble_uart_example串口通信的完整示例15.2 调试工具推荐工具名称平台特点nRF ConnectAndroid功能全面的专业BLE调试工具LightBlueiOS简单易用的蓝牙探索工具Wireshark桌面抓包分析蓝牙通信Bluetooth LoggerAndroid系统级蓝牙日志记录15.3 持续学习建议蓝牙SIG官方文档了解最新BLE规范Android和iOS的蓝牙开发文档理解平台差异Flutter插件开发掌握如何扩展原生功能蓝牙协议分析学习常见BLE设备的通信协议16. 项目实战构建健壮的BLE应用结合前面所有知识点我们来看一个完整的应用架构示例。16.1 应用架构图App Layers: - UI Layer (Flutter Widgets) - BLoC Layer (Business Logic) - Service Layer (BLE, Database) - Model Layer (Data Classes) - Utility Layer (Helpers, Tools)16.2 核心类设计class BleApp { final BleManager _bleManager; final DeviceRepository _deviceRepo; final ConnectionSupervisor _supervisor; BleApp() : _bleManager BleManager(), _deviceRepo DeviceRepository(), _supervisor ConnectionSupervisor(); Futurevoid initialize() async { await _bleManager.initialize(); _supervisor.start(); } Futurevoid connectToSavedDevices() async { final devices await _deviceRepo.getSavedDevices(); for (final device in devices) { _bleManager.connect(device.id); } } } class ConnectionSupervisor { final _interval Duration(minutes: 5); Timer? _timer; void start() { _timer Timer.periodic(_interval, (_) { _checkConnections(); }); } Futurevoid _checkConnections() async { // 实现连接状态检查逻辑 } }16.3 完整工作流程初始化阶段检查权限初始化BLE管理器加载已保存设备连接阶段扫描设备建立连接发现服务通信阶段订阅通知发送命令处理响应

更多文章