Workmanager锁屏或休眠时无法运行的技术问题求助
Workmanager周期性任务锁屏后无法运行的解决方案
问题描述
需要每15分钟持续追踪用户位置,采用Workmanager包实现周期性任务。目前仅在手机屏幕亮起时,App处于前台、后台及终止状态下任务均可正常执行;但锁屏后,Workmanager周期性任务无法运行。
现有代码
import 'package:flutter/material.dart'; import 'package:workmanager/workmanager.dart'; var task = 'FIrstTask'; @pragma('vm:entry-point') void callbackDispatcher() { Workmanager().executeTask((taskName, inputData) { print('Hiiiiiiiiiiiiiiiii-------->>>>>>>>>>>>>$inputData["time"]'); return Future.value(true); }); } void main() async { WidgetsFlutterBinding.ensureInitialized(); await Workmanager().initialize(callbackDispatcher, isInDebugMode: true); runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return const MaterialApp( title: 'Flutter Demo', home: MyHomePage(title: 'Flutter Demo Home Page'), ); } } class MyHomePage extends StatefulWidget { const MyHomePage({super.key, required this.title}); final String title; @override State<MyHomePage> createState() => _MyHomePageState(); } class _MyHomePageState extends State<MyHomePage> { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text(widget.title), ), body: Center( child: TextButton( onPressed: () { var s = DateTime.now().millisecond; Workmanager().registerPeriodicTask(s.toString(), task, inputData: {"time": s.toString()}, frequency: const Duration(minutes: 1), initialDelay: const Duration(seconds: 10), constraints: Constraints(networkType: NetworkType.connected)); }, child: const Text('Click me')), ), ); } }
问题原因
Android系统锁屏后会进入Doze模式,该模式下系统会限制后台任务的执行频率以降低功耗,普通的Workmanager周期性任务会被延迟或暂停。此外,现有代码仅配置了网络连接约束,未针对设备休眠状态做适配。
解决方案
1. 调整任务约束,适配Doze模式
修改任务约束,放宽对设备状态的限制,允许任务在低电量、非空闲状态下运行:
Workmanager().registerPeriodicTask( s.toString(), task, inputData: {"time": s.toString()}, frequency: const Duration(minutes: 15), // 改为需求的15分钟周期 initialDelay: const Duration(seconds: 10), constraints: const Constraints( networkType: NetworkType.connected, requiresBatteryNotLow: false, // 允许低电量时执行任务 requiresDeviceIdle: false, // 不要求设备处于空闲状态 requiresCharging: false, // 不要求设备处于充电状态 ), existingWorkPolicy: ExistingWorkPolicy.replace, // 避免重复注册相同任务 );
2. 针对Android 12+使用精确周期性任务
Android 12及以上版本支持ExactPeriodicWorkRequest,可提升任务触发的精准度,但需申请对应权限:
- 在
AndroidManifest.xml中添加权限:<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" /> - 代码中动态申请权限(针对Android 12+):
import 'package:permission_handler/permission_handler.dart'; // 注册任务前调用该方法申请权限 Future<void> requestExactAlarmPermission() async { if (await Permission.scheduleExactAlarm.isDenied) { await Permission.scheduleExactAlarm.request(); } }
3. 任务执行时获取唤醒锁
在任务回调中获取临时唤醒锁,确保设备在位置追踪期间保持唤醒状态:
import 'package:flutter/services.dart'; @pragma('vm:entry-point') void callbackDispatcher() { Workmanager().executeTask((taskName, inputData) async { const MethodChannel _channel = MethodChannel('wakelock'); // 获取唤醒锁 await _channel.invokeMethod('acquire'); // 执行位置追踪逻辑 print('Hiiiiiiiiiiiiiiiii-------->>>>>>>>>>>>>${inputData?["time"]}'); // 任务完成后释放唤醒锁 await _channel.invokeMethod('release'); return Future.value(true); }); }
对应Android端需实现唤醒锁的MethodChannel:
在MainActivity.kt中添加:
private val CHANNEL = "wakelock" private lateinit var wakeLock: PowerManager.WakeLock override fun configureFlutterEngine(flutterEngine: FlutterEngine) { super.configureFlutterEngine(flutterEngine) MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler { call, result -> when (call.method) { "acquire" -> { val powerManager = getSystemService(Context.POWER_SERVICE) as PowerManager wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "LocationTracker:WakeLock") wakeLock.acquire(10*60*1000L) // 最多保持10分钟,可根据任务时长调整 result.success(null) } "release" -> { if (wakeLock.isHeld) { wakeLock.release() } result.success(null) } else -> result.notImplemented() } } }
同时在AndroidManifest.xml添加唤醒锁权限:
<uses-permission android:name="android.permission.WAKE_LOCK" />
4. 确保Workmanager版本为最新
更新pubspec.yaml中的Workmanager依赖到最新版本,以获得更好的系统适配:
dependencies: workmanager: ^0.5.1 # 替换为最新版本
内容的提问来源于stack exchange,提问作者Rajesh Byroju
相关产品推荐
相关产品推荐

