AlarmManager and Sleepy Android Apps

In my first article explaining How to Code an Android Widget, we covered the steps required to create a basic widget that updates on a non-frequent basis and uses standard components. We couldn’t get it to update the widget on a frequent basis however.

In this article, I will show you how to add a periodically firing update to your Widget using an ‘AlarmManager’. I make the assumption that you have already read the introduction Android Widget Coding article, or that you know the basics of App Widget programming.

Frequently Updating Widgets

Android widgets update their contents on a timed basis, waking the phone up to do so, even if the screen is off. If the update frequency is set too high, this can lead to excess battery usage. As a result, the Android system limits the frequency of widget updates to once every half hour or greater.

That’s no good if you want a frequently updating widget, like a clock. What we need here is a method of updating the widget frequently while the screen is on and only when the screen is on. Luckily there is a way this can be done, using a ‘AlarmManager‘, which is a system service wherein your code registers events to go off at particular times, or at particular periods. This allows something to happen at a particular time, even if the application is not running at that time. Even better, when you specify the right type of timer, you can tell it not to deliver the event if the phone is asleep at the time it goes off. This makes it perfect for our cause.

As with Widget updates, alarms are delivered as Intents, just as everything is in Android. So, the first thing we have to do is configure our application to listen to a custom intent type that we will create specifically for our clock updates.

Open up AndroidManifest.xml and add a new intent-filter beneath the existing filter for APPWIDGET_UPDATE. Because we are using a custom intent, we get to name it ourselves, but it should be fully qualified (i.e. have a reversed domain name on the front) so that we can differentiate between our intents and everyone else’s on the system. In this circumstance, I have chosen com.eightbitcloud.example.widget.8BITCLOCK_WIDGET_UPDATE as the name.

<intent-filter>
    <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
    <intent-filter>
    <action android:name="com.eightbitcloud.example.widget.8BITCLOCK_WIDGET_UPDATE" />
</intent-filter>

Next we need to write some code in our ‘ProviderHandler’ to configure the ‘AlarmManager’ to send out our intent on a regular basis. Load up the ‘WidgetProvider’ that we created in the first tutorial, and add the following methods:

private PendingIntent createClockTickIntent(Context context) {
    Intent intent = new Intent(CLOCK_WIDGET_UPDATE);
    PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
    return pendingIntent;
}

@Override
public void onEnabled(Context context) {
        super.onEnabled(context);
        Log.d(LOG_TAG, "Widget Provider enabled.  Starting timer to update widget every second");
        AlarmManager alarmManager = (AlarmManager)context.getSystemService(Context.A
LARM_SERVICE);

        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(System.currentTimeMillis());
        calendar.add(Calendar.SECOND, 1);
        alarmManager.setRepeating(AlarmManager.RTC, calendar.getTimeInMillis(), 1000
, createClockTickIntent(context));
}

@Override
public void onDisabled(Context context) {
        super.onDisabled(context);
        Log.d(LOG_TAG, "Widget Provider disabled. Turning off timer");
        AlarmManager alarmManager = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
        alarmManager.cancel(createClockTickIntent(context));
}

onEnabled() and onDisabled() are called respectively when the first widget is created of your type, and the last is deleted. We want to start sending out the regular ticks when the first widget is created, and we want to stop the ‘AlarmManager’ when the last widget is deleted. We simply call AlarmManager.setRepeating() to create the repeating alarm, and then call cancel() when we are done with it.

Note that when we create the alarm, we specify an Alarm Type of AlarmManager.RTC. This type of alarm is only generated while the phone is awake. This is the feature that we rely upon to deliver updates only when the is awake, and not when the device is asleep.

Now we’ve told Android that our application is interested in receiving these intents, and we’ve configured the ‘AlarmManager’ to send the intents out on a regular basis. All that is left is to write the code that will handle the intents when they arrive. Alter your ‘WidgetProvider‘ class to include the following code:

/**
 * Custom Intent name that is used by the 'AlarmManager' to tell us to update the 
clock once per second.
 */
public static String CLOCK_WIDGET_UPDATE = "com.eightbitcloud.example.widget.8BITCLOCK_WIDGET_UPDATE";

@Override    public void onReceive(Context context, Intent intent) {
    super.onReceive(context, intent);
    Log.d(LOG_TAG, "Received intent " + intent);
    if (CLOCK_WIDGET_UPDATE.equals(intent.getAction())) {
        Log.d(LOG_TAG, "Clock update");
        // Get the widget manager and ids for this widget provider, then call the shared
        // clock update method.
        ComponentName thisAppWidget = new ComponentName(context.getPackageName(), getClass().getName());
        AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
        int ids[] = appWidgetManager.getAppWidgetIds(thisAppWidget);
        for (int appWidgetID: ids) {
            updateAppWidget(context, appWidgetManager, appWidgetID);
        }
    }
}

This code listens for the intent, and updates the component contents when received. The actual code to update the widget is the same as it was in the previous article, but has been refactored into a method called updateAppWidget to avoid repeating ourselves. Have a look at the full code for the class for more information.

So there you have it. Using the ‘AlarmManager’ we can get the Android operating system to send our application an intent on a regular basis. In this example, we’ve used the technique to update a widget on a very frequent basis, but it can also be used to do periodic updates for other components in your application. As an example, I often see that people have background services running to update their network feeds on a periodic basis. This works, but the service sits there running all the time, taking up memory on the device. If they were to use an ‘AlarmManager’, they could simply wake up their service each time it needed to do an update.

I hope that this article has shown how easy the ‘AlarmManager’ is to use. As always, the code is available on GitHub at Widget Example. In a future article, we’ll look at how to introduce complex user interface components to widgets.

Free book: Jump Start HTML5 Basics

Grab a free copy of one our latest ebooks! Packed with hints and tips on HTML5's most powerful new features.

  • http://www.codefruxtechnology.com Codefrux Technologies

    Nice app for the Alarm Manager on Android Mobile….I would work on this…….Thanks for Sharing….

  • Deepak

    Hi,
    Fantastic tutorial. Much appreciated.
    But, I would like to know if this will work if the user “Force Stop” the application. Consider the scenario where an application is installed and the alarm manager is set to do some task repeatedly. Then after some time the user has to “Force Stop” the application by going Settings->Applications->Manage Application->appname->Force Stop.I think this would stop updating the Appwidget as the Force Stop will kill the set Alarm Manager as well. Is there some way in Android using which the intents can be received even when the application is really stopped.

    • Moon

      Thanks for the tutorial.

      I have the same question. When user closes App using task manager my alarms are gone. How to keep them working even if App is not running?

  • Deepak

    Thank you

  • Steve

    Hi

    Thanks for sharing, I needed help on how to update an analog clock frequently with a second hand. This has helped, thanks.

  • http://www.cheesegroup.com Steven

    Great job! This is the clock I’m waiting for :)

    • Ashwini

      Hi..As I’m new to android apps,please do help me on this..I’ve my application which runs on mobile, now i want to include an audio that plays for every half an hour.
      Please let me know how to do this in my app.

      Regards
      Ashwini

  • http://www.hrupin.com Igor

    thanks!
    It is a really good article for updating app widgets.