Flutter后台服务在Android 8及以下设备无法正常运行的解决方案咨询
Android 8及以下设备后台服务异常修复方案
针对你的Flutter后台服务在Android 8及以下设备出现通知消失、定位停止的问题,结合Android版本的后台限制差异,给出以下具体修复措施:
一、强制将服务立即设为前台服务
Android 8以下系统对后台服务的管控更严格,不能等待外部事件触发前台服务切换,必须在服务启动时直接将其设为前台状态,否则系统会快速回收后台服务。
修改代码中服务初始化部分:
if (service is AndroidServiceInstance) { // 启动时直接设为前台服务,不要等待外部事件 await service.setAsForegroundService(); // 保留原有切换逻辑(如果需要) service.on('setAsForeground').listen((event) { service.setAsForegroundService(); }); service.on('setAsBackground').listen((event) { service.setAsBackgroundService(); }); }
二、适配Android 8以下的通知优先级
Android 8以下没有通知渠道概念,需要通过priority参数提升通知优先级,确保系统不会自动移除通知:
修改AndroidNotificationDetails配置:
AndroidNotificationDetails( notificationChannelId, 'MY FOREGROUND SERVICE', icon: 'ic_bg_service_small', ongoing: true, // Android 8以下设置高优先级 priority: Priority.high, importance: Importance.high, )
三、添加CPU唤醒锁(WakeLock)防止系统休眠
Android 8以下设备在锁屏或后台时,CPU可能进入休眠状态,导致定位服务停止。使用WakeLock保持CPU唤醒:
- 引入
wakelock依赖(pubspec.yaml):
dependencies: wakelock: ^0.6.2
- 在服务启动时初始化并激活WakeLock:
import 'package:wakelock/wakelock.dart'; @pragma('vm:entry-point') Future<void> onStart(ServiceInstance service) async { // ... 原有初始化代码 ... // 激活WakeLock,保持CPU唤醒 Wakelock.enable(); // 服务停止时关闭WakeLock service.on('stopService').listen((event) { Wakelock.disable(); service.stopSelf(); }); // ... 原有定位监听代码 ... }
四、AndroidManifest.xml额外配置
确保服务声明中添加以下属性,提升服务优先级:
<service android:name="your_service_name" android:foregroundServiceType="location" android:stopWithTask="false" android:persistent="true"> </service>
android:stopWithTask="false":应用被移除最近任务列表时,服务不停止android:persistent="true":标记服务为持久化,系统会尽量保留(仅适用于必要场景)
五、定位权限补充检查
确保已在AndroidManifest中申请后台定位权限(Android 8以下不需要单独的后台权限,但需要基础定位权限):
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" /> <!-- 兼容Android 10+ -->
修改后的完整代码示例
@pragma('vm:entry-point') Future<void> onStart(ServiceInstance service) async { DartPluginRegistrant.ensureInitialized(); final DatabaseService databaseService = DatabaseService(); final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin(); // 初始化WakeLock await Wakelock.enable(); if (service is AndroidServiceInstance) { // 立即设为前台服务 await service.setAsForegroundService(); service.on('setAsForeground').listen((event) { service.setAsForegroundService(); }); service.on('setAsBackground').listen((event) { service.setAsBackgroundService(); }); } service.on('stopService').listen((event) { Wakelock.disable(); service.stopSelf(); }); final stream = Geolocator.getPositionStream( locationSettings: const LocationSettings( accuracy: LocationAccuracy.high, distanceFilter: 0, timeLimit: Duration(seconds: 10) ), ).listen((position) async { if (kDebugMode) { print('Position : $position'); } await flutterLocalNotificationsPlugin.show( notificationId, 'COOL SERVICE', '${position.latitude}, ${position.longitude} ${DateTime.now()}', NotificationDetails( android: AndroidNotificationDetails( notificationChannelId, 'MY FOREGROUND SERVICE', icon: 'ic_bg_service_small', ongoing: true, priority: Priority.high, importance: Importance.high, ), ), ); var now = DateTime.now(); var formatter = DateFormat('yyyy-MM-dd HH:mm:ss'); var route = MapRoute(createdAt: formatter.format(now), latitude: position.latitude, longitude: position.longitude); try { await databaseService.insertBreed(route); } catch (e) { if (kDebugMode) { print(e); } } }); }
内容的提问来源于stack exchange,提问作者Sumit yadu
相关产品推荐
相关产品推荐

