Android: Prefer Alarms and Intent Receivers to Services

Cyanogen LogoContinue learning from “A Beginner’s Guide to Android” Google I/O 2010 talk, here is an example on how to use Intent Filter + Intent Receiver + Alarm to implement “schedule to execute every so often” functionality.

In Android, Alarms let you set an event to happen either in the future or on an ongoing basis in the future.

Let’s say we have a listener ( extends BroadcastReceiver ) that would execute a certain action ( MyService ):

public class MyReceiver extends BroadcastReceiver {
 
    @Override
    public void onReceive( Context context, Intent intent ) {
 
        Intent myIntent = new Intent( context, MyService.class );
        context.startService( myIntent );
    }
}

Now let’s connect/map this listener/receiver to a “REFRESH_THIS” Intent by creating an intent filter in a manifest file:

<receiver android:name="MyReceiver">
    <intent-filter>
        <action android:name="REFRESH_THIS"/>
    </intent-filter>
</receiver>

So whenever a system broadcasts a “REFRESH_THIS” intent, MyReceiver is going to spawn up and a “context.startService( myIntent )” is going to be executed.

Now in order to schedule “REFRESH_THIS” intent to be broadcasted, we would use an AlarmManager:

String alarm = Context.ALARM_SERVICE;
AlarmManager am = ( AlarmManager ) getSystemService( alarm );
 
Intent intent = new Intent( "REFRESH_THIS" );
PendingIntent pi = PendingIntent.getBroadcast( this, 0, intent, 0 );
 
int type = AlarmManager.ELAPSED_REALTIME_WAKEUP;
long interval = AlarmManager.INTERVAL_FIFTEEN_MINUTES;
long triggerTime = SystemClock.elapsedRealtime() + interval;
 
am.setRepeating( type, triggerTime, interval, pi );

The above Alarm will wake up a device every 15 minutes and execute MyReceiver’s onReceive() method. The cool thing is that even if your application is killed, this alarm will continue to run without your application running on the background consuming resources.

One thing to note..

Prefer Inexact Alarms …so OS can optimize when the alarm goes off

Why!?.. Let’s say there are 15 applications that set 15 alarms, which take a minute each to execute, and are all scheduled to be executed with a 15 minute interval => Potentially ( depending on the time they’ve been scheduled at ) they can end up executing every minute ( one after another ) resulting in Android device to be constantly on which is a dramatic impact at the resource usage.

“Inexact Alarms” would let OS “phase shift” these alarms to execute at the same time, rather than being arbitrary distributed depending on the time they were scheduled at. This allows OS to optimize and allocate resources in more intelligent fashion. So if you have something that needs to happen regularly, but does not need to happen at exact time, use “Inexact Alarms”.

In the above “alarm example”, in order to use Inexact Alarm change this line:

am.setRepeating( type, triggerTime, interval, pi );

to

am.setInexactRepeating( type, triggerTime, interval, pi );

Now the alarm will rely on the OS to optimize its execution time.