管理快捷方式

创建快捷方式后,您可能需要在应用生命周期内对其进行管理。例如,您可能需要确定用户使用您的快捷方式完成特定操作的频率,以此来优化应用。在其他情况下,您可能会决定停用某个固定快捷方式,以防止应用执行过时或缺失的操作。对于对话中引用的快捷方式,您可能需要跟踪其使用情况,以提供有助于提高快捷方式排名的信号。

本页面将介绍这些方法以及其他几种管理快捷方式的常用方法。

快捷方式的行为

以下各个部分将介绍有关快捷方式行为的常规信息,包括可见性、显示顺序和排名。

快捷方式的可见性

当用户执行特定手势或语音指令时,静态快捷方式和动态快捷方式会显示在支持的启动器或助理中。在支持的启动器上,让快捷方式显示出来的手势是触摸并按住应用的启动器图标,但其他启动器应用上实际适用的手势可能有所不同。借助 Google 助理,您可以在 Google 助理中显示快捷方式,也可以通过用户语音指令启动快捷方式。

LauncherApps 类提供了多个供启动器应用访问 快捷方式的 API。

固定快捷方式显示在启动器中,因此它们始终可见。 只有在以下情况下,固定快捷方式才会从启动器中移除:

  • 用户将其移除。
  • 与该快捷方式关联的应用被卸载。
  • 用户通过依次前往设置 > 应用和通知 、选择应用,然后依次点按存储空间 > 清除存储空间 来清除应用的数据。

共享目标是动态快捷方式的一个子集,显示在 Android 共享表单的直接共享行中。

Android Sharesheet
图 1.Android Sharesheet。直接共享目标显示在第一行,然后是排名靠前的应用,最后是应用列表。

快捷方式的显示顺序

当启动器显示某个应用的快捷方式时,它们必须按以下顺序排列:

  1. 静态快捷方式:其 isDeclaredInManifest() 方法 返回 true 的快捷方式。
  2. 动态快捷方式:其 ShortcutInfo.isDynamic() 方法返回 true 的快捷方式。

在每类(静态和动态)快捷方式内,快捷方式按 排名升序排列,具体取决于ShortcutInfo.getRank。在确定向用户显示的上下文快捷方式时,Google 助理还会考虑快捷方式排名。

排名为连续的非负整数。静态快捷方式按其在 shortcuts.xml 文件中出现的顺序从前到后进行排名。对于动态 快捷方式,您可以在调用 updateShortcuts(Context, List)addDynamicShortcuts(Context, List)pushDynamicShortcut(Context, ShortcutInfoCompat)setDynamicShortcuts(Context, List)时更新现有快捷方式的排名。

共享目标的顺序取决于多种因素,包括过去的用户历史记录、新近度、频率、排名提示、应用使用情况以及与分享快捷键关联的对话中设置的优先级。使用 Sharing Shortcuts API 创建的共享目标 的优先级高于由 ChooserTargetService 生成的共享 目标,后者已在 Android 11 中被废弃。在 Android 12 及更高版本中,由已弃用的 ChooserTargetService 生成的共享目标将不再显示在共享表单中。

大多数启动器最多显示四个快捷方式。对于定义的静态快捷方式和动态快捷方式的任意组合,启动器最多显示两个静态快捷方式和两个动态快捷方式。例如,如果您定义了四个静态快捷方式,并以编程方式创建了三个动态快捷方式,则启动器会显示前两个静态快捷方式和排名最高的两个动态快捷方式。

管理多个 intent 和 Activity

如果您希望应用在用户启动某个快捷方式时执行多项操作,您可以将其配置为触发连续 Activity。为此,您可以分配多个 intent、从一个 Activity 启动另一个 Activity,或者设置 intent 标记,具体取决于快捷方式的类型。

从一个 Activity 启动另一个 Activity

静态快捷方式不能有自定义 intent 标记。静态 快捷方式的第一个 intent 始终设置有 Intent.FLAG_ACTIVITY_NEW_TASKIntent.FLAG_ACTIVITY_CLEAR_TASK。这意味着,当您的应用运行时,启动静态快捷方式时,应用中的所有现有 Activity 都会被销毁。如果您不希望出现这种行为,可以使用 Trampoline Activity(一种启动其他 Activity 的不可见 Activity),方法是在启动块或 onCreate 内(在设置 Compose 内容之前)调用 finish:

  1. AndroidManifest.xml file 中,在 Trampoline Activity 中添加属性分配 android:taskAffinity=""

  2. 在快捷方式资源文件中,在静态快捷方式内的 intent 中引用 Trampoline Activity。

如需详细了解 Trampoline Activity,请参阅 从一个 Activity 启动另一个 Activity

设置 intent 标记

您可以使用任意一组 Intent 标记。 最好在快捷方式的 intent 中指定 Intent.FLAG_ACTIVITY_SINGLE_TOPIntent.FLAG_ACTIVITY_CLEAR_TOP 的组合。这样可确保,如果您的 ComponentActivity 已处于活动状态,则会将其置于前台并重复使用,而不会将其销毁,从而让您的单 Activity 架构能够通过 onNewIntent() 妥善处理快捷方式事件。

如需详细了解任务和 intent 标记,请参阅任务和返回堆栈

更新快捷方式

每个应用的启动器图标最多只能包含数量等于getMaxShortcutCountPerActivity返回值的静态和动态 快捷方式。应用可以创建的固定快捷方式数量没有限制。

在动态快捷方式固定好以后,即使发布商将其作为动态快捷方式移除,该固定快捷方式仍然可见且可启动。这样,应用拥有的快捷方式可以超过 getMaxShortcutCountPerActivity 个。

请考虑以下示例,该示例假定 getMaxShortcutCountPerActivity 返回的值为 4

  1. 聊天应用发布了四个动态快捷方式,分别表示 4 个最近的会话:c1、c2、c3 和 c4。
  2. 用户固定了所有这四个快捷方式。
  3. 之后,用户启动了另外三个会话:c5、c6 和 c7。发布商应用重新发布了动态快捷方式。新的动态快捷方式列表为:c4、c5、c6 和 c7。

应用必须移除 c1、c2 和 c3,因为它不能显示四个以上的动态快捷方式。不过,c1、c2 和 c3 仍然是用户可以访问和启动的固定快捷方式。

用户现在总共可以访问七个快捷方式,它们都链接到发布商应用中的 Activity。这是因为总数中包含达到数量上限的快捷方式和 3 个固定快捷方式。

  1. 应用可使用 updateShortcuts(Context, List) 来更新现有七个快捷方式中的任何一个。例如,您可以在聊天对象的图标发生更改时更新这组快捷方式。
  2. 您可以使用 addDynamicShortcuts(Context, List)setDynamicShortcuts(Context, List) 方法来更新具有相同 ID 的现有快捷方式。不过,它们无法用于更新非动态的固定快捷方式,因为这两种方法都会尝试将指定的快捷方式列表转换为动态快捷方式。

对可以推送到助理应用(例如 Google 助理)中进行显示的快捷方式数量没有限制。使用 ShortcutManagerCompat Jetpack 库的 pushDynamicShortcut 方法创建和更新 助理应用的快捷方式。此外,还必须在应用中添加 Google 快捷方式集成 库,动态链接才能在 Google 助理上显示。

如需详细了解应用快捷方式准则(包括如何更新快捷方式), 请参阅快捷方式最佳实践

处理系统语言区域的变更

应用在收到 Intent.ACTION_LOCALE_CHANGED广播(表明系统 语言区域已更改)后,必须更新动态和固定快捷方式。

跟踪快捷方式的使用情况

为了确定静态和动态快捷方式应在哪些情况下出现,启动器将检查快捷方式的启动记录。对于静态快捷方式, 当发生以下任一事件时,可以通过 调用 reportShortcutUsed 方法并向其传递 快捷方式的 ID 来跟踪用户何时在应用中完成特定操作:

  • 用户选择具有指定 ID 的快捷方式。
  • 在应用内,用户手动完成与同一快捷方式对应的操作。

当发生相关事件时,您的应用通过调用 pushDynamicShortcut 方法并向其传递快捷方式的 ID 来跟踪动态快捷方式的使用情况。 通过此方法推送动态快捷方式使用情况,可以让助理应用(如 Google 助理)向用户推荐相关的快捷方式。由于 pushDynamicShortcut 方法会在被调用时报告使用情况,因此不应对同一快捷方式调用 reportShortcutUsed 方法。

对于与对话相关的快捷方式,跟踪发送和接收消息的使用情况非常重要。如需了解详情,请参阅人员和 对话的最佳实践

停用快捷方式

由于您的应用及其用户可以将快捷方式固定到设备的启动器上,因此这些固定快捷方式可能会引导用户执行应用中已过期或不存在的操作。为应对这种情况,您可以 调用 disableShortcuts来停用不希望用户选择的快捷方式;该方法会从静态 和动态快捷方式列表中移除指定的快捷方式,并停用这些快捷方式的固定副本。您 还可以使用此方法的过载版本,它会接受 CharSequence 作为自定义错误消息。然后,当用户尝试启动任何已停用的快捷方式时,系统会显示该错误消息。

速率限制

使用 setDynamicShortcuts, addDynamicShortcutsupdateShortcuts 方法时,您在后台应用(在前台没有任何 Activity 或服务的应用)中调用这些方法的次数可能有特定的上限。 您可以调用这些方法的特定次数上限称为“速率限制”。 此功能可防止 ShortcutManagerCompat 过度消耗设备资源。

启用速率限制后,isRateLimitingActive 会返回 true。 不过,在某些事件期间,系统会重置速率限制,因此,即使是后台应用也可以调用 ShortcutManager 方法,直到再次达到速率上限。这些事件包括:

  • 应用进入前台。
  • 系统语言区域发生变化。
  • 用户对通知执行内嵌回复操作。

如果您在开发或测试期间遇到速率限制,则可以从 设备 设置中选择 开发者选项 > 重置 ShortcutManager 速率限制,或者在 adb 中输入以下命令:

$ adb shell cmd shortcut reset-throttling [ --user <var>your-user-id</var> ]

备份和恢复

通过在应用的清单文件中添加 android:allowBackup="true" 属性赋值,您可以允许用户在更换设备时对应用执行备份和恢复操作。如果您支持备份和恢复,请牢记有关应用快捷方式的以下注意事项:

  • 静态快捷方式会自动重新发布,但这只发生在用户在新设备上重新安装您的应用后。
  • 系统不会备份动态快捷方式,因此您必须在应用中添加相应的逻辑,以便在用户在新设备上打开应用时重新发布动态快捷方式。
  • 固定快捷方式会自动恢复到设备的启动器,但系统不会备份与固定快捷方式关联的图标。 因此,请将固定快捷方式的图片保存在应用中,以便轻松将其恢复到新设备上。

以下代码段演示了如何以最佳方式恢复应用的动态快捷方式以及如何检查是否保留了应用的固定快捷方式:

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        if (ShortcutManagerCompat.getDynamicShortcuts(this).isEmpty()) {
            // Application restored. Re-publish dynamic shortcuts.
            if (ShortcutManagerCompat.getPinnedShortcuts(this).isNotEmpty()) {
                // Pinned shortcuts are restored. Use updateShortcuts() to make
                // sure they contain up-to-date information.
            }

        }
    }
    // ...
}