Android定时任务选AlarmManager还是WorkManager及长整型日期处理问题
问题1:定时任务选型建议
- 如果你的需求是必须精准在固定时间触发(比如每天固定整点必须弹出反馈,哪怕应用被后台杀死也要触发),优先选
AlarmManager,它是系统级的闹钟服务,触发时间精度更高,适合强时间敏感的场景。 - 如果你的需求允许一定的时间漂移(比如可以在用户设备空闲、充电的时候再执行,不需要绝对准点),优先选
WorkManager,它会自动处理设备重启、进程被杀的重试逻辑,不需要你额外兼容各种厂商的后台权限限制,开发成本更低。
针对大学课程应用的每日反馈场景,不需要毫秒级精度的话更推荐WorkManager,实际落地的兼容性坑更少。
问题2:定时触发逻辑实现方案
第一步:获取比对需要的时间戳范围
你已经将日期存为Long型时间戳,每次触发任务时先计算当日0点和前一日0点的时间戳即可完成数据统计:
// 计算当日0点的时间戳 val todayStart = LocalDate.now().atStartOfDay(ZoneId.systemDefault()).toEpochSecond() * 1000 // 计算前一日0点的时间戳 val yesterdayStart = LocalDate.now().minusDays(1).atStartOfDay(ZoneId.systemDefault()).toEpochSecond() * 1000 // 查询当日数据量 val todayCount = dao.findConsumption(todayStart, System.currentTimeMillis()).size // 查询前一日全天数据量 val yesterdayCount = dao.findConsumption(yesterdayStart, todayStart - 1).size
拿到两个统计值后就可以执行你自己的奖惩反馈逻辑。
第二步:搭配定时任务实现自动触发
若选用WorkManager(推荐):
- 首先定义继承自
Worker的任务类,在doWork()方法里执行上面的查询、比对、推送通知逻辑 - 用
PeriodicWorkRequest构建每日重复任务,指定触发时间:
// 示例设定每天22点执行任务 val triggerTime = LocalTime.of(22, 0) val duration = Duration.between(LocalTime.now(), triggerTime).let { if (it.isNegative) it.plusDays(1) else it } val dailyCheckWork = PeriodicWorkRequestBuilder<DailyCheckWorker>(1, TimeUnit.DAYS) .setInitialDelay(duration) .build() // 入队任务,设置唯一标识防止重复创建 WorkManager.getInstance(context).enqueueUniquePeriodicWork( "daily_check_work", ExistingPeriodicWorkPolicy.KEEP, dailyCheckWork )
若选用AlarmManager:
- 定义BroadcastReceiver接收闹钟触发广播,在
onReceive()里执行查询、比对、推送逻辑 - 注册闹钟,设置每天固定时间触发,注意要额外兼容设备重启后重新注册闹钟的逻辑:
val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager val intent = Intent(context, DailyCheckReceiver::class.java) val pendingIntent = PendingIntent.getBroadcast( context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE ) // 示例设置每天22点触发 val triggerTime = Calendar.getInstance().apply { set(Calendar.HOUR_OF_DAY, 22) set(Calendar.MINUTE, 0) set(Calendar.SECOND, 0) if (timeInMillis < System.currentTimeMillis()) { add(Calendar.DAY_OF_YEAR, 1) } }.timeInMillis alarmManager.setRepeating( AlarmManager.RTC_WAKEUP, triggerTime, AlarmManager.INTERVAL_DAY, pendingIntent )
内容的提问来源于stack exchange,提问作者Alexis Mortinea
相关产品推荐
相关产品推荐

