How to Make Alarm Manager Work When Android 6.0 in Doze Mode

How to make Alarm Manager work when Android 6.0 in Doze mode?

Doze and App Standby definitely change the behavior in regards to alarms and wakelocks, but they're definitely not the end of the world for you!

Have you tried using the method setAlarmclock() instead of set()?
It's designed specifically for alarm clocks and may be able to cut through doze. There are a few adb commands you can use to manually put a phone into doze or app standby mode: https://developer.android.com/preview/features/power-mgmt.html

If that isn't able to wake your app up, there's the surefire method setExactAndAllowWhileIdle() is designed to wake the phone from doze no matter what. Worst case scenario, you can wake your app up with this method and use the wakeup to schedule the next alarm.

Another page worth a read is this blog post with its flowchart for background work and alarms: https://plus.google.com/+AndroidDevelopers/posts/GdNrQciPwqo

Alarm Manager issue in Android 6.0 Doze mode

The Doze mode will delay your alarm until the next maintenance window. To avoid the Doze mode to block your alarm, you can use setAndAllowWhileIdle(), setExactAndAllowWhileIdle() or setAlarmClock(). You will have about 10s to execute your code, and set your next alarm (not more than once per 15min for methods with _AndAllowWhileIdle though)

If you want to test the Doze mode, you can use ADB command:

  1. Configure a hardware device or virtual device with an Android 6.0 (API level 23) or higher system image.

  2. Connect the device to your development machine and install your app.

  3. Run your app and leave it active.
  4. Shut off the device screen. (The app remains active.)
    Force the system to cycle through Doze modes by running the following commands:

    adb shell dumpsys battery unplug

    adb shell dumpsys deviceidle step

  5. You may need to run the second command more than once. Repeat it until the device state changes to idle.

  6. Observe the behavior of your app after you reactivate the device. Make sure the app recovers gracefully when the device exits Doze.

Edit: Add setAlarmClock example

Don't forget to check the SDK level (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)

AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);
Intent intent = new Intent(this, MyAlarmReceiver.class); //or just new Intent() for implicit intent
//set action to know this come from the alarm clock
intent.setAction("from.alarm.clock");
PendingIntent pi = PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
//Alarm fire in 5s.
am.setAlarmClock(new AlarmManager.AlarmClockInfo(System.currentTimeMillis() + 5000, pi), pi);

Why is doze mode not affecting the AlarmManager setExact() function?

I FOUND THE PROBLEM:

First and foremost, Doze mode did not affect the alarmmanager setExact() function when i was testing my app in an emulator(i used genymotion in my case).

I then decided to use a physical phone i.e HTC Desire 530 but the results were still the same. This is where i got frustrated until i found out something very interesting in the HTC official documentation support page which was that:

The phone exits from Doze mode when:

You plug in the power adapter and charge the phone.

There's movement, such as when you pick up the phone.

An alarm clock goes off at your set time.

I wondered if the 3rd point could be the cause behind doze mode not effecting the alarmmanager setExact method. So i tested my app in another phone i.e OPPO A3s. This is where things ran as expected !

The setExact method did not run in doze mode while it did run when i exited the doze mode !
while setExactAndAllowWhileIdle() ran just like its written in the docs.

So i got to the conclusion that:-

  • HTC might have modified the doze mode behavior ? (since android officially
    restricts alarmmanager setExact execution in doze mode while HTC
    doesn't). The reason behind this (maybe naive) assumption is i've seen some un-standard behavior in some android phones like the alarm would go off even when the device was POWERED OFF !
  • and last but not least, never trust your emulator :p

P.S:

if you are wondering why am i so concerned with this whole thing, it's because i am working on an alarm app and i am using the alarmmanager for performing time based tasks. I would not have been able to test my app properly if this problem would have persisted (hope you get my point).

Android's background restrictions and battery optimizations have made simple things complex.

UPDATE:-

Doze mode had no effect on the alarmmanager setExact() even when i turned on the battery optimization in HTC Desire 530.

Doze Mode, Battery Optimization whitelist, AlarmManager more frequent than 9 mins

What are the regular alarms ? is setExactAndAllowWhileIdle() regular ?

No. setExactAndAllowWhileIdle() is not regular. Regular alarm could be AlarmManager alarms set though setExact() and setWindow().

but below 9 minutes it goes to doze mode and do not fire AlarmManager
BroadcastReceiver

It has restrictions on how frequently you can set alarm.

Based on the documentation:

To reduce abuse, there are restrictions on how frequently these alarms
will go off for a particular application. Under normal system
operation, it will not dispatch these alarms more than about every
minute (at which point every such pending alarm is dispatched); when
in low-power idle modes this duration may be significantly longer,
such as 15 minutes.

You can refer to Doze restrictions which says:

Standard AlarmManager alarms (including setExact() and setWindow())
are deferred to the next maintenance window.

  • 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

For Whitelist:

Apps available in whitelist are partially exempt from Doze and App Standby optimizations. This doesn't mean they have full access to and could perform tasks during doze mode. An app that is whitelisted can use the network and hold partial wake locks during Doze and App Standby. However, other restrictions like jobs being differed, standard alarm trigger are still imposed

Note: You should check acceptable usecases for whitelisting an app.

Google Play policies prohibit apps from requesting direct exemption
from Power Management features in Android 6.0+ (Doze and App Standby)
unless the core function of the app is adversely affected.

Precise method to set alarms in Android 6.0

I recently found that an alarm set with setAlarmClock keeps the device from entering IDLE mode within 2 hours of the alarm setting off. It seems like using setAlarmClock with setExactAndAllowWhileIdle is the best approach to go for on Marshmallow.



Related Topics



Leave a reply



Submit