我需要每10分钟计划一次任务。
由于在Lollipop和更高版本中,setRepeating()
不精确,因此我使用setExact()
,并且(在触发警报时)我在10分钟内设置了新的确切警报。
private void setAlarm(long triggerTime, PendingIntent pendingIntent) {
int ALARM_TYPE = AlarmManager.ELAPSED_REALTIME_WAKEUP;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
alarmManager.setExact(ALARM_TYPE, triggerTime, pendingIntent);
} else {
alarmManager.set(ALARM_TYPE, triggerTime, pendingIntent);
}
}
triggerTime
是计算得出的SystemClock.elapsedRealtime() + 600_000;
警报响起时,首先我要计划一个新警报,然后再执行我的任务。
setAlarm();
mySheduledTask;
我的 list 中确实有
WAKE_LOCK
权限。当我在Android 4上进行测试时,它可以完美运行(偏差可能是12-15 毫秒)。
但是当我在小米Redmi Note 3 Pro(5.1.1)上运行应用程序时-偏差可能高达 15秒!
例如,我在日志文件中看到:第一次运行是在1467119934477(RTC时间),第二次是1467120541683。区别是 607_206 毫秒,而不是 600_000 ,这是按计划的!
我想念什么? 有什么方法可以模拟系统警报的行为(这是可以描述我的策略的最接近的用例)?
PS。 我将IntentService用于
PendingIntent = PendingIntent.getService(context, 0, myIntent, 0);
最佳答案
操作系统会根据您指定的时间来选择警报的工作方式。因此,当手机进入“半 sleep ”模式时,无需在您希望的时候使用该资源。基本上,它将等待操作系统为其打开的“窗口”,然后只有您要运行的警报才会运行,这就是您遇到时间间隔的原因。
这是在Marshmallow OS上引入的,并将在Nougat OS上继续使用,作为Google努力改善设备电池电量的一部分。
事情在这里,您有2个选择:
JobScheduler
,这是更推荐的选择,它将节省您的电池电量)。 setExactAndAllowWhileIdle
可能会导致电池问题(请谨慎使用,否则警报过多会对电池造成不良影响)。该方法不再重复,因此您必须声明下一个要在未完成的Intent打开的服务上运行的作业。
如果选择选项2,则从这里开始:
AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
int ALARM_TYPE = AlarmManager.RTC_WAKEUP;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
am.setExactAndAllowWhileIdle(ALARM_TYPE, calendar.getTimeInMillis(), pendingIntent);
else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)
am.setExact(ALARM_TYPE, calendar.getTimeInMillis(), pendingIntent);
else
am.set(ALARM_TYPE, calendar.getTimeInMillis(), pendingIntent);