AlarmManager / Android Wear / BroadcastReceiver

Match Timer – Part 3

Previously in this series we’ve looked at the software design decisions and the main timer engine for our Android Wear app to time do football (soccer to our American cousins) matches. In this article we’ll look at how we can wake up periodically in order to update the user.

matchtimerWe have already discussed how we don’t want to have a long running service in order to conserve battery, so we need to wake up periodically instead. The mechanism that we’ll use to do that is AlarmManager to periodically fire Intents which will trigger a BroadcastReceiver. I have chosen to use a BroadcastReceiver over an IntentService for the simple reason that the individual tasks we’ll be performing are extremely lightweight and short lived. Using a BroadcastReceiver will avoid the full Service lifecycle each time a task is performed, so is much more efficient for repeated small talks. The individual tasks that we need to perform will all execute in the order of magnitude of milliseconds.

At the heart of any BroadcastReceiver is the onReceive method, and this is where we shall marshall the various actions to their respective handlers:

This is pretty straightforward – we create a MatchTimer instance (which will be loaded from the values stored in SharedPreferences), and then pass that in to the individual action handler. After this is complete we then optionally, depending on the action which has been performed, update the Notification. More on this later.

We handle eight different actions: Five of them control the state of the timer (START, STOP, PAUSE, RESUME, RESET); one causes the notification to be updated; and two are for the vibration alarms which will be triggered when the total elapsed time and total played time reaches 45 minutes.

Let’s first with the state control actions:

These methods perform two functions. Firstly they set the state of the MatchTimer object; secondly they set the alarms for the elapsed and played alarms whenever the parameters change. There is also a utility method thrown in there for good measure named setUpdate() which will enable an external component to trigger an update.

The methods to set the alarms use the standard AlarmManager are:

One thing here which is worth some discussion is the behaviour of setRepeatingAlarm() because it is a little different on Wear. This is used by the Start action to trigger an alarm every minute to update the notification, so there is always an accurate display of the number of minutes elapsed. The normally expected behaviour would be for this to trigger exactly 60 seconds after it was set, and then every 60 seconds from then onwards. However, it doesn’t quite work like this on Wear. What happens is: when the device is awake it will behave in this way, but as soon as the device goes to sleep this will be re-scheduled to trigger on exact minute boundaries. This is to synchronise the various components so that the device only needs to wake once per minute and that will tied to when the watch face app require an update at minute tick over.

For Match Timer it means that the elapsed minutes that are displayed may be one minute out, but when we’re displaying the elapsed minutes, it isn’t that time critical (it’s when we want second accuracy that we need to be completely accurate) so we can live with this.

The full time alarm handlers use the vibration service:

Finally we have the method to build the notification that gets displayed to the user:

Notifications are an important part of Wear and warrant a custom class to construct them for our purposes. In the next article we’ll cover the Notifications used by Match Timer.

Match Timer is available on Google Play.

Get it on Google Play

© 2014, Mark Allison. All rights reserved.

Copyright © 2014 Styling Android. All Rights Reserved.
Information about how to reuse or republish this work may be available at


    1. As I said in the first article in the series, the full source will be published at the conclusion of the series. The final article will be published on Friday 26th September.

Leave a Reply to Mark Allison Cancel reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.