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

Flutter flutter_background_service在应用被杀状态下无法稳定启动问题

Flutter Background Service 在应用被杀状态下间歇性失败(Flutter engine disconnected错误)

问题描述

应用处于被杀状态时,flutter_background_service组件有时能正常启动后台服务,有时会因Flutter engine disconnected. Connected engine count 0错误停止,服务稳定性无法保障。

相关代码实现

主函数

void main() async {
 WidgetsFlutterBinding.ensureInitialized();
 await initializeService();
}

应用生命周期监听代码

@override
void didChangeAppLifecycleState(AppLifecycleState state) {
  super.didChangeAppLifecycleState(state);
  if (state == AppLifecycleState.resumed) {
    print('_isInForeground');
  } else if (state == AppLifecycleState.paused) {
    print('_isInBackground');
  } else if (state == AppLifecycleState.detached) {
    print('_isInKilled');
    serviceBackground.startService();
  }
}

后台服务配置代码

Future<void> initializeService() async {
  final serviceBackground = FlutterBackgroundService();
  AndroidNotificationChannel channel = const AndroidNotificationChannel(
    "App",
    "foreground service",
    importance: Importance.high,
  );
  final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
      FlutterLocalNotificationsPlugin();

  await flutterLocalNotificationsPlugin
      .resolvePlatformSpecificImplementation<
          AndroidFlutterLocalNotificationsPlugin>()
      ?.createNotificationChannel(channel);

  await serviceBackground.configure(
      iosConfiguration: IosConfiguration(),
      androidConfiguration: AndroidConfiguration(
        onStart: onStart,
        isForegroundMode: true,
        autoStart: true,
        notificationChannelId: "App",
        initialNotificationTitle: "foreground service",
        initialNotificationContent: "initializing",
        foregroundServiceNotificationId: 888,
      ));
  serviceBackground.startService();
}

@pragma('vm-entry-point')
Future<void> onStart(ServiceInstance serviceBackground) async {
  WidgetsFlutterBinding.ensureInitialized();
  DartPluginRegistrant.ensureInitialized();
  final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
      FlutterLocalNotificationsPlugin();
  serviceBackground.on('stopService').listen((event) {
    print("stopService : $event");
    serviceBackground.stopSelf();
  });

  if (serviceBackground is AndroidServiceInstance) {
    if (await serviceBackground.isForegroundService()) {
      Geolocator.getPositionStream(
          locationSettings: const LocationSettings(
        accuracy: LocationAccuracy.high,
        distanceFilter: 20,
      )).listen((Position? position) {
        addItem(position?.latitude, position?.longitude);
      });

      flutterLocalNotificationsPlugin.show(
        888,
        "Background ON",
        "Location Tracked",
        const NotificationDetails(
            android: AndroidNotificationDetails(
          "App",
          "foreground service",
          ongoing: true,
        )),
      );
    }
  }
}

问题定位与修复方案

1. 移除detached状态下的服务启动逻辑

AppLifecycleState.detached表示Flutter引擎已与宿主分离,此时启动服务无法保证Flutter环境正常初始化。改为在paused状态就确保服务运行:

@override
void didChangeAppLifecycleState(AppLifecycleState state) {
  super.didChangeAppLifecycleState(state);
  if (state == AppLifecycleState.resumed) {
    print('_isInForeground');
  } else if (state == AppLifecycleState.paused) {
    print('_isInBackground');
    // 进入后台立即启动/维持服务,避免等到引擎分离
    serviceBackground.startService();
  }
}

2. 全局维护服务实例

原代码中initializeService内的serviceBackground是局部变量,导致生命周期监听中的实例可能未正确初始化。改为全局声明:

// 全局服务实例,确保全应用内引用一致
final FlutterBackgroundService serviceBackground = FlutterBackgroundService();

Future<void> initializeService() async {
  // 移除局部变量声明,使用全局实例
  AndroidNotificationChannel channel = const AndroidNotificationChannel(
    "App",
    "foreground service",
    importance: Importance.high,
  );
  final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
      FlutterLocalNotificationsPlugin();

  await flutterLocalNotificationsPlugin
      .resolvePlatformSpecificImplementation<
          AndroidFlutterLocalNotificationsPlugin>()
      ?.createNotificationChannel(channel);

  await serviceBackground.configure(
      iosConfiguration: IosConfiguration(),
      androidConfiguration: AndroidConfiguration(
        onStart: onStart,
        isForegroundMode: true,
        autoStart: true,
        notificationChannelId: "App",
        initialNotificationTitle: "foreground service",
        initialNotificationContent: "initializing",
        foregroundServiceNotificationId: 888,
      ));
  serviceBackground.startService();
}

3. 强制设置前台服务优先级

onStart中依赖isForegroundService判断会导致服务启动后未立即进入前台模式,被系统低优先级回收。主动设置前台服务:

@pragma('vm-entry-point')
Future<void> onStart(ServiceInstance serviceBackground) async {
  WidgetsFlutterBinding.ensureInitialized();
  DartPluginRegistrant.ensureInitialized();
  final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
      FlutterLocalNotificationsPlugin();

  if (serviceBackground is AndroidServiceInstance) {
    // 主动设置为前台服务,提升系统优先级
    await serviceBackground.setAsForegroundService();
    
    // 直接执行位置监听逻辑,无需等待状态判断
    Geolocator.getPositionStream(
        locationSettings: const LocationSettings(
      accuracy: LocationAccuracy.high,
      distanceFilter: 20,
    )).listen((Position? position) {
      addItem(position?.latitude, position?.longitude);
    });

    flutterLocalNotificationsPlugin.show(
      888,
      "Background ON",
      "Location Tracked",
      const NotificationDetails(
          android: AndroidNotificationDetails(
        "App",
        "foreground service",
        ongoing: true,
      )),
    );
  }

  serviceBackground.on('stopService').listen((event) {
    print("stopService : $event");
    serviceBackground.stopSelf();
  });
}

4. 处理Android系统后台限制

  • 电池优化白名单:使用permission_handler插件请求忽略电池优化权限,避免系统后台杀进程:
    await Permission.ignoreBatteryOptimizations.request();
    
  • 厂商特殊权限:引导用户手动开启国产厂商(小米、华为、OPPO等)的「自启动」「后台运行权限」,这类厂商有独立的后台管控机制。
  • 补充WorkManager:结合workmanager插件实现周期性位置上报,作为服务被杀死后的兜底方案。

5. 引擎断开自动重启

在onStart中监听引擎断开事件,自动重启服务:

@pragma('vm-entry-point')
Future<void> onStart(ServiceInstance serviceBackground) async {
  // ... 现有代码 ...

  if (serviceBackground is AndroidServiceInstance) {
    // 监听引擎断开,尝试重启服务
    serviceBackground.on('engineDisconnected').listen((_) {
      serviceBackground.startService();
    });
  }
}

内容的提问来源于stack exchange,提问作者عثمان غني

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 04:57:29