Your application may for some reason need to wake up every now and then to perform some operation. A typical example would be an RSS reader application that wakes up every 30 minutes to download RSS feeds so that the user always has an updated view of the feed when the application is started, or a stalker application that sends a message to one of your contacts every 5 minutes. Listing 7–16 shows how an alarm can be created to wake up the application and start a service that simply prints out a message and terminates. Listing 7–17 shows the implementation of the service.
private void setupAlarm(boolean cancel) {
AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(this, MyService.class);
PendingIntent pendingIntent = PendingIntent.getService(this, 0, intent, 0);
if (cancel) {
am.cancel(pendingIntent); // will cancel all alarms whose intent matches
this one
} else {
long interval = DateUtils.HOUR_IN_MILLIS * 1;
long firstInterval = DateUtils.MINUTE_IN_MILLIS * 30;
am.setRepeating(AlarmManager.RTC_WAKEUP, firstInterval, interval,
pendingIntent);
// use am.set(…) to schedule a non-repeating alarm
}
}
public class MyService extends Service {
private static final String TAG = "MyService";
@Override
public IBinder onBind(Intent intent) {
// we return null as client cannot bind to the service
return null;
}
@Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
Log.i(TAG, "Alarm went off – Service was started");
stopSelf(); // remember to call stopSelf() when done to free resources
}
}
As seen with the sensor event listeners, a single value can make a big difference as far as power consumption is concerned. Here this value is AlarmManager.RTC_WAKEUP
. Android defines four types of alarms:
The RTC
and ELAPSED_TIME
types differ only in the way the time is represented, in milliseconds since the Unix epoch for both RTC types (RTC
and RTC_WAKEUP
) vs. in milliseconds since boot time for both ELAPSED_TIME
types (ELAPSED_TIME
and ELAPSED_TIME_WAKEUP
).
The key here is in the _WAKEUP
suffix. An RTC
or ELAPSED_TIME
alarm that goes off when the device is asleep won’t be delivered until the next time the device wakes up, whereas an RTC_WAKEUP
or ELAPSED_TIME_WAKEUP
alarm will wake up the device when it goes off. Obviously, waking up the device continuously can have a dramatic impact on power consumption even if the application that is woken up does not do anything:
As you can see, this can trigger a chain reaction. Even when the other alarms are the ones consuming more power, for example because they end up transferring data over a 3G connection, your application is the one that triggered everything.
Few applications really need to forcibly wake up the device when an alarm goes off. Of course an application such as an alarm clock would need such capability, but it is often preferred to simply wait for the device to wake up (most commonly following a user interaction with the device) before doing any work. As with the location provider, following a passive approach can lead to a longer battery life.
More often than not, applications need to schedule alarms that go off at some point in the future, without any strict requirement of when exactly they should go off. For that purpose, Android defines the AlarmManager.setInexactRepeating()
, which takes the same parameters as its sibling setRepeating()
. The main difference is in the way the system schedules the time the alarm will actually go off: Android can adjust the actual trigger time to fire multiple alarms (possibly from multiple applications) simultaneously. Such alarms are more power-efficient as the system will avoid waking up the device more often than necessary. Android defines five intervals for these alarms:
While these values are defined as the number of milliseconds they represent (for example, INTERVAL_HOUR equals 3,600,000), they are the only intervals setInexactRepeating()
understands to create “inexact alarms.” Passing any other value to setInexactRepeating
will be equivalent to calling setRepeating(). Listing 7–18 shows how to use inexact alarms.
private void setupInexactAlarm(boolean cancel) {
AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(this, MyService.class);
PendingIntent pendingIntent = PendingIntent.getService(this, 0, intent, 0);
if (cancel) {
am.cancel(pendingIntent); // will cancel all alarms whose intent matches
this one
} else {
long interval = AlarmManager.INTERVAL_HOUR;
long firstInterval = DateUtils.MINUTE_IN_MILLIS * 30;
am.setInexactRepeating(AlarmManager.RTC, firstInterval, interval,
pendingIntent);
}
}
TIP: There is no setInexact()
method. If your application needs to schedule an inexact alarm that goes off only once, call setInexactRepeating()
and cancel the alarm after it goes off the first time.
Clearly, the best results are achieved when all applications use such alarms instead of alarms with exact trigger times. To maximize power savings, your application can also let the user configure how often alarms should go off, as some may find that longer intervals do not negatively impact their user experience.
3.144.106.150