在大多数 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
参考文档。