AlarmManager设置间隔时间不准确

Android倒计时可以使用CountDownTimer;定时任务可以使用Timer+TimerTask、或Handler 、或AlarmManager。考虑到用handler 和Thread的或者是Timer 的话,当时屏幕熄灭或者锁屏的情况下可能会出现问题。所以最后的选择方案是AlarmManager(闹钟服务)。

那么问题来了~~~~

Android 4.4开始

为了节能省电(减少系统唤醒和电池使用)。使用AlarmManager.set()和AlarmManager.setRepeating()已经不保证精确性(是不是很蒙圈,不精确还怎么玩?),不过Google不会有这么乌龙的设计!其实Google还提供两个精确的AlarmManager方法setWindow()和setExact(),看来问题是解决了。
为什么不精确呢,看一下setRepeating的源码:



调用内部的一个private的方法setImpl(),具体控是否精确是靠windowMillis这个参数


AlarmManager设置间隔时间不准确_第1张图片

可以看出windowMillis的值是legacyExactLength()得返回值:mAlwaysExact。这个变量控制着该方法的返回值,如果是小于API19的版本会使用 WINDOW_EXACT参数,这个参数是0(意思就是区间设置为0,那么就会按照triggerAtMillis这个时间准时触发,也就是精准触发)另一个参数WINDOW_HEURISTIC的值是-1,这个值具体的用法就要看AlarmManagerService具体的实现了,反正只要知道这个值是不精准就可以。而setExact()这个值为WINDOW_EXACT,setWindow()的话这个值你可以自己传所以19以后他们是精准的.

但是~~~~

在Android 6.0之后

要保持Alarm在手机处于所谓Doze模式时仍然能够被即时响应,则需要使用AlarmManager新提供的两个方法setAndAllowWhileIdle()或者setExactAndAllowWhileIdle()。
所以最后要想精确,代码成这样了:


前方高能,请注意:

闹钟类型

这个闹钟类型就是前面setxxx()方法第一个参数int type.
AlarmManager.ELAPSED_REALTIME:使用相对时间,可以通过SystemClock.elapsedRealtime() 获取(从开机到现在的毫秒数,包括手机的睡眠时间),设备休眠时并不会唤醒设备。
AlarmManager.ELAPSED_REALTIME_WAKEUP:与ELAPSED_REALTIME基本功能一样,只是会在设备休眠时唤醒设备。
AlarmManager.RTC:使用绝对时间,可以通过 System.currentTimeMillis()获取,设备休眠时并不会唤醒设备。
AlarmManager.RTC_WAKEUP: 与RTC基本功能一样,只是会在设备休眠时唤醒设备。
特别关注triggerAtMillis参数,System.currentTimeMillis() 和SystemClock.elapsedRealtime()的区别。

AlarmManager设置间隔时间不准确_第2张图片

注意闹钟类型和triggerAtMillis参数的对应
System.currentTimeMillis()获取的是系统时间,是距离1970年1月1日开始计算的一个值;android.os.SystemClock.elapsedRealtime()获取从设备boot后经历的时间值,包括休眠的时间。(源代码也知道)
更新:小米手机遇到坑,低于5秒,间隔成5秒,高于5秒正常(调查中~~)。

你可能感兴趣的:(AlarmManager设置间隔时间不准确)