为智能助理优化上下文内容

Android 6.0 Marshmallow 提供了一种让用户通过智能助理与应用进行互动的新方式。智能助理是一个顶级窗口,用户可以查看该窗口以获取当前 Activity 的上下文相关操作。这些操作可能包括指向设备上其他应用的深层链接。

用户可通过长按主屏幕按钮或说出一个启动指令来启用智能助理。系统随即打开一个顶级窗口,其中显示了与上下文相关的操作。

Google 应用通过名为“点按即时卡”的功能实现了智能助理层叠窗口,该功能可与 Android 平台级功能配合使用。系统允许用户选择一款智能助理应用,该应用会使用 Android 的 Assist API 从您的应用获取上下文信息。

本指南介绍了 Android 应用如何使用 Android 的 Assist API 来改善智能助理的用户体验。要了解如何创建可让 Google 助理启动和控制的媒体应用,请参阅 Google 助理和媒体应用

使用智能助理

图 1 显示了用户通常会与智能助理进行的一些互动。当用户长按主屏幕按钮时,系统将在来源应用中调用 Assist API 回调(第 1 步)。智能助理会渲染层叠窗口(第 2 步和第 3 步),然后用户选择要执行的操作。智能助理会执行所选操作,例如触发一个以深层链接指向(目标)餐厅应用的 intent(第 4 步)。

图 1. 智能助理与 Google 应用的“点按即时卡”功能互动的示例

用户可以通过依次选择设置 > 应用 > 默认应用 > 助手和语音输入来配置智能助理。用户可以更改系统选项(例如获取屏幕上的文字内容和获取屏幕截图),如图 2 所示。

图 2. 助手和语音输入设置

来源应用

要确保您的应用与智能助理一起作为用户的信息来源,您只需遵循无障碍功能最佳做法。此部分介绍了如何提供其他信息以帮助改善智能助理的用户体验以及需要特殊处理的场景(例如自定义视图)。

与智能助理分享其他信息

除了文字和屏幕截图外,您的应用还可以与智能助理分享其他信息。例如,音乐应用可以选择传递当前专辑信息,以便智能助理可以根据当前 Activity 建议更智能的操作。请注意,Assist API 不提供媒体控件。要添加媒体控件,请参阅 Google 助理和媒体应用

为了向智能助理提供其他信息,您的应用会通过注册应用监听器来提供全局应用上下文,并通过 Activity 回调提供特定于 Activity 的信息,如图 3 所示:

图 3. Assist API 生命周期流程图

为了提供全局应用上下文,该应用会创建 Application.OnProvideAssistDataListener 的实现并使用 registerOnProvideAssistDataListener() 注册它。要提供特定于 Activity 的上下文信息,Activity 会替换 onProvideAssistData()onProvideAssistContent()。系统会在调用可选的全局回调之后调用这两个 Activity 方法。由于回调在主线程上执行,因此它们应该立即完成。仅在 Activity 运行时才调用回调。

提供上下文

当用户启用智能助理时,系统会调用 onProvideAssistData() 以构建完整的 ACTION_ASSIST Intent,并将当前应用的所有上下文都显示为一个 AssistStructure 实例。您可以替换此方法,将您所需的任何内容放入软件包中,以使其显示在 assist intent 的 EXTRA_ASSIST_CONTEXT 部分中。

描述内容

您的应用可以实现 onProvideAssistContent(),通过提供与当前 Activity 相关的内容相关引用来改善智能助理的用户体验。您可以通过 JSON-LD 对象使用由 Schema.org 定义的通用词汇表来描述应用内容。在下面的示例中,音乐应用会提供结构化数据来描述用户当前正在查看的音乐专辑:

Kotlin

    override fun onProvideAssistContent(assistContent: AssistContent) {
        super.onProvideAssistContent(assistContent)

        val structuredJson: String = JSONObject()
                .put("@type", "MusicRecording")
                .put("@id", "https://example.com/music/recording")
                .put("name", "Album Title")
                .toString()

        assistContent.structuredData = structuredJson
    }
    

Java

    @Override
    public void onProvideAssistContent(AssistContent assistContent) {
      super.onProvideAssistContent(assistContent);

      String structuredJson = new JSONObject()
           .put("@type", "MusicRecording")
           .put("@id", "https://example.com/music/recording")
           .put("name", "Album Title")
           .toString();

      assistContent.setStructuredData(structuredJson);
    }
    

您还可以自定义 onProvideAssistContent() 的实现来改善用户体验,从而提供以下优势:

注意:对于使用自定义文字选择实现的应用,可能需要实现 onProvideAssistContent() 并调用 setClipData()

默认实现

如果 onProvideAssistData()onProvideAssistContent() 回调都没有实现,那么除非当前窗口被标记为安全窗口,否则系统仍会继续操作并将自动收集的信息传递给智能助理。如图 3 所示,系统会使用 onProvideStructure()onProvideVirtualStructure() 的默认实现来收集文本和视图层次结构信息。如果您的视图实现了自定义文本绘制,则替换 onProvideStructure() 以通过调用 setText(CharSequence) 向智能助理提供显示给用户的文本。

在大多数情况下,实现无障碍支持使智能助理能够获取所需信息。 要实现无障碍支持,请查阅使应用易于访问中所述的最佳做法,包括以下做法:

从智能助理中排除视图

要处理敏感信息,应用可以通过设置 WindowManagerFLAG_SECURE 布局参数从智能助理中排除当前视图。您必须为 Activity 创建的每个窗口(包括对话框)明确设置 FLAG_SECURE。您的应用也可以使用 setSecure() 从智能助理中排除某个界面。没有任何全局(应用级别)机制可从智能助理中排除所有视图。请注意,FLAG_SECURE 不会导致 Assist API 回调停止触发。使用 FLAG_SECURE 的 Activity 仍然可以使用本指南前面介绍的回调向智能助理显式提供信息。

注意:对于企业帐号 (Android for Work),管理员可以使用 DevicePolicyManager API 的 setScreenCaptureDisabled() 方法禁止收集工作资料的智能助理数据。

语音交互

检测到启动指令时也会调用 Assist API 回调。如需了解详情,请参阅语音操作文档。

Z 轴顺序注意事项

智能助理会在当前 Activity 之上显示一个轻量级层叠窗口。由于用户可以随时激活智能助理,因此请不要创建干扰层叠窗口的永久性系统提醒窗口,如图 4 所示。

图 4. 辅助层 Z 轴顺序

如果您的应用使用系统提醒窗口,请立即将其移除,因为将它们留在屏幕上会影响用户体验。

目标应用

智能助理通常会利用深层链接查找目标应用。要使您的应用成为潜在的目标应用,请考虑添加深层链接支持。当前用户上下文与深层链接或层叠窗口中显示的其他潜在操作之间的匹配(如图 1 中的第 3 步中所示)取决于智能助理的实现方式。例如,Google 应用使用深层链接和 Firebase App Indexing 将流量引向目标应用。

实现您自己的智能助理

您可能希望实现自己的智能助理。如图 2 所示,用户可以选择正在运行的智能助理应用。智能助理应用必须提供 VoiceInteractionSessionServiceVoiceInteractionSession 的实现,如VoiceInteraction 示例所示。它还需要获得 BIND_VOICE_INTERACTION 权限。然后,智能助理可以接收以 onHandleAssist() 中的 AssistStructure 实例形式表示的文本和视图层次结构。它会通过 onHandleScreenshot() 接收屏幕截图。