大多数 Android 设备上的 Android 主屏幕都可让用户嵌入应用 widget(或 widget),以便快速访问内容。如果您要构建主屏幕替换项或类似应用,还可以通过实现 AppWidgetHost
来允许用户嵌入 widget。大多数应用并非需要这样做,但如果您要创建自己的托管应用,请务必了解托管应用默许的合同义务。
本页面重点介绍实现自定义 AppWidgetHost
所涉及的责任。如需查看有关如何实现 AppWidgetHost
的具体示例,请查看 Android 主屏幕 LauncherAppWidgetHost
的源代码。
下面简要介绍了实现自定义 AppWidgetHost
所涉及的关键类和概念:
应用 widget 托管应用:
AppWidgetHost
可为在界面中嵌入 widget 的应用提供与 AppWidget 服务的交互。AppWidgetHost
必须具有在主机自己的软件包中唯一的 ID。此 ID 在主机的所有使用中保持不变。此 ID 通常是您在应用中指定的硬编码值。应用微件 ID:每个微件实例在绑定时都分配有一个唯一 ID。请参阅
bindAppWidgetIdIfAllowed()
;如需了解详情,请参阅后面的绑定 widget 部分。主机使用allocateAppWidgetId()
获取唯一 ID。此 ID 会在 widget 的整个生命周期内持续有效,直到从宿主中删除为止。任何特定于主机的状态(例如 widget 的大小和位置)都必须由托管软件包保留并与应用 widget ID 相关联。应用 widget 托管视图:将
AppWidgetHostView
视为一个框架,每当需要显示 widget 时,都会将其封装到该框架中。每当 widget 由主机膨胀时,它都会与AppWidgetHostView
相关联。- 默认情况下,系统会创建一个
AppWidgetHostView
,但主机可以通过扩展它来创建自己的AppWidgetHostView
子类。 - 从 Android 12(API 级别 31)开始,
AppWidgetHostView
引入了setColorResources()
和resetColorResources()
方法,用于处理动态过载的颜色。主机负责为这些方法提供颜色。
- 默认情况下,系统会创建一个
选项包:
AppWidgetHost
使用选项包向AppWidgetProvider
传达有关如何显示 widget 的信息(例如,大小范围列表),以及 widget 是在锁定屏幕上还是在主屏幕上。此信息可让AppWidgetProvider
根据 widget 的显示方式和显示位置来定制其内容和外观。您可以使用updateAppWidgetOptions()
和updateAppWidgetSize()
修改 widget 的 bundle。这两种方法都会触发对AppWidgetProvider
的onAppWidgetOptionsChanged()
回调。
绑定 widget
当用户向托管应用添加 widget 时,会发生一个称为“绑定”的过程。绑定是指将特定应用 widget ID 与特定宿主和特定 AppWidgetProvider
相关联。
绑定 API 还使主机能够提供用于绑定的自定义界面。如需使用此过程,您的应用必须在主机的清单中声明 BIND_APPWIDGET
权限:
<uses-permission android:name="android.permission.BIND_APPWIDGET" />
但是,这只是第一步。在运行时,用户必须向您的应用明确授予权限,以允许它将 widget 添加到托管应用。如需测试您的应用是否有权添加该 widget,请使用 bindAppWidgetIdIfAllowed()
方法。如果 bindAppWidgetIdIfAllowed()
返回 false
,您的应用必须显示一个对话框来提示用户授予权限:“允许”表示添加当前 widget 的权限,或者“始终允许”表示今后添加所有 widget 的权限。
以下代码段举例说明了如何显示该对话框:
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);
托管应用必须检查用户添加的 widget 是否需要配置。如需了解详情,请参阅允许用户配置应用 widget。
托管方责任
您可以使用 AppWidgetProviderInfo
元数据为 widget 指定多项配置设置。您可以从与 widget 提供程序关联的 AppWidgetProviderInfo
对象中检索这些配置选项(下文对此进行了详细介绍)。
无论您的目标 Android 版本是哪个,所有托管应用都有以下责任:
添加微件时,请按上文所述分配微件 ID。从托管应用中移除微件后,调用
deleteAppWidgetId()
以取消分配微件 ID。添加 widget 时,检查是否需要启动配置 activity。通常,托管应用需要启动 widget 的配置 activity(如果存在),并且未通过同时指定
configuration_optional
和reconfigurable
标志标记为可选。如需了解详情,请参阅从配置 activity 更新 widget。对于许多微件来说,这是显示前必不可少的一步。widget 会在
AppWidgetProviderInfo
元数据中指定默认宽度和高度。从 Android 12 开始,如果指定了targetCellWidth
和targetCellHeight
,这些值都在单元格中定义;如果仅指定了minWidth
和minHeight
,则以 dp 为单位。请参阅微件大小调整属性。请确保 widget 的布局中至少包含这么多 dp。例如,许多托管应用会在网格中对齐图标和微件。在这种情况下,默认情况下,主机使用满足
minWidth
和minHeight
约束条件的最小单元数来添加 widget。
除了上一部分中列出的要求之外,特定平台版本引入的一些功能还要求托管应用承担新的责任。
根据目标 Android 版本确定方法
Android 12
Android 12(API 级别 31)捆绑了一个额外的 List<SizeF>
,其中包含微件实例在选项包中可以采用的可能大小的列表(以 dp 为单位)。所提供的尺寸数量取决于主机的实现情况。主机通常会为手机提供两种尺寸(竖屏和横屏),并为可折叠设备提供四种尺寸。
AppWidgetProvider
可以向 RemoteViews
提供的不同 RemoteViews
的数量上限为 MAX_INIT_VIEW_COUNT
(16)。由于 AppWidgetProvider
对象会将 RemoteViews
对象映射到 List<SizeF>
中的每个尺寸,因此提供的尺寸不要超过 MAX_INIT_VIEW_COUNT
。
Android 12 还引入了 maxResizeWidth
和 maxResizeHeight
属性(以 dp 为单位)。我们建议,使用其中至少一个属性的 widget 不要超过属性指定的大小。
其他资源
- 请参阅
Glance
参考文档。