The good old times

Android was always a tolerant platform when it came to the background operations. As a developer, you could almost always assume that your background job will get performed, as long as you acquire proper wakelocks (ask your fellow iOS developers how envious they are of this). But what’s good for developers isn’t always good for users – such behavior favored poorly written apps that were killing users’ batteries by constantly keeping their devices up and running. Marshmallow’s Doze and App Standby concepts are Google’s picks to solve that problem once and for all.


The newest Android detects when your device is unplugged, not moving and has its screen turned off. Once all these requirements are met, Android will enter Doze mode after some time. This means no SyncAdapter and no JobScheduler will perform. Also, AlarmManager’s functionality will be limited when in Doze, but you can bypass this behavior if you really (but REALLY) need it.

No worries, it doesn’t mean your sync requests or delayed JobScheduler’s tasks will be ignored. They’ll get batch executed once Android exits Doze mode for a maintenance window (which, according to my research, results in approximately 5-10 minutes of possible networking).

Maintenance windows in Doze won’t happen frequently. First window occurs an hour after last activity, the next after two, the next after four and so on. But it doesn’t matter that much since user isn’t even moving her device anyway.

App Standby

From a single app’s perspective, App Standby isn’t much different from Doze. Basically, what Doze does on a system-wide level, App Standby does on a single app level. This means Android 6.0 now detects whether user is using your app or not. In the latter case it moves your app to idle mode. Differently than Doze maintenance windows are much more rare – approximately one per day. Heartbreaking? I know. But you have to live with it. Good thing is that your app isn’t idled without a reason – if the user doesn’t use it actively, why would you care about frequent syncs for her?

AlarmManager to the rescue

There are some cases when Doze/App Standby could cause some serious harm to user’s experience. Take the alarm clock app. You probably wouldn’t be satisfied with a longer battery life being late at the office just because your phone was in Doze at 7 AM. Fortunately, Marshmallow’s AlarmManager offers a way to bypass that behavior in special cases.

AlarmManager.setAndAllowWhileIdle(int type, long triggerAtMillis, PendingIntent operation);
AlarmManager.setExactAndAllowWhileIdle(int type, long triggerAtMillis, PendingIntent operation);

Be aware that both these methods are available since API Level 23. There’s no AlarmManagerCompat in any of the support libraries, but it’s pretty straightforward to write a replacement on your own.

public class AlarmManagerCompat {
  // ...
  public void setAndAllowWhileIdle(int type, long triggerAtMillis, PendingIntent operation) {
    if (isAtLeastMarshmallow()) {
      mAlarmManager.setAndAllowWhileIdle(type, triggerAtMillis, operation);
    } else {
      mAlarmManager.set(type, triggerAtMillis, operation);

  public void setExactAndAllowWhileIdle(int type, long triggerAtMillis, PendingIntent operation) {
    if (isAtLeastMarshmallow()) {
      mAlarmManager.setExactAndAllowWhileIdle(type, triggerAtMillis, operation);
    } else {
      mAlarmManager.setExact(type, triggerAtMillis, operation);

These methods can come in handy if your application:

  • Uses reminder notifications, for instance of upcoming tasks or calendar events,
  • Offers the alarmclock functionality.

One important thing. The fact your PendingIntent will get executed doesn’t mean you’ll be able to perform network requests. You can’t rely on the Internet connection in services you start using the AlarmManager. AlarmManager’s new methods are okay for scheduling offline work, but they won’t do for periodic networking.

High-priority GCM messages

Some apps may require connection regardless of the device being in Doze. Take the Hangouts app as an example. It would be useless if it would need several hours to deliver an incoming message notification. Fortunately, GCM comes to the rescue here and you can send the so-called high-priority messages to wake up user’s device no matter if it’s in Doze, or if your app is idle. High-priority messaging is a new concept, introduced together with Marshmallow’s developer previews. Turning it on is just a matter of adding a priority field to your GCM payload. All the “legacy” messages will be considered as with a ‘normal’ priority and won’t be delivered outside of the maintenance windows.

Attention! Overuse of this behavior can lead to some serious battery draining. You shouldn’t use high-priority GCM messages for periodic syncs. Use them wisely – good use cases would be the instant messaging functionality or a networking job that results in displaying a foreground notification.

Be a good citizen

Your app isn’t the only app on your user’s device. And most likely – unless you’re Baby Instant Sleep* app – it’s not the most important app on your user’s device. Nobody likes the feeling of ‘15% battery remaining’ popup just a few hours after they were fully charged. Behave well and be a good citizen. Your users will be grateful.

* Forgive me this dadsjoke, but I’m a fresh father of twins, I had to.

Cover photo by Tambako licensed with Attribution-NonCommercial 2.0 Generic License

Posted by

Share this article

  • user30000z

    Thanks, Great article.

    This is the reason I’m holding my iOS device : “Behave well and be a good citizen” …. yes, I really trust Android developers to behave (NOT).

  • Krishnan Marimuthu


    When we receive GCM Notification, how long the app has internet access?

    • According to Google documentation a high priority gcm message “gives the app temporary access to network services”. Our tests indicate that the app cannot access network, regardless of the gcm message priority setting.

      • Krishnan Marimuthu

        I tested this today also. I able to observe we are getting network access for 10 seconds when we receive GCM notification. I checked this by using dumpsys. I used the command (adb shell dumpsys deviceidle). A new section temp_whitelist was added with my app UID. After 10 seconds, this section is removed.

        Whether there is a way to increase this 10 seconds for an app ?

        • Interesting, we’ll have to take a second look at Doze. In any case, I highly doubt that you can increase this 10 seconds window duration.