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。