管理快捷方式

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

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

快捷方式的行为

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

快捷方式的可见性

当用户执行特定手势或语音指令时,静态快捷方式和动态快捷方式会显示在受支持的启动器或助理中。在支持的启动器上,轻触并按住应用的启动器图标即可,但在其他启动器应用中,此手势可能有所不同。借助 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) 时更新现有快捷方式的排名。

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

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

管理多个 intent 和 Activity

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

分配多个 intent

使用 ShortcutInfoCompat.Builder 创建快捷方式时,您可以使用 setIntents() 而非 setIntent()。通过调用 setIntents(),您可以在用户选择快捷方式时在应用内启动多个 activity,从而将列表中除最后一个 activity 之外的所有 activity 放置在返回堆栈上。如果用户随后点按设备的返回按钮,他们会看到应用中的其他 activity,而不是返回到设备的启动器。

从一个 Activity 启动另一个 Activity

静态快捷方式不能包含自定义 intent 标记。静态快捷方式的第一个 intent 始终会设置 Intent.FLAG_ACTIVITY_NEW_TASKIntent.FLAG_ACTIVITY_CLEAR_TASK这意味着,当您的应用正在运行时,应用中的所有现有 activity 都会在静态快捷方式启动时销毁。如果您不希望出现此行为,可以在 Activity.onCreate(Bundle) 中使用调用 Activity.finish() 的 trampoline activity(一种用于启动另一个 activity 的不可见 activity):

  1. AndroidManifest.xml 文件中,在 trampoline activity 中添加属性分配 android:taskAffinity=""。
  2. 在快捷方式资源文件中,在静态快捷方式内的 intent 中引用 trampoline activity。

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

设置 intent 标记

您可以使用任意一组 Intent 标志发布动态快捷方式。最好指定 Intent.FLAG_ACTIVITY_CLEAR_TASK 以及其他标志。否则,如果您在应用运行时尝试启动其他任务,目标 activity 可能不会显示。

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

更新快捷方式

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

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

请考虑以下示例,其中假定 getMaxShortcutCountPerActivity() 返回的值是 4

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

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

这样一来,用户总共可以访问 7 个链接到发布商应用中的 activity 的快捷方式。这是因为总数上限包含快捷方式数量上限和 3 个固定快捷方式。

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

可推送以便在 Google 助理等 Google 助理应用中显示的快捷方式数量没有限制。使用 ShortcutManagerCompat Jetpack 库的 pushDynamicShortcut() 方法创建和更新在助理应用中使用的快捷方式。此外,请将 Google Shortcuts Integration 库添加到您的应用,使动态链接能够显示在 Google 助理上。

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

处理系统语言区域的变更

应用收到表示系统语言区域有更改的 Intent.ACTION_LOCALE_CHANGED 广播时,必须更新动态和固定快捷方式。

跟踪快捷方式的使用情况

为了确定静态和动态快捷方式出现的情况,启动器会检查快捷方式的激活历史记录。对于静态快捷方式,您可以在发生以下任一事件时调用 reportShortcutUsed() 方法并向其传递快捷方式的 ID,从而跟踪用户何时在应用中完成特定操作:

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

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

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

停用快捷方式

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

速率限制

使用 setDynamicShortcuts(), addDynamicShortcuts()updateShortcuts() 方法时,您可能只能在后台应用(即在前台没有 activity 或服务的应用)中调用这些方法的次数达到特定次数。您可以调用这些方法的特定次数限制称为“速率限制”。此功能可防止 ShortcutManagerCompat 过度使用设备资源。

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

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

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

$ adb shell cmd shortcut reset-throttling [ --user your-user-id ]

备份和恢复

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

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

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

Kotlin

class MyMainActivity : Activity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        if (ShortcutManagerCompat.dynamicShortcuts.size == 0) {
            // Application restored. Re-publish dynamic shortcuts.
            if (ShortcutManagerCompat.pinnedShortcuts.size > 0) {
                // Pinned shortcuts are restored. Use updateShortcuts() to make
                // sure they contain up-to-date information.
            }

        }
    }
    // ...
}

Java

public class MainActivity extends Activity {
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        if (ShortcutManagerCompat.getDynamicShortcuts().size() == 0) {
            // Application restored. Re-publish dynamic shortcuts.
            if (ShortcutManagerCompat.getPinnedShortcuts().size() > 0) {
                // Pinned shortcuts are restored. Use pdateShortcuts() to make
                // sure they contain up-to-date information.
            }
        }
    }
    // ...
}