Android随笔-WorkManager 与 AlarmManager

Android WorkManager 与 AlarmManager 详解

一、WorkManager

是什么

WorkManager 是 Android Jetpack 组件,用于调度可延迟、可保证执行 的后台任务。它是 Google 推荐的后台任务首选方案

核心特性

特性 说明
保证执行 即使 App 被杀死、设备重启,任务依然会被执行(需满足约束条件)
自动选择 API 内部根据系统版本自动选择 JobScheduler(API 23+)、AlarmManager + BroadcastReceiver(API 14-22)或 Firebase JobDispatcher
约束条件 可设置网络状态、电量、存储空间等条件
链式任务 支持任务依赖(A 完成后执行 B)
观察状态 通过 LiveData/Flow 观察任务执行状态

适用场景

  • 同步数据到服务器(非即时)
  • 上传日志
  • 定期清理缓存
  • 图片压缩/处理

代码示例

kotlin 复制代码
// 定义 Worker
class UploadWorker(
    context: Context,
    params: WorkerParameters
) : CoroutineWorker(context, params) {

    override suspend fun doWork(): Result {
        // 执行后台任务
        val success = uploadData()
        return if (success) Result.success() else Result.retry()
    }
}

// 调度任务
val constraints = Constraints.Builder()
    .setRequiredNetworkType(NetworkType.CONNECTED)  // 需要网络
    .setRequiresBatteryNotLow(true)                 // 电量充足
    .build()

val uploadWork = OneTimeWorkRequestBuilder<UploadWorker>()
    .setConstraints(constraints)
    .setInitialDelay(10, TimeUnit.MINUTES)  // 延迟10分钟
    .addTag("upload")
    .build()

WorkManager.getInstance(context).enqueue(uploadWork)

// 观察状态
WorkManager.getInstance(context)
    .getWorkInfoByIdLiveData(uploadWork.id)
    .observe(lifecycleOwner) { workInfo ->
        if (workInfo?.state == WorkInfo.State.SUCCEEDED) {
            // 任务成功
        }
    }

周期性任务

kotlin 复制代码
val periodicWork = PeriodicWorkRequestBuilder<SyncWorker>(
    15, TimeUnit.MINUTES  // 最小间隔15分钟(系统限制)
).build()
WorkManager.getInstance(context).enqueueUniquePeriodicWork(
    "sync",
    ExistingPeriodicWorkPolicy.KEEP,
    periodicWork
)

二、AlarmManager

是什么

AlarmManager 是 Android 系统级服务,用于在精确时间点触发事件。它基于系统闹钟机制,即使设备休眠也能唤醒。

核心特性

特性 说明
精确触发 可精确到毫秒级触发(API 19 前),API 19+ 默认批量处理以省电
唤醒设备 可设置唤醒类型,在设备休眠时也能触发
系统级服务 直接对接 Linux 闹钟机制,独立于 App 生命周期
不保证执行 App 被强制停止后,闹钟会被清除(除非设置允许重启)

适用场景

  • 闹钟应用(必须在 8:00 响铃)
  • 定时提醒(日程、吃药)
  • 需要在精确时间执行的操作
  • 与 UI 强相关的定时任务

代码示例

kotlin 复制代码
val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager

val intent = Intent(context, AlarmReceiver::class.java)
val pendingIntent = PendingIntent.getBroadcast(
    context, 0, intent, 
    PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
)

// 精确闹钟(API 23+ 需要 SCHEDULE_EXACT_ALARM 权限)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
    alarmManager.setExactAndAllowWhileIdle(
        AlarmManager.RTC_WAKEUP,  // 使用 RTC,休眠时唤醒
        System.currentTimeMillis() + 60000,  // 1分钟后触发
        pendingIntent
    )
}

// 重复闹钟(不精确,系统会批量优化)
alarmManager.setInexactRepeating(
    AlarmManager.RTC_WAKEUP,
    System.currentTimeMillis(),
    AlarmManager.INTERVAL_HOUR,  // 每小时
    pendingIntent
)

接收器

kotlin 复制代码
class AlarmReceiver : BroadcastReceiver() {
    override fun onReceive(context: Context, intent: Intent) {
        // 闹钟触发,这里执行操作
        // 注意:onReceive 在主线程,耗时操作需启动 Service 或 WorkManager
    }
}

三、核心对比

维度 WorkManager AlarmManager
精确性 不保证精确时间(系统会批量优化) 可精确到毫秒(需权限)
保活能力 (App 被杀、重启后仍能执行) (App 被强制停止后闹钟清除)
唤醒设备 不会唤醒休眠设备(省电) 可配置唤醒休眠设备
约束条件 丰富(网络、电量、存储等)
任务链 支持复杂依赖链 不支持
观察状态 支持 LiveData/Flow 观察 不支持
系统限制 最小间隔 15 分钟 API 19+ 默认批量处理
推荐使用 后台数据同步、延迟任务 闹钟、精确提醒

四、底层原理简述

WorkManager

复制代码
App 进程 → WorkManager → 持久化到 Room 数据库 → 
系统 JobScheduler / AlarmManager + BroadcastReceiver → 
满足约束条件后 → 启动进程执行 Worker

关键点:任务信息持久化到 SQLite,即使进程被杀,系统服务仍能调度。

AlarmManager

复制代码
App → AlarmManagerService → 写入 Linux RTC 设备 → 
定时到达 → 内核唤醒系统 → 发送广播 → Receiver.onReceive()

关键点:直接对接 Linux 实时时钟,独立于 App 生命周期。


五、如何选择

复制代码
需要精确时间触发(闹钟、提醒)?  →  AlarmManager + 前台服务
需要保证执行但时间可灵活?        →  WorkManager
需要周期性后台同步?              →  WorkManager 周期性任务
需要在精确时间做后台数据处理?      →  AlarmManager 触发 → WorkManager 执行

最佳实践:AlarmManager 负责"准时叫醒",WorkManager 负责"可靠执行"。两者可以配合使用。


六、Android 12+ 的新限制

版本 限制
API 31+ SCHEDULE_EXACT_ALARM 变为特殊权限,用户需在设置中手动授予
API 33+ 引入 USE_EXACT_ALARM 权限(仅系统应用、闹钟应用可用)
Doze 模式 普通 AlarmManager 在 Doze 下被延迟,需使用 setAndAllowWhileIdle

这些限制进一步强化了 Google 的意图:精确闹钟只给真正需要它的应用(如闹钟),普通后台任务请用 WorkManager。

相关推荐
雨白2 小时前
嵌套 ScrollView 滑动冲突实战:实现内部优先滚动
android
阿pin2 小时前
Android随笔-IntentService详解(了解)
android·intentservice
海天鹰2 小时前
content://com.android.externalstorage.documents/document/primary%3A
android
帅帅的记忆4 小时前
uniapp项目调用原生android studio的sdk文件(即aar文件)
android·uni-app·android studio
用户69371750013844 小时前
Kimi K3 综合能力处于全球第一梯队
android·前端·后端
阿pin4 小时前
Android随笔-BroadcastReceiver
android·broadcast
pengyu5 小时前
【Kotlin 协程修仙录 · 金丹境 · 后阶】 | 异常防火墙:supervisorScope 与异常隔离的终极奥义
android·kotlin
cheng2191016 小时前
Cocos Creator打包安卓并支持 Android 16KB 页面大小
android
夏沫琅琊7 小时前
Jetpack Compose + 原生 PDF API 从零搭一个 Android 工具应用 (一)
android·pdf·kotlin