Building a Customizable Android Analog Clock Widget
Developing widgets for the Android platform involves a slightly different set of tasks than standard app development. In this series of tutorials, we will work through the process of developing a customizable analog clock widget. The clock will be based on the Android AnalogClock class and customized with your own graphics.
Once the clock is added to the user's homescreen, it will continuously update to display the current time. We will define the properties of the widget in XML, with a Java class extending AppWidgetProvider to manage updates. We will also allow the user to configure the widget appearance by clicking on it, with an Activity class handling user interaction. As you may have noticed, the Google Play listings for widgets often have poor ratings and comments from users who don't realize a widget is not launched in the same way as a normal app. For this reason, and to accommodate some issues with devices running Android 4.0 (Ice Cream Sandwich), we will also include an informative launcher Activity for the widget app. We will also specify the layout and various other application resources in XML.
This tutorial series on Building a Customizable Android Analog Clock Widget is in four parts:
- Android Widget Project Setup
- Designing the Clock
- Receiving Updates and Launching
- Implementing User Configuration
Here's a snapshot of what the end result will look like with the default display (i.e. before user customization):
In this first part of the series, we will setup our widget project, add the necessary elements to the Manifest file, and create the XML resource file that will define the basic properties of the widget. This initial tutorial only involves a few steps, but understanding each of them is vital for learning the essentials of widget development.
Step 1: Start an Android Widget Project
If you have only created standard Android apps in the past, creating a widget project is a little different. Start your project in Eclipse in the usual way, choosing "File," "New" and then "Project." Select "Android Project" from the list and then press "Next." In the "New Android Project" window, enter the name you want to use for your widget project and click "Next."
Select a build target for your app and click "Next." We are targeting Android 4.0, which is API level 14.
In the Application Info window, enter your package name. When you develop a widget app, you do not need to create an Activity, so you can optionally uncheck the "Create Activity" section. However, we are going to include an Activity to provide information about using the widget, so we will let Eclipse create the Activity for now. You can alter the minimum SDK here or optionally modify it in the Manifest file.
Click "Finish" and Eclipse will build your project.
Step 2: Edit the Project Manifest
Open your project Manifest file - it should be saved as "AndroidManifest.xml" in the project folder, visible within the Package Explorer. Double-click to open it, then select the "AndroidManifest.xml" tab so that you can edit the XML code directly.
If you did not alter the minimum SDK when you created the project, but you wish to do so now, you can alter the "uses-sdk" element as in the following example:
<uses-sdk android:targetSdkVersion="14" android:minSdkVersion="8" />
As well as specifying the minimum SDK here, we also indicate the target SDK. By targeting level 14, we can make use of the automatic margin space between widgets that appears on devices running Ice Cream Sandwich.
At this point, you could edit the main Activity section of the Manifest if you did not want to use a launcher Activity. However, we are going to leave this section as it is. There are two reasons for doing so:
- When users download a widget through Google Play, they often instinctively attempt to open it, forgetting or not knowing that widget apps are not launched in the normal way but are instead added to the homescreen. When this happens, we can use the main launcher Activity to display a little informative text explaining how to add the widget - preempting any negative comments or ratings from confused users.
- There is an issue with widgets running on Android 4.0 that sometimes prevents users from being able to add new widgets to their screens. In 4.0, users add widgets by opening the device menu, selecting the Widget tab, finding the widget listed there then pressing to hold it, dropping it onto the homescreen. However, in some cases a new widget does not appear in the Widget tab - normally this is solved when the device is restarted, but it can of course cause confusion and prevent the use of your app. Providing a launch Activity prevents this issue.
After the closing Activity tag, but inside the Application element, add another Activity element for the screen we will include to let users select a custom clock style:
<activity android:name=".ClockChoice"> </activity>
The Activity will be named "ClockChoice" and we will add to the project in Part 4. After the new Activity element, add a Receiver element to your Manifest as follows:
<receiver android:name=".ClockWidget" android:label="Custom Clock Widget"> </receiver>
Here we indicate the class that will handle updates to the widget, which will be "ClockWidget" and will extend AppWidgetProvider. Inside this Receiver element, between its opening and closing tags, add an Intent Filter as follows:
<intent-filter> <action android:name="android.appwidget.action.APPWIDGET_UPDATE" /> </intent-filter>
This specifies that the widget is going to receive updates. Finally, still inside the Receiver element, add a meta-data element:
<meta-data android:name="android.appwidget.provider" android:resource="@xml/clock_widget" />
Here we specify an XML file in which we will declare the basic properties of the widget, using the name attribute to indicate that this file contains data for an AppWidgetProvider. Save your Manifest file - don't worry if you see an error because the XML resource cannot be found, we will create it next.
Step 3: Define the Widget Properties
Let's now create the XML resource we specified in the Manifest. The widget properties will be defined in this file. In your project resources directory, add a new folder named "xml" if there is not already one there. Right-click the "res" folder (or select it and choose "File"), select "New" then "Folder", and enter "xml" as the folder name before clicking "Finish."
Now create a new file in this folder by right-clicking it (or selecting it and choosing "File"), choosing "New" then "File" and entering "clock_widget.xml" to match the name you included in your Manifest meta-data element.
Click "Finish" to create the file - don't worry about any errors, they will disappear when we add our XML code.
Your file should open automatically in Eclipse. Select the "clock_widget.xml" tab to edit the code.
The widget XML only needs a single XML element - add it as follows:
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android" android:minWidth="146dp" android:minHeight="146dp" android:updatePeriodMillis="0" android:initialLayout="@layout/clock_widget_layout" />
The element attributes here are the bones of any widget app. First, we define the minimum width and height for the clock widget as it will appear on the user's screen. We use density-independent pixels to let the Android system cope with screen density variations. When calculating the size of a widget, you multiply the number of cells you want on each axis by 74, then subtract 2 from the result. We want the clock widget to be 2 cells wide and 2 cells in height, so the minimum height and width are both 146.
The update period value determines how often your widget app will update. As we are using the Android AnalogClock as the basis for our widget, we do not need to worry too much about this value and can supply zero. When you are developing widgets you plan on updating within your own application code, you may need to supply a different value here. If you do use this value to determine the update period, the most often updates will occur is every 30 minutes. However, you can provide more frequent updates if you use an AlarmManager within your app.
Finally, we indicate the widget's initial layout by naming a layout file, which we will add to the project in the next tutorial - don't worry about the errors Eclipse displays in the meantime. There are other attributes you can include in the "appwidget-provider" element if you wish, such as a preview image for users to see before adding your widget - if you do not provide a preview, users will instead see the app icon in the widget picker or menu.
Step 4: Add Values to the Project
The final preparation step for the clock widget concerns the app's value resources. Eclipse should have created a "values" folder inside the "res" folder for your project, with the Strings XML file already included. We are going to add another values folder specifically for Android APIs from 14 onwards. This will allow us to tailor certain aspects of the widget to those API levels, particularly the Strings that appear within the interface and the dimension values we use to apply margins to the widget display.
Create a new folder in your "res" directory by right-clicking it (or selecting it and choosing "File"), selecting "New," "Folder" and entering "values-v14" before clicking "Finish."
Open the Strings XML file from your main values folder and select the "strings.xml" tab to view the code.
First edit the application name String to something more readable, as follows:
<string name="app_name">Custom Clock Widget</string>
Next, edit the "hello" String to provide instructions:
<string name="hello"> Hello\n\n Thanks for installing the Custom Clock Widget.\n\n You need to add the widget to your home screen to use it. Long-press the home screen and select the widget from the list of those installed on your device. </string>
This is the informative text we will display if the user launches or opens the app after installing it. Of course, you can edit this text in any way you like. As the process for adding widgets is different for devices running Android 4.0 and up, we will use a slightly different String to target those users. Save your main Strings XML file, then copy and paste it into the "values-v14" folder. To copy, right-click the "strings.xml" file in the "values" folder (or select it and choose "Edit") then select "Copy." To paste, right-click "values-v14" (or select it and choose "Edit") and select "Paste." Now open the version of the Strings XML file in the "values-v14" folder. Edit the "hello" String in this new copy of the file to suit users on Android 4.0 plus:
<string name="hello"> Hello\n\n Thanks for installing the Custom Clock widget. You need to add the widget to your home screen to use it. Select the Widget tab within your device application menu. When you find the clock widget, press and hold it, dropping it to add to your screen. </string>
Now each user will see an informative String that is relevant to their own device. We will include these Strings when we create the launch Activity layout. Later, we will add another file to each values folder, but this is all we need for now.
We have now carried out the setup tasks for the widget, so we are ready to implement the clock design, which we will do in the next tutorial. This will involve creating drawable XML layout files for the widget and launcher Activity display. In Part 3, we will handle receiving updates for the clock and implementing the launch Activity. In Part 4, we will add the ability for users to choose a clock display option on clicking the widget.