The Android home screen available on most Android devices allows the user to
embed app widgets (or widgets) for quick
access to content. If you're building a home screen replacement or a similar
app, you can also allow the user to embed widgets by implementing
AppWidgetHost
. This is not
something that most apps will ever need to do, but if you are creating your own
host, it's important to understand the contractual obligations a host implicitly
agrees to.
This document focuses on the responsibilities involved in implementing a custom
AppWidgetHost
. For a specific example of how to implement an AppWidgetHost
,
look at the source code for the Android home screen LauncherAppWidgetHost
.
Here is an overview of key classes and concepts involved in implementing a custom
AppWidgetHost
:
App widget host: The
AppWidgetHost
provides the interaction with the AppWidget service for apps that want to embed app widgets in their UI. AnAppWidgetHost
must have an ID that is unique within the host's own package. This ID remains persistent across all uses of the host. The ID is typically a hard-coded value that you assign in your application.App widget ID: Each widget instance is assigned a unique ID at the time of binding (see
bindAppWidgetIdIfAllowed()
, covered in more detail in Binding widgets on this page. The unique ID is obtained by the host usingallocateAppWidgetId()
. This ID is persistent across the lifetime of the widget, that is, until it is deleted from the host. Any host-specific state (such as the size and location of the widget) should be persisted by the hosting package and associated with the app widget ID.App widget host view: Think of
AppWidgetHostView
as a frame that the widget is wrapped in whenever it needs to be displayed. A widget is associated with anAppWidgetHostView
every time the widget is inflated by the host. Note the following points:- By default, the system will create an
AppWidgetHostView
, but the host can create its own subclass ofAppWidgetHostView
by extending it. - Starting in Android 12 (API level 31),
AppWidgetHostView
introduces the thesetColorResources()
andresetColorResources()
methods for handling dynamically overloaded colors. The host is responsible for providing the colors to these methods.
- By default, the system will create an
Options bundle: The
AppWidgetHost
uses the options bundle to communicate information to theAppWidgetProvider
about how the widget is being displayed (for example, the list of size ranges, and whether the widget is on a lockscreen or the home screen). This information allows theAppWidgetProvider
to tailor the widget's contents and appearance based on how and where it is displayed. You can useupdateAppWidgetOptions()
andupdateAppWidgetSize()
to modify a widget's bundle. Both of these methods trigger theonAppWidgetOptionsChanged()
callback to theAppWidgetProvider
.
Binding widgets
When a user adds a widget to a host, a process called binding occurs.
Binding refers to associating a particular app widget ID with both a specific
host and a specific AppWidgetProvider
.
Binding APIs also make it possible for a host to provide a custom UI for
binding. To use this process, your app must declare the
BIND_APPWIDGET
permission in the host's manifest:
<uses-permission android:name="android.permission.BIND_APPWIDGET" />
But this is just the first step. At runtime, the user must explicitly grant
permission to your app to allow it to add a widget to the host. To test whether
your app has permission to add the widget, use the
bindAppWidgetIdIfAllowed()
method. If bindAppWidgetIdIfAllowed()
returns false
, your app must display a
dialog prompting the user to grant permission ("allow" for the current widget
addition, or "always allow" to cover all future widget additions).
This snippet gives an example of how to display the dialog:
Kotlin
val intent = Intent(AppWidgetManager.ACTION_APPWIDGET_BIND).apply { putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId) putExtra(AppWidgetManager.EXTRA_APPWIDGET_PROVIDER, info.componentName) // This is the options bundle described in the preceding section. putExtra(AppWidgetManager.EXTRA_APPWIDGET_OPTIONS, options) } startActivityForResult(intent, REQUEST_BIND_APPWIDGET)
Java
Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_BIND); intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId); intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_PROVIDER, info.componentName); // This is the options bundle described in the preceding section. intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_OPTIONS, options); startActivityForResult(intent, REQUEST_BIND_APPWIDGET);
The host also has to check whether the widget that a user added needs configuration. For more information, see Enable users to configure widgets.
Host responsibilities
You can specify a number of configuration settings for widgets using the AppWidgetProviderInfo
metadata. These configuration options,
covered in more detail in the following sections, can be retrieved by the host
from the AppWidgetProviderInfo
object associated with a widget provider.
Regardless of the version of Android you are targeting, all hosts have the following responsibilities:
When adding a widget, you must allocate the widget ID as described above. You must also make sure that when a widget is removed from the host, you call
deleteAppWidgetId()
to deallocate the widget ID.When adding a widget, be sure to check if the configuration activity needs to be launched. Typically, the host needs to launch the widget's configuration activity if it exists and is not marked as optional by specifying both the
configuration_optional
andreconfigurable
flags. See Update the widget from the configuration activity for details. This is a necessary step for many widgets before they can be properly displayed.Widgets specify a default width and height in the
AppWidgetProviderInfo
metadata. These values are defined in cells (starting in Android 12, iftargetCellWidth
andtargetCellHeight
are specified) or dps (if onlyminWidth
andminHeight
are specified). See Widget sizing attributes.Make sure that the widget is laid out with at least this many dps. For example, many hosts align icons and widgets in a grid. In this scenario, by default the host should add the a widget using the minimum number of cells that satisfy the
minWidth
andminHeight
constraints.
In addition to the requirements listed in the preceding section, specific platform versions introduce features that place new responsibilities on the host.
Determine your approach based on the targeted Android version
The approach you use in implementing your host should depend on what Android version you're targeting. Many of the features described in this section were introduced in 3.0 or later. For example:
- Android 3.0 (API Level 11) introduces auto-advance behavior for widgets.
- Android 3.1 (API Level 12) introduces the ability to resize widgets.
- Android 4.0 (API Level 15) introduces a change in padding policy that puts the responsibility on the host to manage padding.
- Android 4.1 (API Level 16) adds an API that allows the widget provider to get more detailed information about the environment in which its widget instances are being hosted.
- Android 4.2 (API Level 17) introduces the options bundle and the
bindAppWidgetIdIfAllowed()
method. It also introduces lockscreen widgets.
If you are targeting earlier devices, refer to the original Launcher as an example.
The following sections provide additional detail about features that place new responsibilities on the host.
Android 3.0
Android 3.0 (API Level 11) introduces the ability for a widget to specify autoAdvanceViewId()
.
This view ID should point to an instance of an
Advanceable
, such as StackView
or AdapterViewFlipper
. This indicates that the host
should call advance()
on this
view at an interval deemed appropriate by the host (taking into account whether
it makes sense to advance the widget—for example, the host probably
wouldn't want to advance a widget if it were on another page, or
if the screen were turned off).
Android 3.1
Android 3.1 (API Level 12) introduces the ability to resize widgets. A widget
can specify that it is resizable using the
android:resizeMode
attribute in the AppWidgetProviderInfo
metadata, and indicate whether it
supports horizontal and/or vertical resizing. Introduced in Android 4.0 (API
Level 14), the widget can also specify a
android:minResizeWidth
and/or
android:minResizeHeight
.
It is the host’s responsibility to make it possible for the
widget to be resized horizontally and/or vertically, as specified
by the widget. A widget that specifies that it is resizable can be
resized arbitrarily large, but should not be resized smaller than
the values specified by android:minResizeWidth
and android:minResizeHeight
.
For a sample implementation, see AppWidgetResizeFrame
in Launcher2
.
Android 4.0
Android 4.0 (API Level 15) introduces a change in padding policy that
puts the responsibility on the host to manage padding. As of 4.0, app
widgets no longer include their own padding. Instead, the system adds
padding for each widget, based the characteristics of the current screen.
This leads to a more uniform, consistent presentation of widgets in a grid.
To assist applications that host widgets, the platform provides
the method
getDefaultPaddingForWidget()
.
Applications can call this method to get the system-defined padding
and account for it when computing the number of cells to allocate to the widget.
Android 4.1
Android 4.1 (API Level 16) adds an API that allows the widget provider to get more detailed information about the environment in which its widget instances are being hosted. Specifically, the host hints to the widget provider about the size at which the widget is being displayed. It is the host’s responsibility to provide this size information.
The host provides this information via
updateAppWidgetSize()
.
The size is specified as a minimum and maximum width/height in dps.
The reason that a range is specified (as opposed to a fixed size)
is because the width and height of a widget may change with orientation.
You don’t want the host to have to update all of its widgets on rotation,
as this could cause serious system slowdown. These values should be
updated once upon the widget being placed, any time the widget is resized,
and any time the launcher inflates the widget for the first time in a
given boot (as the values aren’t persisted across boot).
Android 4.2
Android 4.2 (API Level 17) adds the ability for the options bundle
to be specified at bind time. This is the ideal way to specify app
widget options, including size, as it gives the AppWidgetProvider
immediate access to the options data on the first update. This can be achieved by using the method bindAppWidgetIdIfAllowed()
. For more discussion of this topic,
see Binding widgets.
Android 4.2 also introduces lockscreen widgets. When hosting widgets
on the lockscreen, the host must specify this information within the app
widget options bundle (the AppWidgetProvider
can use this information to style
the widget appropriately). To designate a widget as a lockscreen widget, use updateAppWidgetOptions()
and include the field
OPTION_APPWIDGET_HOST_CATEGORY
with the value WIDGET_CATEGORY_KEYGUARD
.
This option defaults to
WIDGET_CATEGORY_HOME_SCREEN
,
so it is not explicitly required to set this for a home screen host.
Make sure that your host adds only widgets that are appropriate
for your app—for example, if your host is a home screen, ensure
that the
android:widgetCategory
attribute in the
AppWidgetProviderInfo
metadata includes
the flag WIDGET_CATEGORY_HOME_SCREEN
.
Similarly, for the lockscreen, ensure that field includes the flag WIDGET_CATEGORY_KEYGUARD
. For more
discussion of this topic, see
Enabling App Widgets on the Lockscreen.
Android 12
Android 12 (API level 31) bundles an extra List<SizeF>
that contains the list
of possible sizes (in dps) a widget instance can take in the options bundle.
The number of sizes provided depends on the host implementation.
Hosts should typically provide two sizes for phones (portrait and landscape) and
four sizes for foldables.
There is a limit of MAX_INIT_VIEW_COUNT
(16) on the number of different
RemoteViews
that an AppWidgetProvider
can provide to RemoteViews
. Since AppWidgetProvider
s will map a RemoteViews
object to each size in the List<SizeF>
, try not to provide more than MAX_INIT_VIEW_COUNT
sizes.
Android 12 also introduces the
maxResizeWidth
and
maxResizeHeight
attributes in dps. We recommend that a widget that uses at least one of these
attributes does not exceed the size specified by the attributes.