Monday, 20 February 2012
I recently approached the task of developing an Android widget for the first time. I created an Android battery level widget, mainly so that I could write a tutorial on it.
The tutorial was originally published on the Tuts+ marketplace, which has since ceased to operate. Here's a copy of it: Jump Into Android: Create a Battery Level Widget
Anyway, in this article I thought I'd run through a few tips for creating Android widgets, with specific guidance on retrieving and displaying information about aspects of phone state, such as the battery level. We won't go into too much detail here, but hopefully you'll find it a useful overview of Android widget development.
What's the Difference?
In many ways widget development for Android is the same as development for any other app type on the platform. However, although the differences are slight, they can throw you off when you attempt a widget for the first time. I would strongly recommend not attempting a widget as your first app, but instead trying Android widget development after you've tried developing at least one standard application.
You will presumably already know the difference between widgets and other Android apps from the user's point of view, so let's start there. Widgets are not launched from the application menu, but are instead added to the user's homescreen. Some widgets are interactive, normally allowing users to choose settings on pressing the widget once it is on screen, or when it runs for the first time. The download and installation process is basically the same as for other apps.
What you Don't Need to Do
Since widget apps are not launched in the same way as normal apps, your project structure does not need a main Activity class to execute when the application starts up. As well as removing the need for an Activity class file, this means you do not need to include your main launcher Activity in the project Manifest XML file.
What to Do Instead
Instead of a main Activity class, your widget apps need to extend the AppWidgetProvider class. You also need to include your widget provider in the Manifest as a receiver item, specifying a metadata file along with it. If your widget is going to update, you need to indicate this within the Manifest too, using an intent filter. Your metadata file should be saved in "res/xml" and the code within it should define the basic aspects of your widget, including its dimensions and update frequency where appropriate. The metadata file can also specify an initial XML layout resource to use when the widget appears.
That's basically all you need for a widget, but depending on your own project you may need additional elements. For example, you can override the AppWidgetProvider methods, such as onUpdate, specifying what should happen when the widget updates, which will often involve altering the visual display.
You can optionally include an Activity in your app for configuring the widget. Similarly, you can make the widget interactive by supplying a click listener and presenting an options setting section for your users.
Running and Testing
Testing widgets is roughly the same as testing other Android apps, with some exceptions depending on the nature of your own particular projects. For example, when I created my battery level widget, I could only test it properly by running it on a device, because the emulator by default only shows a battery level of 50%. It's always preferable to test your apps on real devices anyway.
Some widgets have serious performance implications. For example, you can use the AlarmManager class to provide more frequent updates to a widget than you can using the XML metadata method. In such apps, you really need to pay extra attention to efficiency, or your users will be dismayed to see their battery levels draining too fast.
Phone State Including Battery Level
So far we've discussed widgets generally, but you have an additional set of considerations if you're creating a widget to indicate phone state such as battery level. To create this type of widget, you need to register for a receiver. This basically means telling the system to inform your app about changes in state.
If you are setting your widget update frequency in the XML metadata, the most often it can receive updates is every 30 minutes. To update more often, you can use a service, implementing an alarm if the widget needs to update when the device is asleep. You will also need a service if your widget is fetching data over the Web.
The Android system issues broadcasts about certain aspects of the device. Some of these are described as "sticky", including the battery level. This means that the last broadcast hangs around the system, allowing your widgets to access the data within it at any time. For a battery level widget that only updates at the frequency set in the XML metadata, this means that the displayed level will actually be whatever the last level broadcast was, which may have been any time in the past half hour at most. Naturally, this is not ideal for all apps, which is why many of them use services and alarms.
So that's an overview of the basics when developing widget apps. Here are a few related links: