管理快捷方式

创建快捷方式后,您需要在应用生命周期内对其进行管理。例如,您可能需要确定用户使用您的快捷方式完成特定操作的频率,以此来优化应用。在其他情况下,您可能会决定停用某个固定快捷方式,以防止应用执行过时或缺失的操作。本指南将介绍这些方法以及其他几种管理快捷方式的常用方法。

快捷方式的行为

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

快捷方式的可见性

安全方面的重要提示:所有快捷方式信息均存储在凭据加密存储空间中,因此您的应用只能在用户解锁设备之后访问用户的快捷方式。

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

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

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

  • 用户将其移除。
  • 与该快捷方式关联的应用被卸载。
  • 用户转至设置 > 应用和通知,选择一个应用并按下存储 > 清除存储空间,清除了应用的数据。

快捷方式的显示顺序

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

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

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

排名为连续的非负整数。您可以在调用 updateShortcuts(Context, List) addDynamicShortcuts(Context, List) setDynamicShortcuts(Context, List) 时更新现有快捷方式的排名。

注意:排名会自动调整,因此,每类(静态或动态)快捷方式都只有一种排名。例如,假设有三个排名分别为 0、1 和 2 的动态快捷方式,如果再添加另一个排名为 1 的动态快捷方式,则表示请求将此快捷方式置于第二位。作为响应,第三个和第四个快捷方式将进一步靠近快捷方式列表底部,其排名将分别变为 2 和 3。

管理多个 intent 和 Activity

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

分配多个 intent

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

注意:如果用户在选择某个快捷方式后按下返回键,您的应用会启动与快捷方式资源文件中列出的倒数第二个 intent 相对应的 Activity。此行为模式会在用户反复按下返回按钮时继续,直到用户清除快捷方式创建的返回堆栈为止。接下来,如果用户按下返回按钮,系统会使其返回到启动器。

从一个 Activity 启动另一个 Activity

静态快捷方式不能有自定义 intent 标记。 静态快捷方式的第一个 intent 始终设置有 Intent.FLAG_ACTIVITY_NEW_TASK Intent.FLAG_ACTIVITY_CLEAR_TASK。这意味着,如果应用已在运行,则在静态快捷方式启动时,应用中的所有现有 Activity 都会被销毁。如果不希望出现这种行为,您可以使用 Trampoline Activity,或者使用一个先在 Activity.onCreate(Bundle) 中启动其他 Activity、而后调用 Activity.finish() 的不可见 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. 聊天应用发布了四个动态快捷方式,分别表示 4 个最近的会话(c1、c2、c3 和 c4)。
  2. 用户固定了所有这四个快捷方式。
  3. 之后,用户启动了另外三个会话(c5、c6 和 c7),因此,发布商应用重新发布了动态快捷方式。新的动态快捷方式列表为:c4、c5、c6 和 c7。

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

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

  4. 应用可使用 updateShortcuts(Context, List) 来更新现有七个快捷方式中的任何一个。例如,您可以在聊天对象的图标发生更改时更新这组快捷方式。
  5. 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() 方法。

注意:需要使用 Google 快捷方式集成库,才能使您的应用推送的动态链接显示在 Google Surface(例如 Google 助理)上。将此库添加到应用中即表示您允许 Google 助理提取您的动态链接,并从 Google 助理应用中向用户推荐这些链接。

停用快捷方式

由于您的应用及其用户可以将快捷方式固定到设备的启动器上,因此这些固定快捷方式可能会引导用户执行应用中已过期或不存在的操作。为应对这种情况,您可以调用 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. Need to re-publish dynamic shortcuts.
            if (ShortcutManagerCompat.pinnedShortcuts.size > 0) {
                // Pinned shortcuts have been 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. Need to re-publish dynamic shortcuts.
            if (ShortcutManagerCompat.getPinnedShortcuts().size() > 0) {
                // Pinned shortcuts have been restored. Use
                // updateShortcuts() to make sure they contain
                // up-to-date information.
            }
        }
    }
    // ...
}

其他资源

Android AppShortcuts 示例进一步说明了如何使用本页介绍的工作流程。