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