You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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;
  }
}

关键改动说明

  1. 移除冗余StreamController:直接使用FlutterBlue.instance.scanResults流,减少不必要的流处理环节
  2. 找到设备立即停扫:避免流持续发射结果导致多次触发连接逻辑
  3. 连接前检查设备状态:确保设备处于断开状态再发起连接,处理第一次连接后未完全断开的情况
  4. 添加断开后的延迟:给蓝牙设备足够的状态切换时间,避免状态未同步导致的连接失败
  5. 清理订阅:每次扫描前先取消之前的订阅,防止多个扫描流同时运行

另外,你还可以考虑:

  • 在connect()时添加autoConnect: true参数(如果你的设备支持),提升连接稳定性:
    await targetScanResult.device.connect(autoConnect: true);
    
  • 监听设备状态变化,确保状态稳定后再进行后续操作:
    targetScanResult.device.state.listen((state) {
      if (state == BluetoothDeviceState.connected) {
        // 设备已连接,执行后续逻辑
      }
    });
    

内容的提问来源于stack exchange,提问作者Sami Issa

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 17:37:47