Flutter使用flutter_blue包连接蓝牙设备出现间歇性失败问题
解决flutter_blue 0.6.3+1连接蓝牙设备时的不稳定问题
看起来你遇到的是典型的扫描-连接时序冲突问题,结合你的错误信息和代码,我来拆解下问题根源和修复方案:
问题分析
你的代码里存在几个关键问题导致连接不稳定:
- 扫描未及时停止:找到目标设备后没有立即调用
stopScanning(),导致scanResults流会持续发射新的扫描结果,可能多次触发连接逻辑,造成连接请求冲突 - 冗余的StreamController:直接监听
FlutterBlue.instance.scanResults就足够了,额外包一层StreamController反而可能导致流处理延迟或重复 - 未检查设备状态:第一次连接成功后,设备处于已连接状态,第二次扫描到设备时直接调用
connect()会因为设备状态异常失败;而第三次可能设备刚好完成断开,所以又能成功,形成循环
修复方案
下面是调整后的代码,我会标注关键改动:
void scanForDevices() async { // 先取消之前的扫描订阅(避免重复扫描) if (scanSubscription != null) { await scanSubscription.cancel(); scanSubscription = null; } // 直接监听FlutterBlue的scanResults流,无需额外StreamController scanSubscription = FlutterBlue.instance.scanResults.listen((devices) async { final result = devices.where((currentDev) => currentDev.advertisementData.localName.contains((_dev as BaseDevice).psn) ).toList(); if (deviceToConnect == null && result.isNotEmpty) { final targetScanResult = result.first; deviceToConnect = targetScanResult.device; print("找到目标设备:${targetScanResult.advertisementData.localName}"); // 找到设备后立即停止扫描,避免重复触发 await stopScanning(); // 连接前检查设备当前状态,确保处于断开状态 if (targetScanResult.device.state != BluetoothDeviceState.disconnected) { // 如果设备未断开,先尝试断开 await targetScanResult.device.disconnect(); // 给设备一点时间完成断开 await Future.delayed(Duration(milliseconds: 500)); } try { await targetScanResult.device.connect(); await checkState(); setState(() => ViewState.Idle); print("连接成功"); } catch (e) { setState(() => ViewState.Idle); print("连接失败:$e"); // 可选:添加重试逻辑,比如失败后延迟1秒重试一次 // await Future.delayed(Duration(seconds: 1)); // await targetScanResult.device.connect(); } } }); // 启动扫描,设置超时 await FlutterBlue.instance.startScan(timeout: Duration(seconds: 10)); } void stopScanning() async { print('停止扫描'); await FlutterBlue.instance.stopScan(); if (scanSubscription != null) { await scanSubscription.cancel(); scanSubscription = null; } }
关键改动说明
- 移除冗余StreamController:直接使用
FlutterBlue.instance.scanResults流,减少不必要的流处理环节 - 找到设备立即停扫:避免流持续发射结果导致多次触发连接逻辑
- 连接前检查设备状态:确保设备处于断开状态再发起连接,处理第一次连接后未完全断开的情况
- 添加断开后的延迟:给蓝牙设备足够的状态切换时间,避免状态未同步导致的连接失败
- 清理订阅:每次扫描前先取消之前的订阅,防止多个扫描流同时运行
另外,你还可以考虑:
- 在
connect()时添加autoConnect: true参数(如果你的设备支持),提升连接稳定性:await targetScanResult.device.connect(autoConnect: true); - 监听设备状态变化,确保状态稳定后再进行后续操作:
targetScanResult.device.state.listen((state) { if (state == BluetoothDeviceState.connected) { // 设备已连接,执行后续逻辑 } });
内容的提问来源于stack exchange,提问作者Sami Issa
相关产品推荐
相关产品推荐

