So what’s your Widget look like?
This is what our widget looks like. It’s updated every 30 minutes. Pressing the button starts a new activity where we display an image
Describe your Widget’s layout in an XML layout file
You’ll need a layout for your widget.
Widget layouts are based on RemoteViews. RemoteViews don’t support all of the available views and layouts.
We’ve used a LinearLayout, an ImageView, two TextView’s and a Button in our RemoteViews view. Check the documentation, Creating the App Widget Layout for more options.
Create your widget’s layout like you would any other and save the file in the res/layout folder.
There are some strict requirements for widget sizes. So you may want to check the official documentation for more on designing the widget:
- The Standard Widget Anatomy
- Designing Widget Layouts and Background Graphics
- Using the App Widget Templates pack
- Download the App Widget Templates Pack
Describe your Widget Provider in an XML file: Use the AppWidgetProviderInfo Class’s fields
You’ll need to describe your widget: such as how big it is, where to find your widget layout file and how often it should be updated.
You define your widget in an XML file saved in the res/xml folder.
Here’s the code for ours:
Describe the metadata of your widget in an XML file
Note the following:
- We describe the metadata for our app widget provider using the AppWidgetProviderInfo class fields. It’s described in an XML file, res/xml/appwidget_provider.xml
- We use only a few of the available fields. Check the documentation for more
- configure – we want the user to be able to configure the widget before it’s displayed. So we specify the activity to launch to configure our app widget here
- initialLayout – this is the widget layout that specifies what the widget should look like
- minHeight – the default height for the widget
- minWidth – the default width for the widget
- updatePeriodMillis – a time in milliseconds indicating how often the widget should be updated
Your Widget’s dimensions
Your widget may display larger than your minimum dimensions as it’s resized to fit the given screen.
Homescreens are divided into grids. Generally, handsets have a 4x4 grid while tablets have an 8x7 grid.
Your widget will stretch to fill up the minimum number of cells while satisfying your minimum width and height requirements
You can use this formula to calculate the size:
70 x (number of cells (columns or rows)) - 30
Check out the documentation for more on calculating the size of your widget’s layout.
Updating your widget
You specify how often you want your widget to update. Try not to let it update too often as it can drain the battery. The minimum update period is every half hour.
Configuring your widget
You can include an activity where the user can configure the widget before it is displayed for the first time. We’ll discuss this later.
Create your widget provider class: MyWidgetProvider
You need an AppWidgetProvider class to receive broadcasts. These broadcasts trigger methods to enable, update, disable and delete your widget.
Our MyWidgetProvider class extends the BroadcastReceiver class to handle the widget’s broadcasts. These broadcast events trigger the following methods:
- onUpdate – called to update the widget. You set the frequency with the updatePeriodMillis attribute when you defined the widget. Note:
- It’s also called when the user adds the widget to their Homescreen
- It’s not called when added to the screen if you use a configuration activity, the configuration activity should do this after configuring the widget. However, it will be updated at the regular interval after that
- onAppWidgetOptionsChanged – called when first added to the Homescreen and each time the size of the widget changes
- onDeleted – called when the widget is deleted
- onEnabled – called when the widget is created for the first time. Note that you can have more than one instance of the same widget running. onEnabled() is called when the first widget is added to the host
- onDisabled – called when the last instance of the widget is deleted
- onReceive – all Broadcast Receivers execute this method. It’s not necessary here as the AppWidgetProvider class receives and filters the broadcasts and then calls one of the appropriate above methods
Register the provider in the manifest
You need to register the provider in the manifest, as you would any other BroadcastReceiver:
We register our app widget provider in the AndroidManifest.xml file
Note the following:
- we declare our app widget provider in the AndroidManifest.xml file
- it’s a BroadcastReceiver so we use the <receiver> element
- <meta-data> - this element specifies the AppWidgetProviderInfo resource. We need to specify the following attributes:
- name – we use the java style naming convention and name it android.appwidget.provider
- resource – specifies the location of our AppWidgetProviderInfo XML resource file
- <intent-filter> - this broadcast receiver will only receive broadcasts that match this filter. The <action> attribute specifies that this receiver will accept the ACTION_APPWIDGET_UPDATE broadcast. Note that this is the only action that you must declare. All other App Widget broadcasts (ACTION_APPWIDGET_ENABLED, ACTION_APPWIDGET_DISABLED, ACTION_APPWIDGET_DELETED and ACTION_APPWIDGET_OPTIONS_CHANGED) are automatically sent to our app widget provider
Our provider receives the broadcasts and executes the appropriate method. You may want to read Android Broadcast Receivers for more on receivers (there’s a link to a great tutorial too!).
Called to update the widget.
The onUpdate() method is triggered when our provider receives a broadcast message to update the widget
Note the following:
- This method is called in response to the ACTION_APPWIDGET_UPDATE broadcast requesting our App Widget provider to provide a RemoteViews view for the widget. We use it to update the widget
- The method receives three parameters:
- The context
- An instance of the AppWidgetManager – it manages the state of the widgets. We use it update the widget
- An array of widget id’s. Remember that we can have a number of the same widget running at the same time. Each has its own ID
- N – the number of instances of this widget currently running
- The for loop – we loop through all the instances of the widget to get the:
- appWidgetId - each individual widget’s ID
- widgetLabel - each widget’s label. The labels are saved in a preference file. We use the configuration activity’s loadWidgetLabelPreference() method to get the label out of the preference file
- updateOurWidget – we call this method to update the widget, passing it the four parameters: the context, an instance of the app widget manager, the widget’s ID and its label
Called in response to the ACTION_APPWIDGET_ENABLED broadcast which is sent when the first instance of the widget is created.
We have our own BroadcastReceiver, MyWidgetBroadcastReceiver. It only needs to be active while our widget is displayed so we enable it here and disable it in onDisabled().
onEnabled() is called when the widget is created for the first time. We use it to enable our BroadcastReceiver
Note the following:
- pm – the package manager. Allows us to get information about application packages installed on the device
- setComponentEnabledSetting – this is where we set the state of the broadcast receiver. There are three parameters:
- the component name – our broadcast receiver
- the state of the component – we set it to enabled
- flags – optional behaviour. We don’t want to kill the app containing the widget
We finish off the tutorial in part 2, App Widget tutorial: part 2.
I hope that you have found this tutorial helpful.