Search code examples
androidalarmmanager

Android: correct way to use AlarmManager without draining battery


I need to do a background check in my app, basically polling various URLs for new stuff. So I've read this is done with the AlarmManager.

The thing is, I don't need the user to be notified as soon as new stuff arrives. Let's say I'm checking every hour, I'm perfectly fine with not doing any check while the phone is sleeping, and resuming the checks when the phone is used. That way the user eventually gets the notification, but the drain is minimal.

So I've tried with setInExactRepeating. I'm starting it at boot time, but also at app startup (mostly for the session after install, and to make sure it's running even if the app gets "force killed"). How do I prevent all these checks to add up? (A new check should only be run if none is running, or the previous one needs to be stopped).


Solution

  • I've found setInexact Repeating coupled with ELAPSED_REALTIME (or RTC) works quite well to achieve very minimal battery drain. Using the flag FLAG_UPDATE_CURRENT on an existing pendingintent (same intent and id) will simply refresh the current alarm schedule if it already exists. Alternatively, add the code suggested by Ralgha to check and see if you already created the pending intent and set the alarm, and then if not, set the pending intent and alarm schedule. Both methods will likely have the same impact on battery (negligible). What will cause significant drain is doing something on a frequent schedule. The fact that you only want to update every hour and not when the screen is off, your app will use barely any battery (assuming it is done with it's processing relatively quickly and cleans up after itself nicely)

    http://developer.android.com/reference/android/app/AlarmManager.html#ELAPSED_REALTIME

    ELAPSED_REALTIME

    This alarm does not wake the device up; if it goes off while the device is asleep, it will not be delivered until the next time the device wakes up.

    http://developer.android.com/reference/android/app/AlarmManager.html#setInexactRepeating%28int,%20long,%20long,%20android.app.PendingIntent%29

    setInexactRepeating

    These alarms are more power-efficient than the strict recurrences supplied by setRepeating(int, long, long, PendingIntent), since the system can adjust alarms' phase to cause them to fire simultaneously, avoiding waking the device from sleep more than necessary.

    http://developer.android.com/reference/android/app/PendingIntent.html#FLAG_UPDATE_CURRENT

    FLAG_UPDATE_CURRENT

    ...if the described PendingIntent already exists, then keep it but its replace its extra data with what is in this new Intent. This can be used if you are creating intents where only the extras change, and don't care that any entities that received your previous PendingIntent will be able to launch it with your new extras even if they are not explicitly given to it.