Professional Documents
Culture Documents
Figure 1
Then click on Finish. This will create you a fully working and testable Android application.
Run it in the emulator now if you like, by right clicking on the project and selecting Run As
Android Application. You might need to create a definition for an emulator. Once running,
the app simply displays you a black screen with a Hello World string in it. Boring, but it is a
good starting point.
In Android, all components that are shown in the OS are defined in the manifest file. Load
upAndroidManifest.xml from the top level of your project. Eclipse will show you the file in a
structured editor, but if you are familiar with XML, it might be easier to switch to the source
view by selecting the last tab in the editor. It should look something like this:
1 <?xml version="1.0" encoding="utf-8"?>
2 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
3
4
5
6
package="com.eightbitcloud.example.widget" android:versionCode="1"
android:versionName="1.0">
<uses-sdk android:minSdkVersion="8" />
<application android:icon="@drawable/icon" android:label="@string/app_name"
>
7
8
9
10
11
12
13
14
15
<activity android:name=".WidgetExampleActivity"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
The important thing that is in this file at the moment is the Activity that specifies the main
view of the application. Youll see it inside the application tag. This tells Android where the
class is that specifies the main view of your application, what name it should be given (by
the label attribute), and what intents it should respond to. The main view is marked as
the MAIN action to indicate that Android should load it up when the app starts, and
with LAUNCHER to indicate that it should appear in the application list. None of this is
directly related to widgets, but is useful background on how Android handles its manifest.
To add our widget, we need to introduce a new element to the manifest that specifies it.
Below the activity, add the following
1 <receiver android:name=".ExampleAppWidgetProvider" android:label="8-bit cloud
widget 1">
2
<intent-filter>
3
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
4
</intent-filter>
<meta-data android:name="android.appwidget.provider"android:resource="@xml
/widget1_info" />
6 </receiver>
5
by specifying a value for theandroid:label attribute. Normally, you would specify this in your
applications res/values/strings.xmlfile, but for the sake of simplicity I have placed the value
directly in the manifest file. I used 8-bit cloud widget 1. The remainder of the configuration
of the widget will be specified in the meta-data file, which will be located in
the res/xml/widget1_info.xml file. Our next step is to create that meta-data file. Create it by
selecting File New Other Android Android XML and fill it in as follows.
Figure 2
Once the file is created, switch to the source tab, and set the contents of the file to the
following:
1 <?xml version="1.0" encoding="utf-8"?>
2 <appwidget-provider xmlns:android=
"http://schemas.android.com/apk/res/android"
3
android:minWidth="294dp"
4
android:minHeight="72dp"
5
android:updatePeriodMillis="1000"
6
android:initialLayout="@layout/widget1">
7
</appwidget-provider>
The minWidth and minHeight parameters specify the size of the widget. There are special
rules about the sizes that Android widgets can have because Android arranges its home
screens in a grid of 4 x 4. The documentation specifies that you calculate the size by using
the following formula:
size = (number of cells * 74) 2
In our example, we want our widget to be 4 * 1 cells in size, so we specify the size as (4 *
74) 2 = 294 by 72 dps.
Android views only update on a periodic basis. We want to display a clock, so Ive put in
anupdatePeriodMillis of one second (1000 ms), so that it updates every second. It turns out
that values this small dont work, but Ill come back to that later. Finally, we specify what
layout will be used for the widget. Lets create that layout file using the same android XML
creation wizard we used before, except this time we select a layout type and a file name of
widget1. As before, switch to the source tab of the file, and use the following contents:
1
2
3
4
5
6
7
8
9
<TextView android:id="@+id/widget1label"android:layout_height="wrap_cont
1
0 ent" android:textAppearance="?android:attr/textAppearanceLarge" android:layou
t_width="wrap_content"/>
<Button android:text="Click
1
1 Me!" android:id="@+id/button"android:layout_width="wrap_content" android:lay
out_height="wrap_content"/>
12 </LinearLayout>
The layout specifies what components will be in the widget, and how they are laid out. The
important things to see here however are the TextView and Button components that have
been added to it. They correspond to the components that will be shown on the screen.
When creating your widget, you might be tempted to create fancy layouts, using your own
custom components and complex layouts. There are quite severe restrictions on which
components can be used in Widgets however, because the widget runs in a different
application, and doesnt have access to your own code when rendering.
There are sneaky ways you can make your widget look like its more complex however,
which I will cover in another article. For now, note that the only components that you can
use in a widget are:
FrameLayout
LinearLayout
RelativeLayout
AnalogClock
Button
Chronometer
ImageButton
ImageView
ProgressBar
TextView
ViewFlipper
Youll notice in the layout that there is a background specified for the widget as well. Youll
need to create your own background drawable in res/drawable/background, or you could
use the one I created for the example.
1
package com.eightbitcloud.example.widget;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import android.app.PendingIntent;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.Context;
10
import android.content.Intent;
11
12
import android.util.Log;
import android.widget.RemoteViews;
13 public class ExampleAppWidgetProvider extends AppWidgetProvider {
14
DateFormat df = new SimpleDateFormat("hh:mm:ss");
15
16
21
22
23
This class contains the code that will be used to update our view each time that the timeout
period expires. It is responsible for updating the contents of the widget. Widgets run in a
different application (the Home screen) to our application, so it is not just a matter of simply
updating the components. Instead, you are given access to a RemoteViews component
which you can use to set strings, images and button actions on the remote components.
In our case, we are looking to do two things. First, we want to add an action listener for our
button so that when we click on it, it opens up our main application. This is done with
the PendingIntent and thesetOnClickPendingIntent() method. Second, we want to update
the TextView in our view to show the current date. This is done via the call
to setTextViewText(). Once this is done, we update the widget using
the updateAppWidget() method.
Voila! We now have a working widget application. Install it on your emulator by selecting the
run profile you created before. As before, it will show you the application view. Quit out to
the Home screen using the home button, then long press on the background and
select Widget. You should now be presented with a list of widgets, with your widget in the
list. Select your widget, and it will be added to your home screen.
Figure 3
Figure 4
Yay! Hang on, the clock isnt updating! We set the update period to 1 second in our metadata file, so it should update once every second, right? It turns out there is a very good
reason for this. Every time a widget needs updating, Android will wake up your device, load
your application, and run the WidgetProvider class to update the widget. It does this even if
your screen is off and the phone is asleep. If the update period were set to only run a few
times an hour or less frequently, then this doesnt amount to much of a battery drain. If the
update period is very short like our example, then the widget would drain very quickly and
you would have a long list of angry customers. To avoid this, Google limits the update period
to once every half an hour or greater.
Luckily there is another way to handle more frequent updates; one that only operates while
the screen is on so as not to drain the battery. To do this, we use the AlarmManager. Using
the AlarmManager will be the focus of my next article.
As with all my articles, I have posted the source to GitHub. You can find the code as part of
my Android-Examples repository, in the WidgetExample subdirectory. This project will be
updated as the tutorial series progresses, so I have marked this first example as a tag.
Please feel free to ask questions or provide feedback