Android 14下Flutter应用重启时前台服务启动超时崩溃求助
解决方案:Android14 前台服务启动超时崩溃问题
核心问题分析
错误Context.startForegroundService() did not then call Service.startForeground()在Android14中触发,本质是前台服务启动后未在10秒内调用startForeground()绑定通知,或是通知渠道配置不符合Android14新要求。结合你使用的flutter_background_service和flutter_blue_plus,大概率是服务重启时通知初始化滞后,或是Android14的前台服务权限、启动时序未处理到位。
具体修复步骤
1. 强制前置前台通知绑定
修改flutter_background_service的服务初始化逻辑,必须在服务启动的第一时间完成前台通知绑定,不能延迟到蓝牙扫描逻辑之后:
Future<void> initializeService() async { final service = FlutterBackgroundService(); await service.configure( androidConfiguration: AndroidConfiguration( onStart: onStart, autoStart: true, isForegroundMode: true, notificationChannelId: "beacon_scan_channel", initialNotificationTitle: "Beacon扫描服务", initialNotificationContent: "正在后台扫描Beacon", foregroundServiceNotificationId: 100, ), iosConfiguration: IosConfiguration( autoStart: true, onForeground: onStart, onBackground: onIosBackground, ), ); } void onStart(ServiceInstance service) async { // Android14要求:先绑定前台通知,再执行其他业务逻辑 if (Platform.isAndroid) { service.setForegroundNotificationInfo( title: "Beacon扫描服务", content: "正在后台扫描Beacon", ); service.startForeground(100); // 这行必须放在所有业务逻辑之前 } // 后续再初始化蓝牙扫描 FlutterBluePlus flutterBlue = FlutterBluePlus.instance; // ... 你的蓝牙扫描逻辑代码 }
2. 适配Android14通知渠道要求
Android14规定前台服务的通知渠道必须为IMPORTANCE_LOW或更高级别,需提前创建符合要求的渠道:
import 'package:flutter_local_notifications/flutter_local_notifications.dart'; Future<void> createNotificationChannel() async { final FlutterLocalNotificationsPlugin notificationsPlugin = FlutterLocalNotificationsPlugin(); const AndroidNotificationChannel channel = AndroidNotificationChannel( 'beacon_scan_channel', // 与后台服务配置的channelId完全一致 'Beacon扫描服务', description: '后台Beacon扫描的前台通知渠道', importance: Importance.low, playSound: false, ); await notificationsPlugin .resolvePlatformSpecificImplementation<AndroidFlutterLocalNotificationsPlugin>() ?.createNotificationChannel(channel); }
在main()函数中,先调用createNotificationChannel(),再初始化后台服务。
3. 补全Android14权限配置
在AndroidManifest.xml中添加Android14新增的前台服务权限:
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" /> <uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> <uses-permission android:name="android.permission.FOREGROUND_SERVICE_CONNECTED_DEVICE" />
同时在Flutter中动态申请必要权限:
import 'package:permission_handler/permission_handler.dart'; Future<void> requestRequiredPermissions() async { await Permission.notification.request(); await Permission.bluetoothScan.request(); await Permission.bluetoothConnect.request(); await Permission.locationWhenInUse.request(); // Android12+蓝牙扫描需位置权限 }
确保在启动后台服务前完成所有权限申请。
4. 避免服务重复启动冲突
关闭应用后重启,旧服务可能未完全销毁,导致新服务启动冲突。在AndroidManifest.xml中给后台服务添加单例配置:
<service android:name="id.flutter.flutter_background_service.BackgroundService" android:permission="android.permission.BIND_JOB_SERVICE" android:stopWithTask="false" android:singleInstance="true" />
同时在Flutter启动服务前检查运行状态:
final service = FlutterBackgroundService(); bool isServiceRunning = await service.isRunning(); if (!isServiceRunning) { await service.startService(); }
5. 延迟蓝牙扫描启动(可选)
如果上述步骤仍无效,可给蓝牙扫描逻辑加短暂延迟,确保前台通知绑定完成:
void onStart(ServiceInstance service) async { if (Platform.isAndroid) { service.setForegroundNotificationInfo( title: "Beacon扫描服务", content: "正在后台扫描Beacon", ); service.startForeground(100); } // 延迟100ms启动扫描,给前台通知绑定留足时间 await Future.delayed(const Duration(milliseconds: 100)); FlutterBluePlus flutterBlue = FlutterBluePlus.instance; // ... 你的蓝牙扫描逻辑 }
内容的提问来源于stack exchange,提问作者Dries Vandenbussche
相关产品推荐
相关产品推荐

