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