Affiliate links on Android Authority may earn us a commission. Learn more.
How to create a widget for your Android app
For users, widgets help them make the most of all that homescreen real estate that would otherwise go to waste. And for developers, creating a widget to accompany your latest Android app is a way of delivering a better user experience (and if you want those 5 star reviews then you should seize any opportunity to deliver a better user experience) plus a well-designed app widget is a useful tool for keeping your app at the forefront of the user’s mind.
Every time the user passes through their homescreen, your widget has an opportunity to catch their interest by presenting them with a snippet of your app’s most important content – ideally tempting them into launching your app.
In this article, I’m going to show you how to create an effective app widget for your latest Android project. I’ll be covering all the essentials of creating a basic widget, before sharing some best practices that can help ensure your widget will have no problem securing itself a permanent spot on the user’s homescreen.
Planning your widget
So, you’re sold on the idea of creating an Android app widget, but the first step is deciding what kind of widget you’re going to build.
If you’re struggling for inspiration, then it can help to look at what other Android developers are doing. When you look at all the Android widgets that are currently out there, they can generally be divided into the following categories:
- Information widgets. Display important information related to your app. Some examples include clock and weather widgets, and widgets that notify the user about new emails or SMS messages.
- Collection widgets. These vertically-scrolling widgets display multiple elements from the same group, such as a collection of headlines from a news app, or a series of photos from a gallery app.
- Control widgets. These widgets give users the ability to trigger an app’s most important features from the comfort of their homescreen – kind of like a remote control. A control widget can help your app feel more like an integral part of the user’s device, rather than an add-on that the user opens, plays around with for a while, and then closes. A widget that allows the user to play, pause and skip tracks in a music application is one example of a control widget.
- Hybrid widgets. Can’t choose between the different categories? Many widgets combine elements from two or more categories – case in point, the music widget from our previous bullet point. Assuming this widget displays some information about the currently-selected track, then this is an example of a control widget that borrows elements from the information widget category. If you do decide to mix and match, then it’s recommended that you target one category first and then add elements from other categories as and when required.
What are the essential components of an Android widget?
To create a widget, you’ll need the following classes and XML files:
- An AppWidgetProviderInfo file. An XML file containing important information about your widget, such as its minimum width and height, its layout resource file, how often it should be updated, and whether it uses a configuration Activity.
- An AppWidgetProvider class implementation. This is where you’ll define the methods that you’ll use to programmatically interact with your widget.
- An XML layout resource file. Your widget’s initial layout.
- An App Widget configuration Activity. If you want the user to be able to modify your widget, then you’ll need to create a configuration Activity. This Activity will launch automatically when the user creates an instance of your widget.
There’s no set rules about the order you should create these files and classes in, but I find that it helps to have a clear idea of how your widget will look, before you start worrying about how it’ll function, so I’m going to start by creating my widget’s layout.
Creating your widget’s layout
You define your widget’s layout in the same way you define the layout for any Activity: create an XML layout resource file and add all the UI elements you want to use.
The only major difference is that widget layouts are based on RemoteViews, so you can only use layouts and views that RemoteViews supports.
Specifically, when you’re creating your widget’s layout you can use the following layout classes only:
- FrameLayout
- GridLayout
- LinearLayout
- RelativeLayout
And you can use the following widget classes only:
- AdapterViewFlipper
- AnalogClock
- Button
- Chronometer
- GridView
- ImageButton
- ImageView
- ListView
- ProgressBar
- StackView
- TextView
- ViewFlipper
Any layout you create should look good and function correctly across a wide range of different screens, however when it comes to widget layouts you have some extra motivation for ensuring you layout is as flexible as possible:
- Users typically place widgets on their homescreens, and although all Android homescreens are divided into a grid, the exact number of cells, spacing and sizing will vary between devices. Your widget needs to be flexible enough to handle all the different homescreen grids it may encounter.
- Users expect to be able to resize widgets horizontally and vertically, so your widget should meet these expectations unless it has a very good reason not to. This means your layout needs to be able to cope with however the user chooses to resize your widget.
Creating a flexible widget layout follows many of the best practices you’ll be familiar with from building other Android layouts, but in particular you should:
- Provide alternate versions of all your layout’s resources. These alternatives should be optimized for a range of different screen configurations. The Android system will then select the best version of each resource to use at runtime, based on the current device.
- Create a density-independent layout. Make sure you specify all layout dimensions using density-independent pixels (dpi) and use flexible units of measure, such as “wrap_content” and “match_parent,” rather than absolute units.
- Test! Make sure you test your widget across a range of screen configurations by creating multiple Android Virtual Devices (AVDs). If you do discover issues with a particular screen configuration, then you may want to create an alternate layout that’s optimized for this particular screen. You should also check that your layout can handle being flipped between portrait and landscape mode, and that it continues to look good and function correctly regardless of how the user resizes it. If you do encounter issues once your widget has been shrunk past a certain size, then you can specify a minimum size for your widget – something I’ll be covering when we create our AppWidgetProviderInfo file.
Create an AppWidgetProviderInfo file
The next step is creating a AppWidgetProviderInfo XML file and defining all the qualities you want your widget to have.
Create a res/xml directory (if your project doesn’t contain one already) and then create a new XML layout inside this directory.
This is going to be our AppWidgetProviderInfo file, so open it and set its root element to <appwidget-provider>. You can now specify all the qualifies your widget should possess – here’s a few examples:
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
// Your widget’s default width and height
android:minWidth="50dp"
android:minHeight="50dp"
// How often your widget should be updated, in milliseconds
android:updatePeriodMillis="90000000"
// The XML file containing the widget’s layout
android:initialLayout="@layout/appwidget"
// Whether the user can resize your widget horizontally, vertically, or both (horizontal|vertical). If you don’t
// want your widget to be resizable, then you can set this attribute to "none"
android:resizeMode="horizontal|vertical"
// Even if you follow all the best practices for designing a flexible layout, if a user keeps shrinking your
// widget indefinitely then at some point it’s going to become unusable. Prevent the user from pushing your
// layout to its breaking point, by assigning it a minimum height and width
android:minResizeHeight="30dp"
android:minResizeWidth="30dp"
// Specify whether your widget can be displayed on the homescreen, (home_screen), the lockscreen (keyguard)
// or both - although only devices running Android 4.0 and lower support lockscreen widgets. Lockscreen
// widgets aren’t particularly private, so if you do give the user the option of placing your widget on their
// lockscreen then just make sure your widget doesn’t feature any sensitive or potentially embarrassing
// information!
android:widgetCategory="home_screen">
</appwidget-provider>
Create Your AppWidgetProvider class
The AppWidgetProvider class is where you’ll define the methods that will be called during the widget’s lifecycle, for example whenever a widget is deleted, enabled or disabled. This class is also where you’ll create the code that’ll ultimately be responsible for updating your widget.
Create a new Java class that extends the AppWidgetProvider class and override its update methods. In my example, I’m going to be using MyAppWidgetProvider.
public class MyAppWidgetProvider extends AppWidgetProvider {
...
...
// Retrieve the widget’s layout//
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.activity_main);
// Tell the AppWidgetManager to perform an update on this application widget//
appWidgetManager.updateAppWidget(currentWidgetId,views);
You’ll then need to declare the AppWidgetProvider class in your project’s Manifest:
//Specify your AppWidgetProviderInfo XML file//
<receiver android:name="MyAppWidgetProvider" >
// Specify that the AppWidgetProvider accepts ACTION_APPWIDGET_UPDATE, which is the broadcast that’s sent whenever
// a new instance of this widget is instantiated and also whenever a widget requests an update. Both of these
// are events that the AppWidgetProvider class needs to be able to respond to
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data android:name="android.appwidget.provider"
// Point the Manifest in the direction of the AppWidgetProviderInfo XML file you created earlier //
android:resource="@xml/myappwidgetprovider" />
</receiver>
Creating an app widget configuration Activity
Do you want the user to be able to customize your widget? These customizations could be visual tweaks, such as changing the widget’s colour, or functional changes such as specifying how often the widget should be updated.
Whatever the specifics, if you want to create a customizable widget then you’ll need to create a configuration Activity, and set this Activity to launch automatically when the user creates a new instance of your application widget.
To add a configuration Activity to your project, create a new Java class (I’m going to use ConfigurationWidget). Then, when you declare this Activity in your Manifest make sure you specify that it accepts the ACTION_APPWIDGET_CONFIGURE intent.
<activity android:name=".ConfigurationWidget">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_CONFIGURE"/>
</intent-filter>
</activity>
You’ll also need to declare this Activity in your project’s AppWidgetProviderInfo using the android:configure attribute, so hop back to this file and add the following:
android:configure="com.example.android.ConfigurationWidget"
Although the main body of your configuration Activity will vary depending on how the user can edit your widget, there’s a few common features you should add to any configuration Activity, in order to ensure it functions correctly.
Firstly, if the user exits the Activity without completing the configuration process, then you should notify the widget host and tell it not to add the widget to the user’s homescreen:
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setResult(RESULT_CANCELED);
Normally, when the user adds a widget to their homescreen, performing the initial setup is the onUpdate method’s responsibility. However, as soon as you create a configuration Activity, this setup becomes the responsibility of the configuration Activity. This means your configuration Activity will need to request an update from the AppWidgetManager:
//Find the App Widget ID from the Intent that launched this Activity//
Intent intent = getIntent();
Bundle extras = intent.getExtras();
if (extras != null) {
mAppWidgetId = extras.getInt(
AppWidgetManager.EXTRA_APPWIDGET_ID,
AppWidgetManager.INVALID_APPWIDGET_ID);
}
// If you receive an intent without the appropriate ID, then the system should kill this Activity//
if (mAppWidgetId == AppWidgetManager.INVALID_APPWIDGET_ID) {
finish();
}
Once you’ve completed this setup, you can fill this class with all the options your users should be presented with when they create an instance of your widget. Just don’t get carried away – setting up a widget shouldn’t feel like a monumental task, so limit yourself to 2-3 configuration options.
Once you’ve written your configuration code, there’s a few final tasks you’ll need to complete. Firstly, you’ll need to get an instance of the AppWidgetManager by calling getInstance(Context):
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
Then, you’ll need to update the app widget with a RemoteViews layout by calling updateAppWidget(int, RemoteViews):
RemoteViews views = new RemoteViews(context.getPackageName(),
R.layout.example_appwidget);
appWidgetManager.updateAppWidget(mAppWidgetId, views);
Finally, create the return Intent, set it with the Activity result, and finish your configuration Activity:
Intent resultValue = new Intent();
resultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mAppWidgetId);
setResult(RESULT_OK, resultValue);
finish();
App Widget Best Practices
Now you know the basics of creating a functioning application widget, let’s look at ways to build on these foundations by covering some best practices.
Include margins for earlier versions of Android
An application widget that extends to the edges of the user’s screen or presses flush against other widgets runs the risk of making the user’s homescreen look messy or cluttered. You can make sure your widget always has some breathing space, by including margins.
On Android 4.0 and higher, the system automatically adds padding between the widget frame and the widget’s bounding box, so you only need to add margins manually when your app is installed on devices running anything earlier than Ice Cream Sandwich. You definitely don’t want to add margins across the board, as your manual margins combined with those automatic margins can seriously add up on devices running Android 4.0 and higher, creating an awkward amount of empty space around your widget.
The solution is to create two dimens.xml files that specify different margins, depending on the device your app is installed on:
- res/values-v14/dimens.xml. In this file, define the 0dp of padding that should be added to the margins that Android 4.0 creates by default.
<dimen name="widgetmargin">0dp</dimen>
- res/values/dimens.xml. This is where you’ll define your widget’s custom margins that should be used on devices running anything earlier than Android 4.0.
<dimen name="widgetmargin">10dp</dimen>
Then, you just need to reference “widgetmargin” in your widget’s layout and the system will select the appropriate widgetmargin value to use at runtime:
android:padding="@dimen/widgetmargin"
Don’t update too often
Up now, we’ve focused on one method of updating your widget: using the updatePeriodMillis attribute to specify an update interval. Once this interval has elapsed, the app widget framework will request an update, and if the device happens to be asleep at the time then it’ll wake up in order to perform this update.
Waking the user’s device every now and again generally isn’t a huge problem, but if your widget requires frequent updates then this can result in a noticeable drain on the device’s battery. And battery-hogging apps rarely get good reviews on Google play! For the sake of preserving the device’s battery life, you should update your widget as infrequently as you can possibly can without compromising the user experience.
If your widget does have a valid reason for requiring frequent updates, then you should avoid using updatePeriodMillis and opt for an alternative, more battery-friendly way of updating your widget.
One option, is to perform updates based on an alarm that only gets delivered if the device is awake. If the device is asleep, then the update will be delayed until the device wakes up, which means your widget’s updates won’t have such a negative impact on the user’s battery.
To use this technique in your project, you’ll need to use the AlarmManager system service to create an alarm and set it to the type AlarmManager.RTC. You can then specify how often you want your widget to update, in milliseconds, for example:
alarmManager.setRepeating(AlarmManager.RTC, calendar.getTimeInMillis(), 1000 , ClockIntent(context));
Even after you’ve written this code, your project’s updatePeriodMillis attribute can override your alarm and wake the device anyway. To make sure this doesn’t happen, find this attribute in your project and set it to android:updatePeriodMillis=”0″
Since alarms are delivered as intents, you’ll need to configure your app to listen for this intent type, so open your project’s Manifest and add a new intent-filter beneath the existing APPWIDGET_UPDATE filter. For example:
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
<intent-filter>
<action android:name="com.jessicathornsby.myapplicationwidget.WIDGET_UPDATE" />
</intent-filter>
With this bit of setup out of the way, you’re free to update your AppWidgetProvider class with the code that specifies how often you want to send this intent, and how your widget should handle these intents when they arrive.
Provide a preview image
You add a new widget to your homescreen by launching your device’s widget picker, browsing the available options, and then selecting the one you like the look of. When you’re browsing this widget picker, you may have noticed that many apps display a preview image of how their widget will look once it’s properly configured and setup on your homescreen.
A well-designed preview image is a good way of encouraging the user to choose your widget over the competition, so it’s well worth taking the time to create a preview image. If your project doesn’t feature a dedicated preview image, then the system will use your app’s launcher icon instead, which doesn’t quite have the same effect.
Create the image you want to use and add it to your project’s ‘drawable’ folder. Then, open your AppWidgetProviderInfo file and point it in the direction of this new drawable resource, using the android:previewImage attribute:
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
...
android:previewImage="@drawable/preview">
</appwidget-provider>
Wrapping Up
In this article, we looked at how to create all the necessary classes and files you’ll need to develop an Android app widget, including an optional configuration Activity that will allow users to tweak your widget’s settings. I also shared some best practices that can help you put those finishing touches to your widget. You can find an app widget outline, complete with all the code covered in this article, on GitHub.
Are you going to develop a widget to accompany your next Android app project? Let us know in the comments below!