为助手优化上下文内容

Android 6.0 Marshmallow 引入了一种新的方式,让用户可以通过助手应用(例如 Google 助手)与应用互动。助手是一个顶层窗口,用户可以通过它查看当前活动的相关操作。这些操作可能包括指向设备上其他应用的深层链接。

用户可以通过长按主页按钮或说出 关键词 来激活助手。作为响应,系统将打开一个顶层窗口,显示上下文相关的操作。

助手应用(例如 Google 助手)通过称为“Now on Tap”的功能实现助手叠加窗口,该功能与 Android 平台级功能一起使用。系统允许用户选择一个助手应用,该应用使用 Android 的 Assist API 从您的应用获取上下文信息。

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

使用助手

图 1 说明了用户与助手的典型交互。当用户长按主页按钮时,Assist API 回调将在应用中调用(步骤 1)。助手呈现叠加窗口(步骤 2 和 3),然后用户选择要执行的操作。助手执行所选操作,例如使用指向(目标)餐厅应用的深层链接触发意图(步骤 4)。

图 1. 使用 Google 应用的 Now on Tap 功能的助手交互示例

用户可以通过选择设置 > 应用 > 默认应用 > 助手和语音输入来配置助手。用户可以更改系统选项,例如访问屏幕内容作为文本和访问屏幕截图,如图 2 所示。

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

源应用

为了确保您的应用与助手一起作为用户信息来源正常工作,您只需遵循 辅助功能最佳实践。本节介绍如何提供其他信息以帮助改善助手用户体验,以及需要特殊处理的场景,例如自定义视图。

与助手共享其他信息

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

要向助手提供其他信息,您的应用通过注册应用监听器并使用活动回调提供特定于活动的的信息来提供全局应用上下文,如图 3 所示

图 3. Assist API 生命周期序列图

要提供全局应用上下文,应用会创建 Application.OnProvideAssistDataListener 的实现,并使用 registerOnProvideAssistDataListener() 注册它。要提供特定于活动的上下文信息,活动会覆盖 onProvideAssistData()onProvideAssistContent()。这两个活动方法在可选的全局回调被调用之后调用。由于回调在主线程上执行,因此它们应及时完成。仅当活动正在运行时才会调用回调。

提供上下文

当用户激活助手时,将调用 onProvideAssistData() 以构建一个完整的 ACTION_ASSIST 意图,其中所有当前应用的上下文都表示为 AssistStructure 的实例。您可以覆盖此方法,将您想要的任何内容放入捆绑包中,以便显示在助手意图的 EXTRA_ASSIST_CONTEXT 部分。

描述内容

您的应用可以实现 onProvideAssistContent(),通过提供与当前活动相关的与内容相关的引用来改善助手用户体验。您可以通过 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) 为助手提供显示给用户的文本。

在大多数情况下,实现辅助功能支持可以让助手获取其所需的信息。 要实现辅助功能支持,请遵守 使应用可访问 中描述的最佳实践,包括以下内容

从助手排除视图

为了处理敏感信息,您的应用可以通过设置 FLAG_SECURE 布局参数(位于 WindowManager 中)来将当前视图从助手排除。您必须为活动创建的每个窗口(包括对话框)显式设置 FLAG_SECURE。您的应用还可以使用 setSecure() 将表面从助手排除。没有全局(应用级)机制可以将所有视图从助手排除。请注意,FLAG_SECURE 不会导致 Assist API 回调停止触发。使用 FLAG_SECURE 的活动仍然可以使用本指南前面描述的回调显式地向助手应用提供信息。

注意: 对于企业帐户(Android for Work),管理员可以使用 setScreenCaptureDisabled() 方法(位于 DevicePolicyManager API 中)禁用工作配置文件的助手数据收集。

语音交互

关键词检测 时也会调用 Assist API 回调。有关更多信息,请参阅 语音操作 文档。

Z 轴顺序注意事项

助手使用一个轻量级叠加窗口,该窗口显示在当前活动的顶部。由于用户可以随时激活助手,因此请勿创建会干扰叠加窗口的永久 系统警报 窗口,如图 4 所示。

图 4. 助手图层 Z 轴顺序

如果您的应用使用 系统警报 窗口,请立即将其移除,因为将其保留在屏幕上会降低用户体验。

目标应用

助手应用通常利用深度链接来查找目标应用。要使您的应用成为潜在的目标应用,请考虑添加 深度链接 支持。当前用户上下文与叠加窗口中显示的深度链接或其他潜在操作之间的匹配是 Google 助手实现特有的。例如,Google 助手应用使用深度链接和 应用链接 来推动流量到目标应用。

实现您自己的助手

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