App widgets are miniature application views that can be embedded in other applications (such as the home screen) and receive periodic updates. These views are referred to as widgets in the user interface, and you can publish one with an app widget provider (or widget provider). An app component that is able to hold other widgets is called an app widget host (or widget host). The following example shows a music widget.

This document describes how to publish a widget using a widget provider. For
details on creating your own AppWidgetHost
to host app
widgets, see Build a widget host.
For information about how to design your widget, see App widgets overview.
Widget components
To create a widget, you need the following basic components:
AppWidgetProviderInfo
object- Describes the metadata for a widget, such as the widget's layout,
update frequency, and the
AppWidgetProvider
class. Defined in the XML on this page. AppWidgetProvider
class- Defines the basic methods that allow you to programmatically interface with
the widget. Through it, you will receive broadcasts when the widget is
updated, enabled, disabled, or deleted.
AppWidgetProvider
is declared in the manifest and then implemented, as described on this page. - View layout
- Defines the initial layout for the widget. Defined in XML, as described on this page.

In addition to the required basic components, if your widget needs user configuration you should implement the App Widget configuration activity. This activity allows users to modify widget settings (for example, the time zone for a clock widget).
- Starting in Android 12 (API level 31), you can choose to provide a default configuration and allow users to reconfigure the widget later. See Use the widget's default configuration and Enable users to reconfigure placed widgets for more details.
- In Android 11 (API level 30) or lower, this activity is launched every time the user adds the widget to their home screen.
Other optional but recommended improvements include flexible widget layouts, miscellaneous enhancements, advanced widgets, collection widgets, and building a widget host.
Declare the AppWidgetProviderInfo
XML
The AppWidgetProviderInfo
defines the essential qualities of a widget. Define
the AppWidgetProviderInfo
object in an XML resource file using a single
<appwidget-provider>
element and save it in the project's res/xml/
folder.
For example:
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:minWidth="40dp"
android:minHeight="40dp"
android:targetCellWidth="1"
android:targetCellHeight="1"
android:maxResizeWidth="250dp"
android:maxResizeHeight="120dp"
android:updatePeriodMillis="86400000"
android:description="@string/example_appwidget_description"
android:previewLayout="@layout/example_appwidget_preview"
android:initialLayout="@layout/example_loading_appwidget"
android:configure="com.example.android.ExampleAppWidgetConfigurationActivity"
android:resizeMode="horizontal|vertical"
android:widgetCategory="home_screen"
android:widgetFeatures="reconfigurable|configuration_optional">
</appwidget-provider>
Widget sizing attributes
The default home screen positions widgets in its window based on a grid of cells that have a defined height and width. Moreover, most home screens only allow widgets to take on sizes that are integer multiples of the grid cells (for example, 2 cells horizontally x 3 cells vertically).
The widget sizing attributes allow you to both specify a default size for your widget and provide lower and upper bounds on the size of the widget. In this context, the default size of a widget is the size that the widget will take on when it is first added to the home screen.
The following table describes the <appwidget-provider>
attributes pertaining
to widget sizing.
Attributes and description | |
---|---|
targetCellWidth and targetCellHeight (Android 12), minWidth and minHeight |
targetCellWidth /targetCellHeight and minWidth /minHeight sets of attributes, so that your app can fall back to using minWidth and minHeight if the user's device doesn’t support targetCellWidth and targetCellHeight . If supported, the targetCellWidth and targetCellHeight attributes take precedence over the minWidth and minHeight attributes.
|
minResizeWidth and minResizeHeight |
Specifies the widget's absolute minimum size. These values should specify the size under which the widget would be illegible or otherwise unusable. Using these attributes allows the user to resize the widget to a size that may be smaller than the default widget size. The minResizeWidth attribute is ignored if it is greater than minWidth or if horizontal resizing isn't enabled (see resizeMode ). Likewise, the minResizeHeight attribute is ignored if it is greater than minHeight or if vertical resizing isn't enabled. Introduced in Android 4.0. |
maxResizeWidth and maxResizeHeight |
Specifies the widget's recommended maximum size. If the values aren’t a multiple of the grid cell dimensions, they are rounded up to the nearest cell size. The maxResizeWidth attribute is ignored if it is smaller than minWidth or if horizontal resizing isn't enabled (see resizeMode ). Likewise, the maxResizeHeight attribute is ignored if it is greater than minHeight or if vertical resizing isn't enabled. Introduced in Android 12. |
resizeMode |
Specifies the rules by which a widget can be resized. You can use this attribute to make homescreen widgets resizeable—horizontally, vertically, or on both axes. Users long-press a widget to show its resize handles, then drag the horizontal and/or vertical handles to change its size on the layout grid. Values for the resizeMode attribute include horizontal , vertical , and none . To declare a widget as resizeable horizontally and vertically, use horizontal|vertical . Introduced in Android 3.1. |
Example
To illustrate how the attributes in the preceding table affect widget sizing, assume the following specifications:
- A grid cell is 30dp wide and 50dp tall.
- The following attribute specification is provided.
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:minWidth="80dp"
android:minHeight="80dp"
android:targetCellWidth="2"
android:targetCellHeight="2"
android:minResizeWidth="40dp"
android:minResizeHeight="40dp"
android:maxResizeWidth="120dp"
android:maxResizeHeight="120dp"
android:resizeMode="horizontal|vertical" />
Starting with Android 12:
We will use the targetCellWidth
and targetCellHeight
attributes as the default size of the widget.
The widget’s size will be 2x2 by default. The widget can be resized down to 2x1 or resized up to 4x3.
Android 11 and lower:
We will use the minWidth
and minHeight
attributes to compute the default
size of the widget.
The default width = Math.ceil(80 / 30)
= 3
The default height = Math.ceil(80 / 50)
= 2
The widget’s size will be 3x2 by default. The widget can be resized down to 2x1 or resized up to take up the full screen.
Additional widget attributes
The following table describes the <appwidget-provider>
attributes pertaining
to qualities other than widget sizing.
Attributes and description | |
---|---|
updatePeriodMillis |
Defines how often the widget framework should request an update from the AppWidgetProvider by calling the onUpdate() callback method. The actual update is not guaranteed to occur exactly on time with this value and we suggest updating as infrequently as possible—perhaps no more than once an hour to conserve the battery. For the full list of considerations to pick an appropriate update period, see Optimizations for updating widget content. |
initialLayout |
Points to the layout resource that defines the widget layout. |
configure |
Defines the activity that launches when the user adds the widget, allowing them to configure widget properties. See Enable users to configure widgets. (Starting in Android 12, your app can skip the initial configuration. See Use the widget's default configuration for details.) |
description |
Specifies the description for the widget picker to display for your widget. Introduced in Android 12. |
previewLayout (Android 12) and previewImage (Android 11 and lower) |
previewImage and previewLayout attributes, so that your app can fall back to using previewImage if the user's device doesn’t support previewLayout . For more details, see Backward-compatibility with scalable widget previews.
|
autoAdvanceViewId |
Specifies the view ID of the widget subview that should be auto-advanced by the widget's host. Introduced in Android 3.0. |
widgetCategory |
Declares whether your widget can be displayed on the home screen (home_screen ), the lock screen (keyguard ), or both. Only Android versions lower than 5.0 support lock-screen widgets. For Android 5.0 and higher, only home_screen is valid.
|
widgetFeatures |
Declares features supported by the widget. For example, if you’d like your widget to use its default configuration when a user adds it, specify both the configuration_optional and reconfigurable flags. This bypasses launching the configuration activity after a user adds the widget. (The user can still reconfigure the widget afterwards.) |
Use the AppWidgetProvider
class to handle widget broadcasts
The AppWidgetProvider
class handles widget broadcasts and updates the
widget in response to widget lifecycle events. The following sections describe
how to declare AppWidgetProvider
in the manifest and then implement it.
Declare a widget in the manifest
First, declare the AppWidgetProvider
class in your application's
AndroidManifest.xml
file. For example:
<receiver android:name="ExampleAppWidgetProvider"
android:exported="false">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data android:name="android.appwidget.provider"
android:resource="@xml/example_appwidget_info" />
</receiver>
The <receiver>
element requires the android:name
attribute, which
specifies the AppWidgetProvider
used by the widget. The component should not
be exported unless a separate process needs to broadcast to your
AppWidgetProvider
, which is usually not the case.
The <intent-filter>
element must include an <action>
element with
the android:name
attribute. This attribute specifies that the
AppWidgetProvider
accepts the ACTION_APPWIDGET_UPDATE
broadcast. This is the only broadcast that you must explicitly declare. The
AppWidgetManager
automatically sends all other widget broadcasts to the AppWidgetProvider
as
necessary.
The <meta-data>
element specifies the AppWidgetProviderInfo
resource and
requires the following attributes:
android:name
: Specifies the metadata name. Useandroid.appwidget.provider
to identify the data as theAppWidgetProviderInfo
descriptor.android:resource
: Specifies theAppWidgetProviderInfo
resource location.
Implement the AppWidgetProvider
class
The AppWidgetProvider
class extends
BroadcastReceiver
as a
convenience class to handle widget broadcasts. It receives only the event
broadcasts that are relevant to the widget, such as when the widget is updated,
deleted, enabled, and disabled. When these broadcast events occur, the following
AppWidgetProvider
methods are called:
onUpdate()
- This is called to update the widget at intervals defined by the
updatePeriodMillis
attribute in the AppWidgetProviderInfo. (See the table describing additional widget attributes in this document). - This method is also called when the user adds the widget, so it should perform
the essential setup, such as define event handlers for
View
objects or start a job to load data to be displayed in the widget. However, if you have declared a configuration activity without theconfiguration_optional
flag, this method is not called when the user adds the widget, but is called for the subsequent updates. It is the responsibility of the configuration activity to perform the first update when configuration is complete. (See Creating a widget configuration activity.) - The most important callback is
onUpdate()
. See Handle events with theonUpdate()
class on this page for more information. onAppWidgetOptionsChanged()
This is called when the widget is first placed and any time the widget is resized. Use this callback to show or hide content based on the widget's size ranges. Get the size ranges—and, starting in Android 12, the list of possible sizes a widget instance can take—by calling
getAppWidgetOptions()
, which returns aBundle
that includes the following:OPTION_APPWIDGET_MIN_WIDTH
: Contains the lower bound on the width, in dp units, of a widget instance.OPTION_APPWIDGET_MIN_HEIGHT
: Contains the lower bound on the height, in dp units, of a widget instance.OPTION_APPWIDGET_MAX_WIDTH
: Contains the upper bound on the width, in dp units, of a widget instance.OPTION_APPWIDGET_MAX_HEIGHT
: Contains the upper bound on the height, in dp units, of a widget instance.OPTION_APPWIDGET_SIZES
: Contains the list of possible sizes (List<SizeF>
), in dp units, a widget instance can take. Introduced in Android 12.
onDeleted(Context, int[])
This is called every time a widget is deleted from the widget host.
onEnabled(Context)
This is called when an instance the widget is created for the first time. For example, if the user adds two instances of your widget, this is only called the first time. If you need to open a new database or perform another setup that only needs to occur once for all widget instances, then this is a good place to do it.
onDisabled(Context)
This is called when the last instance of your widget is deleted from the widget host. This is where you should clean up any work done in
onEnabled(Context)
, such as delete a temporary database.onReceive(Context, Intent)
This is called for every broadcast and before each of the preceding callback methods. You normally don't need to implement this method because the default
AppWidgetProvider
implementation filters all widget broadcasts and calls the preceding methods as appropriate.
You must declare your AppWidgetProvider
class implementation as a broadcast
receiver using the <receiver>
element in the AndroidManifest
. See
Declare a widget in the manifest on this page.
Handle events with the onUpdate()
class
The most important AppWidgetProvider
callback is onUpdate()
because it is
called when each widget is added to a host (unless you use a configuration
activity without the configuration_optional
flag). If your widget accepts any
user interaction events, then you need to register the event handlers in this
callback. If your widget doesn't create temporary files or databases, or perform
other work that requires clean-up, then onUpdate()
may be the only callback
method you need to define. For example, if you want a widget with a button that
launches an activity when clicked, you could use the following implementation of
AppWidgetProvider
:
Kotlin
class ExampleAppWidgetProvider : AppWidgetProvider() { override fun onUpdate( context: Context, appWidgetManager: AppWidgetManager, appWidgetIds: IntArray ) { // Perform this loop procedure for each widget that belongs to this // provider. appWidgetIds.forEach { appWidgetId -> // Create an Intent to launch ExampleActivity. val pendingIntent: PendingIntent = PendingIntent.getActivity( /* context = */ context, /* requestCode = */ 0, /* intent = */ Intent(context, ExampleActivity::class.java), /* flags = */ PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE ) // Get the layout for the widget and attach an on-click listener // to the button. val views: RemoteViews = RemoteViews( context.packageName, R.layout.appwidget_provider_layout ).apply { setOnClickPendingIntent(R.id.button, pendingIntent) } // Tell the AppWidgetManager to perform an update on the current // widget. appWidgetManager.updateAppWidget(appWidgetId, views) } } }
Java
public class ExampleAppWidgetProvider extends AppWidgetProvider { public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { // Perform this loop procedure for each widget that belongs to this // provider. for (int i=0; i < appWidgetIds.length; i++) { int appWidgetId = appWidgetIds[i]; // Create an Intent to launch ExampleActivity Intent intent = new Intent(context, ExampleActivity.class); PendingIntent pendingIntent = PendingIntent.getActivity( /* context = */ context, /* requestCode = */ 0, /* intent = */ intent, /* flags = */ PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE ); // Get the layout for the widget and attach an on-click listener // to the button. RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.example_appwidget_layout); views.setOnClickPendingIntent(R.id.button, pendingIntent); // Tell the AppWidgetManager to perform an update on the current app widget. appWidgetManager.updateAppWidget(appWidgetId, views); } } }
This AppWidgetProvider
defines only the onUpdate()
method for the purpose of
creating a PendingIntent
that launches
an Activity
and attaching it to the
widget's button with setOnClickPendingIntent(int,
PendingIntent)
. Notice that it includes a loop that iterates
through each entry in appWidgetIds
, which is an array of IDs that identify
each widget created by this provider. In this way, if the user creates more than
one instance of the widget, then they are all updated simultaneously. However,
only one updatePeriodMillis
schedule will be managed
for all instances of the widget. For example, if the update schedule is defined
to be every two hours, and a second instance of the widget is added one hour
after the first one, then they will both be updated on the period defined by the
first one and the second update period will be ignored (they'll both be updated
every two hours, not every hour).
Also see the ExampleAppWidgetProvider.java
sample class.
Receive widget broadcast Intents
AppWidgetProvider
is just a
convenience class. If you would like to receive the widget broadcasts
directly, you can implement your own
BroadcastReceiver
or override
the onReceive(Context,Intent)
callback. The Intents you need to care about are as follows:
ACTION_APPWIDGET_UPDATE
ACTION_APPWIDGET_DELETED
ACTION_APPWIDGET_ENABLED
ACTION_APPWIDGET_DISABLED
ACTION_APPWIDGET_OPTIONS_CHANGED
Create the widget layout
You must define an initial layout for your widget in XML and save it in the
project's res/layout/
directory. Refer to
Design guidelines for details.
Creating the widget layout is simple if you're familiar with
layouts. However, be aware that widget
layouts are based on RemoteViews
,
which do not support every kind of layout or view widget. You cannot use custom
views or subclasses of the views that are supported by RemoteViews
.
RemoteViews
also supports ViewStub
,
which is an invisible, zero-sized View
you can use to lazily inflate layout
resources at runtime.
Support for stateful behavior
Android 12 adds new support for stateful behavior using the following existing components:
The widget is still stateless. Your app must store the state and register for state change events.

The following code example shows how to implement these components.
Kotlin
// Check the view. remoteView.setCompoundButtonChecked(R.id.my_checkbox, true) // Check a radio group. remoteView.setRadioGroupChecked(R.id.my_radio_group, R.id.radio_button_2) // Listen for check changes. The intent will have an extra with the key // EXTRA_CHECKED that specifies the current checked state of the view. remoteView.setOnCheckedChangeResponse( R.id.my_checkbox, RemoteViews.RemoteResponse.fromPendingIntent(onCheckedChangePendingIntent) )
Java
// Check the view. remoteView.setCompoundButtonChecked(R.id.my_checkbox, true); // Check a radio group. remoteView.setRadioGroupChecked(R.id.my_radio_group, R.id.radio_button_2); // Listen for check changes. The intent will have an extra with the key // EXTRA_CHECKED that specifies the current checked state of the view. remoteView.setOnCheckedChangeResponse( R.id.my_checkbox, RemoteViews.RemoteResponse.fromPendingIntent(onCheckedChangePendingIntent));
Provide two different layouts, with one targeting devices running
Android 12 or higher (res/layout-v31
) and the other targeting
previous Android 11 or lower (in the default res/layout
folder).
Implement rounded corners
Android 12 introduces the following system parameters to set the radii of your widget's rounded corners:
system_app_widget_background_radius
: The corner radius of the widget background, which will never be larger than 28dp.system_app_widget_inner_radius
: The corner radius of any view inside the widget. This is exactly 8dp less than the background radius to align nicely when using an 8dp padding.
The following example shows a widget that uses
system_app_widget_background_radius
for the corner of the widget and
system_app_widget_inner_radius
for views inside the widget.

1 Corner of the widget.
2 Corner of a view inside the widget.
Important considerations for rounded corners
- Third-party launchers and device manufacturers can override the
system_app_widget_background_radius
parameter to be smaller than 28dp. Thesystem_app_widget_inner_radius
parameter will always be 8dp less than the value ofsystem_app_widget_background_radius
. - If your widget doesn’t use
@android:id/background
or define a background that clips its content based on the outline (withandroid:clipToOutline
set totrue
), the launcher tries to automatically identify the background and clip the widget using a rectangle with rounded corners of up to 16dp. See Ensure your widget is compatible with Android 12).
To ensure widget compatibility with previous versions of Android, we recommend defining custom attributes and using a custom theme to override them for Android 12, as shown in the following examples of XML files:
/values/attrs.xml
<resources>
<attr name="backgroundRadius" format="dimension" />
</resources>
/values/styles.xml
<resources>
<style name="MyWidgetTheme">
<item name="backgroundRadius">@dimen/my_background_radius_dimen</item>
</style>
</resources>
/values-31/styles.xml
<resources>
<style name="MyWidgetTheme" parent="@android:style/Theme.DeviceDefault.DayNight">
<item name="backgroundRadius">@android:dimen/system_app_widget_background_radius</item>
</style>
</resources>
/drawable/my_widget_background.xml
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:radius="?attr/backgroundRadius" />
...
</shape>
/layout/my_widget_layout.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
...
android:background="@drawable/my_widget_background" />