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

Flutter Android端前台服务终止导致BLE连接断开问题求助

Android端Flutter BLE后台恢复自动断开问题解决方案

问题概述

用flutter_reactive_ble连接BLE设备时,Android端在后台恢复(锁屏后切回、切换应用返回)时会自动断开连接,iOS端无此异常。排查发现应用后台恢复时后台服务会触发service.stopSelf(),进而触发BLE连接断开逻辑,用flutter_background_service后问题依旧。

环境信息

System: Android
Flutter Version: 3.16.7
Package Versions:
flutter_reactive_ble: v5.3.1
flutter_background_service : v5.0.5

解决方案

1. 防止后台服务被误停止

检查应用生命周期相关代码,确认是否在后台恢复时错误发送了stopService事件给后台服务。修改后台服务逻辑,增加防护判断:

@pragma('vm:entry-point')
void onStart(ServiceInstance service) async {
  DartPluginRegistrant.ensureInitialized();

  if (service is AndroidServiceInstance) {
    service.on('setAsForeground').listen((event) {
      service.setAsForegroundService();
    });
    service.on('setAsBackground').listen((event) {
      service.setAsBackgroundService();
    });
  }
  
  // 增加验证逻辑,避免误触发停止
  service.on('stopService').listen((event) {
    // 可根据实际需求添加判断条件,比如仅在指定场景下停止服务
    // 示例:if (event['forceStop'] == true)
    service.stopSelf();
  });
}

2. 配置前台服务权限与运行模式

Android对后台进程限制严格,BLE长连接必须依赖前台服务才能稳定运行:

  • 在AndroidManifest.xml中添加必要权限:
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_CONNECTED_DEVICE" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
  • 启动后台服务后直接设置为前台模式,避免被系统回收:
// 启动服务后立即调用
await FlutterBackgroundService().invoke("setAsForeground");

3. 优化BLE连接,添加自动重连

修改flutter_reactive_ble连接代码,开启自动重连并增加异常重连逻辑:

StreamSubscription<ConnectionStateUpdate>? deviceStream;

// 封装连接方法,方便重复调用
void connectToBleDevice(Device device, int index) {
  deviceStream = flutterReactiveBle
      .connectToDevice(
          id: device.id,
          connectionTimeout: const Duration(seconds: 5),
          // 启用系统自动重连
          autoConnect: true)
      .listen(
    (connectionState) {
      if (connectionState.connectionState == DeviceConnectionState.connected) {
        // 连接成功后的业务处理
      } else if (connectionState.connectionState == DeviceConnectionState.disconnected) {
        print("BLE Disconnect is disconnected");
        // 延迟2秒后尝试重连,可根据需求调整时长或增加重连次数限制
        Future.delayed(const Duration(seconds: 2), () {
          connectToBleDevice(device, index);
        });
        onDisconnect(index, true);
      }
    },
    onError: (error) {
      print("BLE Disconnect connection error = $error");
      // 连接出错时同样触发重连
      Future.delayed(const Duration(seconds: 2), () {
        connectToBleDevice(device, index);
      });
    },
  );
}

提示:autoConnect: true会让系统在设备可连接时自动尝试重连,但要确保设备处于可被扫描到的状态。

4. 监听应用生命周期,主动恢复连接

在应用从后台切回前台时,检查BLE连接状态,若已断开则主动重建:

// 在StatefulWidget的生命周期方法中监听
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
  super.didChangeAppLifecycleState(state);
  if (state == AppLifecycleState.resumed) {
    // 检查当前设备连接状态,若未连接则触发重连
    if (currentConnectionState != DeviceConnectionState.connected) {
      connectToBleDevice(currentDevice, currentIndex);
    }
  }
}

5. 后台服务持有BLE连接实例

把BLE连接实例放在后台服务中初始化和管理,避免因UI层生命周期销毁导致连接断开:

@pragma('vm:entry-point')
void onStart(ServiceInstance service) async {
  DartPluginRegistrant.ensureInitialized();
  FlutterReactiveBle flutterReactiveBle = FlutterReactiveBle();
  StreamSubscription<ConnectionStateUpdate>? deviceStream;

  // 监听UI层发送的连接指令
  service.on('connectDevice').listen((event) {
    String deviceId = event['deviceId'];
    deviceStream = flutterReactiveBle.connectToDevice(
      id: deviceId,
      connectionTimeout: const Duration(seconds: 5),
      autoConnect: true,
    ).listen((state) {
      // 把连接状态同步给UI层
      service.sendEvent(event: {
        'connectionState': state.connectionState.name,
        'deviceId': deviceId,
      });
    });
  });

  // 监听UI层发送的断开指令
  service.on('disconnectDevice').listen((event) {
    deviceStream?.cancel();
  });

  if (service is AndroidServiceInstance) {
    service.on('setAsForeground').listen((event) {
      service.setAsForegroundService();
    });
    service.on('setAsBackground').listen((event) {
      service.setAsBackgroundService();
    });
  }
  
  service.on('stopService').listen((event) {
    deviceStream?.cancel();
    service.stopSelf();
  });
}

这样BLE连接由后台服务持有,不受UI页面销毁或后台切换的影响。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 06:25:05