管理快捷方式

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

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

快捷方式的行为

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

快捷方式的可见性

当用户执行特定手势或语音指令时,静态快捷方式和动态快捷方式会显示在支持的启动器或助理中。在支持的启动器上,让快捷方式显示出来的手势是轻触并按住应用的启动器图标,但其他启动器应用上实际适用的手势可能有所不同。借助 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 生成的分享目标将不再显示在分享表中。

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

管理多个 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 内调用 finish,然后再设置 Compose 内容:

  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 your-user-id ]

备份和恢复

通过在应用的清单文件中添加 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.
            }

        }
    }
    // ...
}