Clock Widget Project
In my last post about inertia I mentioned that I had started to take a look at Android App Widgets. I’ve long had the idea that it would be interesting to create a widget capable of consuming themes for MacSlow’s Cairo Clock project. This very cool analog clock uses a set of SVG graphics to theme the clock in such a way that it can be scaled to various sizes. While I’m not there quite yet, the ultimate goal is that the widget is capable of rendering all of the themes found at gnome-look.org.
This screen capture from the emulator shows multiple live instances of the widget running simultaneously with many different themes. I would not suggest that anyone actually do this do the amount of memory required, however it shows the power of the themes.
Getting to this point has been an interesting process, as the Android widget support definitely makes this type of widget somewhat difficult to build.
AndEngine SVG Support
I’ve had this idea for quite some time. What helped me move forward was the addition of SVG support to AndEngine. Thanks to Nicolas Gramlich yet again for his excellent engine. I’ve found a few glitches along the way that I’ve started to submit patches to the project to correct, but as always his code works amazingly well.
As I mentioned in my inertia post, the standard Android widgets model is really more of a “pull” model versus a “push” model. The widget provider definition file (in XML) specifies the frequency that the Android framework will call the widget’s update functionality:
However, no matter what is specified for this value, Android limits the update frequency to no more than once every 30 minutes to avoid the battery drain associated with executing code too often. Thus, it is necessary to push changes to the widget based on our own schedule to make sure the clock is updated every minute.
My initial implementation used Java’s Timer and TimerTask to do these updates. Looking at the framework’s analog clock implementation, I discovered Android’s time-related broadcast messages:
Using these broadcast messages is a vast improvement over maintaining my own timer threads for this functionality. However, since a widget is nothing more than a fancy broadcast receiver, it is necessary to spin up a separate service to register a broadcast receiver for these messages. On reception of one of these messages, each clock instance is updated to match the current time. This update generates a properly sized bitmap that is pushed to the widget instance:
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.main); views.setImageViewBitmap(R.id.imageview, bitmap); appWidgetManager.updateAppWidget(instanceIdentifier, views);
It’s important to note that there is also an updateAppWidget method call that accepts an instance of android.content.ComponentName. Using this method will update all instances for the specified provider with the bitmap. It took a bit to figure out why all of my clock instances were showing the same theme until I realized it was due to using the wrong method.
Improving Battery Performance
Given that this widget is controlling updates rather than allowing the framework to do the job, my primary concern is in terms of performance. Android devices are notorious for poor battery life, however it does seem that it is primarily due to background applications. I’ve done a couple of things thus far to attempt to minimize battery usage.
No Seconds Hand
At least at the moment, the widget removes the seconds hand to avoid pushing more updates to the screen than necessary. Assuming that Android wants to limit updates to once every 30 minutes, the widget is already pushing updates 30 times more often than the framework would like. Multiplying that yet again by 60 seconds seems like a bit too much. In the future, I may consider allowing the user to enable the seconds hands with proper warnings attached.
Manage Broadcast Receiver Messages
An unfortunate side effect of the way that widgets work is that it does not appear to be possible for a widget to determine if it is actually being displayed. If a widget is placed on screen 1, but the user is currently viewing screen 2, there is really no reason to update the widget. With that said, the implementation can still be smart about updates. The service alters the messages it listens for based on the status of the screen:
- Screen Off
- Screen On
After the user has cleared the lock screen (ACTION_USER_PRESENT), the widget registers to hear time updates as well as the screen turning off. Once the screen turns off, the widget stops listening for time updates and switches to listening for user presence. This lowers the update frequency for the widgets when there is no chance that they will actually be visible to the user.
This project has a chance of being something that I can complete and that others might be interested in actually using. I’m considering whether I want to submit this to the Android Market when it is a bit further along. If I do, I will have to decide whether or not I would charge for it which implies a certain level of required support. Either way, I’m not at the point of releasing any significant amount of source code until I decide what to do with this project.