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,提问作者عثمان غني
相关产品推荐
相关产品推荐

