setAlarmClock() fires too late in doze mode

巧了我就是萌 提交于 2020-04-10 18:46:53

问题


I have soooo much trouble getting my radio alarm clock working as intended and I have read a lot of threads here about that topic, but unfortunatley none did help me.

AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);        
Intent intent = new Intent(this, AlarmReceiver.class);
PendingIntent penInt = PendingIntent.getBroadcast(this, intentId, intent, 0);

This method of distinction between the API levels I found here on stackoverflow and put it inside my calcNextAlarm() function (plus some log messages for debugging) to set the alarm correctly no matter what API is being used on the device:

// problems in doze mode api 23+
if (Build.VERSION.SDK_INT >= 23) {
    if (testMode) Log.d("Ben", "setAlarmClock() - API 23+");
    am.setAlarmClock(new AlarmManager.AlarmClockInfo(alarmTimeInMillis, penInt), penInt);
}

else if (Build.VERSION.SDK_INT >= 19) {
// Wakes up the device in Idle Mode
    if (testMode) Log.d("Ben", "setExact() - API >= 19 && API < 23");
    am.setExact(AlarmManager.RTC_WAKEUP, alarmTimeInMillis, penInt);
}
// Old APIs
else {
    if (testMode) Log.d("Ben", "set() - API < 19");
    am.set(AlarmManager.RTC_WAKEUP, alarmTimeInMillis, penInt);
}

According to the Log.d messages I can see that, on my Android 7.1 Device the first method setAlarmClock() is being executed to set the alarm in the Receiver.

I am getting really desperate after 3 weeks of unsuccessful tests and coding - my alarm today got off 4 minutes too late again - this should never happen, according to the doze mode training page:

Alarms set with setAlarmClock() continue to fire normally — the system exits Doze shortly before those alarms fire.

On my 7.1 phone the alarm will even be 20 seconds to 1:40 mins late when I set the alarm to "now +5 or 6" minutes. Could anyone advise me how to really ALWAYS get the alarm off perfectly in time?


回答1:


Try using:

setExactAndAllowWhileIdle()

This will ensure that the alarm fires on time. I have tested it in my own app and it's reliable.

If you are targeting API less than 23, keep this inside an if clause which checks the current api installed in the device. Use this only above API level 23, for rest keep using setExact

All right to answer your comment:

1) i have accurately tested it in doze mode without the battery being plugged in

2) yea unfortunately there's the one alarm per 9 minutes limit for while idle type alarms. You have two alternatives here:

First use the setExactAndAllowWhileIdle to fire the first alarm.

a) For snooze, you will have to use setAlarmClock method

b) for snooze, you can have a JobScheduler job scheduled with minimum latency time set as your snooze time. This will ensure that the job gets at least scheduled at the gap of the snooze interval. But just this will cause the job to get randomly scheduled after the interval so you'll also need to have an override deadline set to 0 so that the job gets scheduled immediately after the minimum latency. Also keep network requirements as none and idle mode needed as default or false. This is also as reliable as the alarm exact methods as per my experience and i personally use this approach.




回答2:


The documentation states that:

  • If you need to set alarms that fire while in Doze, use setAndAllowWhileIdle() or setExactAndAllowWhileIdle().

  • Alarms set with setAlarmClock() continue to fire normally — the system exits Doze shortly before those alarms fire.

In "Adapt your app to Doze" section it also says that:

Note: Neither setAndAllowWhileIdle() nor setExactAndAllowWhileIdle() can fire alarms more than once per 9 minutes, per app.

The documentation for setExactAndAllowWhileIdle says that:

Unlike other alarms, the system is free to reschedule this type of alarm to happen out of order with any other alarms, even those from the same app. This will clearly happen when the device is idle (since this alarm can go off while idle, when any other alarms from the app will be held until later), but may also happen even when not idle. Note that the OS will allow itself more flexibility for scheduling these alarms than regular exact alarms, since the application has opted into this behavior. When the device is idle it may take even more liberties with scheduling in order to optimize for battery life.

So setExactAndAllowWhileIdle is not guaranteeing the exact execution, and setAlarmClock is more exact (according to documentation).



来源:https://stackoverflow.com/questions/48008999/setalarmclock-fires-too-late-in-doze-mode

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!