Chapter 28 Background Services
Delayed Execution with AlarmManager
To actually use your service in the background, you will need some way to make things happen when
none of your activities are running. Say, by making a timer that goes off every five minutes or so.
You could do this with a Handler by calling Handler.sendMessageDelayed(...) or
Handler.postDelayed(...). But this solution will probably fail if the user navigates away from all your
activities. The process will shut down, and your Handler messages will go kaput with it.
So instead of Handler, you will use AlarmManager, a system service that can send Intents for you.
How do you tell AlarmManager what intents to send? You use a PendingIntent. You can use
PendingIntent to package up a wish: “I want to start PollService.” You can then send that wish to
other components on the system, like AlarmManager.
Write a new method called setServiceAlarm(Context, boolean) inside PollService that turns an
alarm on and off for you. You will write it as a static method. That keeps your alarm code with the
other code in PollService that it is related to while allowing other components to invoke it. You will
usually want to turn it on and off from front-end code in a fragment or other controller.
Listing 28.8 Adding alarm method (PollService.java)
public class PollService extends IntentService {
private static final String TAG = "PollService";
// Set interval to 1 minute
private static final long POLL_INTERVAL_MS = TimeUnit.MINUTES.toMillis(1);
public static Intent newIntent(Context context) {
return new Intent(context, PollService.class);
}
public static void setServiceAlarm(Context context, boolean isOn) {
Intent i = PollService.newIntent(context);
PendingIntent pi = PendingIntent.getService(context, 0, i, 0);
AlarmManager alarmManager = (AlarmManager)
context.getSystemService(Context.ALARM_SERVICE);
if (isOn) {
alarmManager.setRepeating(AlarmManager.ELAPSED_REALTIME,
SystemClock.elapsedRealtime(), POLL_INTERVAL_MS, pi);
} else {
alarmManager.cancel(pi);
pi.cancel();
}
}
...
}
The first thing you do in your method is construct your PendingIntent that starts PollService.
You do this by calling PendingIntent.getService(...), which packages up an invocation of
Context.startService(Intent). It takes in four parameters: a Context with which to send the intent,
a request code that you can use to distinguish this PendingIntent from others, the Intent object to
send, and finally a set of flags that you can use to tweak how the PendingIntent is created. (You will
use one of these in a moment.)