The following is the first few sections of a chapter from The Busy Coder's Guide to Android Development, plus headings for the remaining major sections, to give you an idea about the content of the chapter.


AlarmManager and the Scheduled Service Pattern

Many applications have the need to get control every so often to do a bit of work. And, many times, those applications need to get control in the background, regardless of what the user may be doing (or not doing) at the time.

The solution, in most cases, is to use AlarmManager, which is roughly akin to cron on Linux and macOS and Scheduled Tasks in Windows. You teach AlarmManager when you want to get control back, and AlarmManager will give you control at that time.

Scenarios

The two main axes to consider with scheduled work are frequency and foreground (vs. background).

If you have an activity that needs to get control every second, the simplest approach is to use a postDelayed() loop, scheduling a Runnable to be invoked after a certain delay, where the Runnable reschedules itself to be invoked after the delay in addition to doing some work. We saw this in the chapter on threads. This has the advantages of giving you control back on the main application thread and avoiding the need for any background threads.

On the far other end of the spectrum, you may need to get control on a somewhat slower frequency (e.g., every 15 minutes), and do so in the background, even if nothing of your app is presently running. You might need to poll some Web server for new information, such as downloading updates to an RSS feed. This is the scenario that AlarmManager excels at. While postDelayed() works inside your process (and therefore does not work if you no longer have a process), AlarmManager maintains its schedule outside of your process. Hence, it can arrange to give you control, even if it has to start up a new process for you along the way.

JobScheduler, added to Android 5.0, also does this. If your minSdkVersion is 21 or higher, JobScheduler is definitely worth considering, as it not only takes time into account, but other environmental factors as well. For example, if you need an Internet connection to do your work, JobScheduler will only give you control if there is an Internet connection. JobScheduler is covered a bit later in the book.

Options

There are a variety of things you will be able to configure about your scheduled alarms with AlarmManager.

Wake Up… Or Not?

The biggest one is whether or not the scheduled event should wake up the device.

A device goes into a sleep mode shortly after the screen goes dark. During this time, nothing at the application layer will run, until something wakes up the device. Waking up the device does not necessarily turn on the screen — it may just be that the CPU starts running your process again.

If you choose a “wakeup”-style alarm, Android will wake up the device to give you control. This would be appropriate if you need this work to occur even if the user is not actively using the device, such as your app checking for critical email messages in the middle of the night. However, it does drain the battery some.

Alternatively, you can choose an alarm that will not wake up the device. If your desired time arrives and the device is asleep, you will not get control until something else wakes up the device.

Repeating… Or Not?

You can create a “one-shot” alarm, to get control once at a particular time in the future. Or, you can create an alarm that will give you control periodically, at a fixed period of your choice (e.g., every 15 minutes).

If you need to get control at multiple times, but the schedule is irregular, use a “one-shot” alarm for the nearest time, where you do your work and schedule a “one-shot” alarm for the next-nearest time. This would be appropriate for scenarios like a calendar application, where you need to let the user know about upcoming appointments, but the times for those appointments may not have any fixed schedule.

However, for most polling operations (e.g., checking for new messages every NN minutes), a repeating alarm will typically be the better answer.

Inexact… Or Not?

If you do choose a repeating alarm, you will have your choice over having (relatively) precise control over the timing of event or not.

If you choose an “inexact” alarm, while you will provide Android with a suggested time for the first event and a period for subsequent events, Android reserves the right to shift your schedule somewhat, so it can process your events and others around the same time. This is particularly important for “wakeup”-style alarms, as it is more power-efficient to wake up the device fewer times, so Android will try to combine multiple apps’ events to be around the same time to minimize the frequency of waking up the device.

However, inexact alarms are annoying to test and debug, simply because you do not have control over when they will be invoked. Hence, during development, you might start with an exact alarm, then switch to inexact alarms once most of your business logic is debugged.

Note that Android 4.4 changes the behavior of AlarmManager, such that it is more difficult to actually create an exact-repeating alarm schedule. This will be examined in greater detail shortly, as we review the various methods and flags for scheduling AlarmManager events.

Absolute Time… Or Not?

As part of the alarm configuration, you will tell Android when the event is to occur (for one-shot alarms) or when the event is to first occur (for repeating alarms). You can provide that time in one of two ways:

For most polling operations, particularly for periods more frequent than once per day, specifying the time relative to now is easiest. However, some alarms may need to tie into “real world time”, such as alarm clocks and calendar alerts — for those, you will need to use the real-time clock (typically by means of a Java Calendar object) to indicate when the event should occur.

What Happens (Or Not???)

And, of course, you will need to tell Android what to do when each of these timer events occurs. You will do that in the form of supplying a PendingIntent. First mentioned in the chapter on services, a PendingIntent is a Parcelable object, one that indicates an operation to be performed upon an Intent:

While the service chapter discussed an Android activity using createPendingResult() to craft such a PendingIntent, that is usually not very useful for AlarmManager, as the PendingIntent will only be valid so long as the activity is in the foreground. Instead, there are static factory methods on PendingIntent that you will use instead (e.g., getBroadcast() to create a PendingIntent that calls sendBroadcast() on a supplied Intent). That being said, our next sample will use createPendingResult(), to keep the sample as simple as possible.

A Simple Example

The preview of this section was eaten by a grue.

The Five set…() Varieties

The preview of this section is out seeking fame and fortune as the Dread Pirate Roberts.

The Four Types of Alarms

The preview of this section was traded for a bag of magic beans.

When to Schedule Alarms

The preview of this section was abducted by space aliens.

Archetype: Scheduled Service Polling

The preview of this section is sleeping in.

Staying Awake at Work

The preview of this section is being chased by zombies.

Warning: Not All Android Devices Play Nice

The preview of this section is in the process of being translated from its native Klingon.

Debugging Alarms

The preview of this section was abducted by space aliens.

WakefulBroadcastReceiver

The preview of this section is sleeping in.

Android 6.0 and the War on Background Processing

The preview of this section took that left turn at Albuquerque.

Android 7.0 and OnAlarmListener

The preview of this section was abducted by space aliens.