Alarms

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.

Listing 7–16. Setting Up An Alarm

    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
        }
    }

Listing 7–17. Service Implementation

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:

  • ELAPSED_TIME
  • ELAPSED_TIME_WAKEUP
  • RTC
  • RTC_WAKEUP

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:

  • The device will wake up to start your own application.
  • Other (well-behaved) alarms that were waiting for the device to wake up will be delivered.

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.

Scheduling Alarms

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:

  • INTERVAL_FIFTEEN_MINUTES
  • INTERVAL_HALF_HOUR
  • INTERVAL_HOUR
  • INTERVAL_HALF_DAY
  • INTERVAL_DAY

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.

Listing 7–18. Setting Up An Inexact Alarm

    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.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.147.84.62