Build a widget host

The Android home screen, available on most Android-powered devices, lets the user 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 let the user embed widgets by implementing AppWidgetHost. This isn't something that most apps 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 page 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 embed widgets in their UI. An AppWidgetHost must have an ID that is unique within the host's own package. This ID persists across all uses of the host. The ID is typically a hardcoded value that you assign in your app.

  • App widget ID: each widget instance is assigned a unique ID at the time of binding. See bindAppWidgetIdIfAllowed() and, for more detail, the Binding widgets section that follows. The host obtains the unique ID using allocateAppWidgetId(). This ID persists across the lifetime of the widget until it is deleted from the host. Any host-specific state—such as the size and location of the widget—must 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 an AppWidgetHostView every time the widget is inflated by the host.

    • By default, the system creates an AppWidgetHostView, but the host can create its own subclass of AppWidgetHostView by extending it.
    • Starting in Android 12 (API level 31), AppWidgetHostView introduces the the setColorResources() and resetColorResources() methods for handling dynamically overloaded colors. The host is responsible for providing the colors to these methods.
  • Options bundle: the AppWidgetHost uses the options bundle to communicate information to the AppWidgetProvider about how the widget is displayed—for example, the list of size ranges—and whether the widget is on a lockscreen or the home screen. This information lets the AppWidgetProvider tailor the widget's contents and appearance based on how and where it is displayed. You can use updateAppWidgetOptions() and updateAppWidgetSize() to modify a widget's bundle. Both of these methods trigger the onAppWidgetOptionsChanged() callback to the AppWidgetProvider.

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 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 let it 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 must check whether the widget that a user adds needs configuration. For more information, see Enable users to configure app widgets.

Host responsibilities

You can specify a number of configuration settings for widgets using the AppWidgetProviderInfo metadata. You can retrieve these configuration options, covered in more detail in the following sections, 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, allocate the widget ID as described earlier. When a widget is removed from the host, call deleteAppWidgetId() to deallocate the widget ID.

  • When adding a widget, check whether the configuration activity needs to be launched. Typically, the host needs to launch the widget's configuration activity if it exists and isn't marked as optional by specifying both the configuration_optional and reconfigurable flags. See Update the widget from the configuration activity for details. This is a necessary step for many widgets before they can display.

  • Widgets specify a default width and height in the AppWidgetProviderInfo metadata. These values are defined in cells—starting in Android 12, if targetCellWidth and targetCellHeight are specified—or dps if only minWidth and minHeight 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 adds the a widget using the minimum number of cells that satisfy the minWidth and minHeight 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

Android 12

Android 12 (API level 31) bundles an extra List<SizeF> that contains the list of possible sizes in dps that a widget instance can take in the options bundle. The number of sizes provided depends on the host implementation. Hosts 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 objects map a RemoteViews object to each size in the List<SizeF>, don't 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 doesn't exceed the size specified by the attributes.

Additional resources

  • See the Glance reference documentation.