AlarmManager set 设置定时闹钟,延时执行的问题
Posted 夏至的稻穗
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了AlarmManager set 设置定时闹钟,延时执行的问题相关的知识,希望对你有一定的参考价值。
背景:使用 AlarmManager 给系统设置定时关机,延时了1个多小时的才执行的问题
接到问题后,首先排查了代码,看到代码使用的是 android 自带的 AlarmManager 设置一个服务的 PendingIntent,当时间到了,则执行关机程序。代码如下:
/**
* 设置定时关机
* @param time 多少ms后关机
*/
fun shutDownSystem(time: Long) {
val intent = Intent(WebConfigApi.context,ShutdownService::class.java)
val pendingIntent = PendingIntent.getService(
context, 0, intent,
PendingIntent.FLAG_UPDATE_CURRENT
)
if (time <= 0) {
alarm.cancel(pendingIntent)
} else {
alarm.set(AlarmManager.RTC_WAKEUP, time, pendingIntent)
}
}
从代码逻辑看,没啥问题。
一开始怀疑是客户设置了 ntp 服务,导致系统时间延时引起,但 ntp 只是为了校准时间,问了客户时间也是正常的。
从日志看,也不是必现的,所以写了一个定时开关机的脚本去压测,每次开机后对当前时间+5分钟,做定时开关机压测,测试了两天,都能开机关机。
从这里反应,程序应该是没问题,而且出货之前也测试过这块内容。
但从客户日志来,有一个跟脚本和测试明显的不同的区分,就是客户设置定时关机的跨度比较大,且设完一段时间未使用设备。
所以找了几个盒子,进行煲机,确实复现到了
但为啥时间跨度大,未使用设备就会出现?
说明软件程序确实有问题,跟踪进去,发现 set 方法,在 API 19,使用这个方法传递的时间视为不准确,系统为了减少电池消耗,可能会把这个 set 推迟,然后批量发送;
从这里可以看到,确实是set 这个方法引起的;
所以,从源码出发,发现 setExact 这个方法,该方法指定系统在规定时间内发出,不允许系统调整交付时间。
修改后,问题解决。
思考:set 方法有问题,那可能标志位也有问题。可以发现 RTC_WAKEUP 标识使用的是 系统时间,也就是 System.currentTimeMillis(),这样设置的时间,容易被人修改;所以采用 ELAPSED_REALTIME_WAKEUP 这个标志位,它根据系统开机时间来计算,也就是 SystemClock.elapsedRealtime()。
所以,代码这里,关机的时间也需要改一下,从开机时间+设置的时间即可,如下:
/**
* 设置定时关机
* @param time 多少ms后关机
*/
fun shutDownSystem(time: Long) {
val elapsedTime = SystemClock.elapsedRealtime()
//开机时间 + 延时时间
val alarmTime = elapsedTime + time
val intent = Intent(
WebConfigApi.context,
ShutdownService::class.java
)
val pendingIntent = PendingIntent.getService(
context, 0, intent,
PendingIntent.FLAG_UPDATE_CURRENT
)
if (alarmTime <= 0) {
alarm.cancel(pendingIntent)
isDelayShutdown = false
} else {
//ELAPSED_REALTIME_WAKEUP 自开机其开始算时间,RTC_WAKEUP 则是根据系统时间有关
// alarm.setExact()
alarm.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP, alarmTime, pendingIntent)
}
}
以上是关于AlarmManager set 设置定时闹钟,延时执行的问题的主要内容,如果未能解决你的问题,请参考以下文章