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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 13:13:17