添加自定义搜索建议

使用 Android 搜索对话框或搜索微件时,您可以提供 根据应用中的数据创建的自定义搜索建议。例如: 如果您的应用是字典,您可以建议字典中 匹配用户完成输入之前在搜索字段中输入的文本 查询内容这些建议很有价值,因为它们可以有效预测 用户需要的内容,并提供对服务的即时访问。图 1 显示了一个示例 显示自定义建议的搜索对话框。

您在提供自定义建议后,还可以将其提供给 快速搜索框,可让您从 Google 网站外部 应用。

在添加自定义建议之前,请先实现 Android 搜索对话框或 搜索微件可在应用中搜索。请参阅创建 搜索界面 内容 提供商

基础知识

图 1. 包含以下内容的搜索对话框的屏幕截图 自定义搜索建议。

当用户选择自定义建议时,系统会发送 Intent已添加到您的 搜索活动。与发送 intent 和 ACTION_SEARCH 您可以改为指定自定义建议 ACTION_VIEW - 或 任何其他 intent 操作,还要包含 选定的建议。在字典示例中,当用户选择 应用就可以立即打开该字词的定义 在字典中搜索匹配项的过程。

如需提供自定义建议,请执行以下步骤:

  • 实现一个基本的可搜索 activity,如 创建搜索界面
  • 使用内容相关信息修改可搜索配置 提供自定义建议的提供程序。
  • 构建一个表,例如在 SQLiteDatabase, 以获取建议,并使用所需的列设置表格格式。
  • 创建内容 provider,该提供程序有权访问您的建议表格,并声明 provider。
  • 声明当用户选择Intent 包括自定义操作和自定义数据。

正如 Android 系统会显示搜索对话框一样,它也会显示您的 搜索建议。您需要一个供系统用来 检索您的建议。已读 content provider 了解如何创建内容提供程序。

当系统发现您的 Activity 可搜索并提供 搜索建议,当用户输入 查询:

  1. 系统会获取搜索查询文本,也就是说, 对管理 建议。
  2. 您的内容提供程序会返回 Cursor 指向与搜索查询相关的所有建议 文本。
  3. 系统会显示由 Google 提供的 Cursor

显示自定义建议后,可能会发生以下情况:

  • 如果用户输入其他字母或以任何方式更改查询, 系统会重复上述步骤,相应建议列表也会随之更新。
  • 如果用户执行此搜索,这些建议会被忽略,并且 使用常规搜索结果传送到您的可搜索活动。 ACTION_SEARCH intent。
  • 如果用户选择一条建议,则系统会向可搜索对象发送一个 intent activity,其中包含自定义操作和自定义数据,以便您的应用可以打开 相应建议的内容。

修改可搜索配置

要添加自定义建议的支持,请将 android:searchSuggestAuthority 属性添加到 <searchable> 元素, 如以下示例中所示:

<?xml version="1.0" encoding="utf-8"?>
<searchable xmlns:android="http://schemas.android.com/apk/res/android"
    android:label="@string/app_label"
    android:hint="@string/search_hint"
    android:searchSuggestAuthority="com.example.MyCustomSuggestionProvider">
</searchable>

您可能需要其他属性,具体取决于您要执行的 intent 类型 附加到每条建议,以及您希望如何设置内容查询的格式 提供商。下面将讨论其他可选属性 部分。

创建 content provider

如需为自定义建议创建 content provider,请先参阅 content provider 了解如何创建内容提供程序。用于自定义的 content provider 与其他任何内容提供程序都是相似的。不过,对于每个 Cursor中的相应行必须 添加系统可以理解并用来设置 建议。

当用户在搜索对话框或搜索微件中输入文本时,系统会 通过调用 query() 每次输入字母时都会触发一次。在您的 query() 实现中, 您的内容提供程序必须搜索您的建议数据并返回 Cursor,它指向确定为优质的行 建议。

如需详细了解如何为自定义建议创建 content provider,请参阅 具体介绍:

处理建议查询
系统如何向您的内容提供方发送请求以及如何处理 。
构建建议表格
如何定义系统期望在 随每个查询返回 Cursor

处理建议查询

当系统向您的内容提供程序请求建议时,它会调用 内容提供程序的 query() 方法。实现此方法 搜索您的建议数据,并返回指向Cursor 并给出您认为相关的建议

下面概要列出了系统传递给 query() 方法(按顺序列出):

  1. uri

    始终是内容 Uri,格式为 如下:

    content://your.authority/optional.suggest.path/SUGGEST_URI_PATH_QUERY
    

    默认行为是系统传递此 URI 并附加查询 文本到其中:

    content://your.authority/optional.suggest.path/SUGGEST_URI_PATH_QUERY/puppies
    

    末尾的查询文本使用 URI 编码规则进行编码,因此您可能 在执行搜索前需要对其进行解码。

    optional.suggest.path 部分仅包含在 URI(如果您在可搜索配置文件中设置了此类路径) android:searchSuggestPath 属性。只有在 您可为多个可搜索 activity 使用同一 content provider。如果 就是这种情况,消除建议查询来源的歧义。

    <ph type="x-smartling-placeholder">
  2. projection
    始终为 null。
  3. selection
    android:searchSuggestSelection 中提供的值 属性,否则设置为 null 声明 android:searchSuggestSelection 属性。通过 我们将进一步讨论这一点。
  4. selectionArgs
    如果存在以下情况,则包含搜索查询作为数组的第一个也是唯一一个元素: 声明 android:searchSuggestSelection 属性, 您的可搜索配置。如果您没有声明 android:searchSuggestSelection,则此参数为 null。 下一部分将对此作进一步说明。
  5. sortOrder
    始终为 null。

系统可以通过两种方式向您发送搜索查询文本。默认方法是 查询文本将作为传入的内容 URI 的最后一个路径包含在内 uri 参数。但是,如果您在 可搜索配置的android:searchSuggestSelection 属性,那么查询文本会作为 selectionArgs 字符串数组。这两个选项 继续。

在 Uri 中获取查询

默认情况下,查询会附加为 uri 的最后一段 参数 - Uri 对象。要在此例中检索查询文本, 大小写, 使用 getLastPathSegment(), 如以下示例中所示:

Kotlin

val query: String = uri.lastPathSegment.toLowerCase()

Java

String query = uri.getLastPathSegment().toLowerCase();

这将返回 Uri 的最后一段,即查询 用户输入文本。

在选择参数中获取查询

与使用 URI 相比, query() 方法,即可接收执行 您可能需要 selectionselectionArgs 参数,以包含适当的值。在本课中, 请将 android:searchSuggestSelection 属性添加到 带有 SQLite 选择字符串的可搜索配置。在选定范围内 字符串中,请添加一个问号 (?) 作为占位符,以表示 搜索查询。系统会使用如下选择字符串调用 query()selection 参数,并将搜索查询作为第一个元素 在 selectionArgs 数组中。

例如,您可以按照如下方式构建 android:searchSuggestSelection 属性来创建全文 搜索语句:

<?xml version="1.0" encoding="utf-8"?>
<searchable xmlns:android="http://schemas.android.com/apk/res/android"
    android:label="@string/app_label"
    android:hint="@string/search_hint"
    android:searchSuggestAuthority="com.example.MyCustomSuggestionProvider"
    android:searchSuggestIntentAction="android.intent.action.VIEW"
    android:searchSuggestSelection="word MATCH ?">
</searchable>

使用此配置时,query() 方法会传递 selection 参数作为 "word MATCH ?"selectionArgs 参数作为搜索查询。将这些值传递给 一个 SQLite query() 方法作为各自的参数,系统会将它们合成为 也就是说,问号会替换为查询文本。如果 以这种方式接收建议查询,并且需要向查询中添加通配符 您需要将它们附加到 selectionArgs 参数或作为其前缀,因为 该值会用引号引起来,并插入问号的位置。

上例中的另一个属性是 android:searchSuggestIntentAction,用于定义 intent 操作 随每个 intent 发送。我们将在本课程中 请参阅声明 intent 建议部分。

<ph type="x-smartling-placeholder">

构建建议表格

当您使用 Cursor 向系统返回建议时, 系统要求每行中有特定的列。无论您是存储 设备上的 SQLite 数据库(网络上的数据库)中的建议数据 或者以其他格式在设备或网络上,将建议的格式设置为行 放在表中,并使用 Cursor 呈现。

<ph type="x-smartling-placeholder">

系统可以理解多个列,但其中只有其中两个是必需的:

_ID
每条建议的唯一整数行 ID。系统要求此操作 在 ListView
SUGGEST_COLUMN_TEXT_1
显示为建议的字符串。

以下各列均为可选列。大部分功能在 后续部分。

SUGGEST_COLUMN_TEXT_2
一个字符串。如果您的Cursor包含此列,则所有 建议以两行格式提供。此列中的字符串为 在主要建议下方显示为第二行较小的文本 文本。它可以为 null 或为空,表示没有次要文本。
SUGGEST_COLUMN_ICON_1
一个可绘制资源、内容或文件 URI 字符串。如果您的 Cursor包含此列,则提供所有建议 采用图标加文本格式,可绘制图标在左侧。这个 可以为 null 或 0,表示该行中没有图标。
SUGGEST_COLUMN_ICON_2
一个可绘制资源、内容或文件 URI 字符串。如果您的 Cursor包含此列,则提供所有建议 图标加文本格式,图标在右侧。可以是 null 或 0 表示该行中没有图标。
SUGGEST_COLUMN_INTENT_ACTION
一个 intent 操作字符串。如果此列存在且在 给定行,此处定义的操作将用于生成建议的 intent。如果未提供该元素,则系统会从 可搜索的android:searchSuggestIntentAction字段 配置。如果对所有建议执行的操作都相同, 指定操作 android:searchSuggestIntentAction 并省略此列。
SUGGEST_COLUMN_INTENT_DATA
一个数据 URI 字符串。如果此列存在且在给定位置包含值 行中,这些数据会在形成建议的 intent 时使用。如果 提供的数据来自 可搜索的android:searchSuggestIntentData字段 配置。如果二者均未提供,则 intent 的数据字段为 null。如果所有建议的数据都相同,或者可以描述 使用常量部分和特定 ID,那么指定它更高效 使用 android:searchSuggestIntentData 忽略此项 列。
SUGGEST_COLUMN_INTENT_DATA_ID
一个 URI 路径字符串。如果此列存在且在给定位置包含值 行,后跟“/”并将此值附加到 intent 中的数据字段。 仅当由 android:searchSuggestIntentData 属性 已设置为相应的基本字符串。
SUGGEST_COLUMN_INTENT_EXTRA_DATA
任意数据。如果此列存在且在给定行中包含值, 这是形成建议 intent 时使用的额外数据。 如果未提供,则 intent 的额外数据字段为 null。通过此列,您可以 这些建议会提供额外数据,这些数据会作为 extra 包含在 intent 的 EXTRA_DATA_KEY 键。
SUGGEST_COLUMN_QUERY
如果此列存在并且指定行中存在此元素,则此值为 构成建议查询时使用的数据,以 在 intent 的 QUERY 键。如果建议的操作为 ACTION_SEARCH,则必须指定该字段。 但在其他情况下则是可选的。
SUGGEST_COLUMN_SHORTCUT_ID
仅当为快速搜索框提供建议时,才使用此列。此列 指示是否必须将搜索建议存储为快捷方式; 是否必须进行验证。快捷方式通常在用户 点按快速搜索框中的建议。如果缺失,结果将存储为 快捷方式,且永不刷新。如果设置为 SUGGEST_NEVER_MAKE_SHORTCUT, 结果不会存储为快捷方式。否则,快捷方式 ID 会用于 请稍后再回来查看 SUGGEST_URI_PATH_SHORTCUT
SUGGEST_COLUMN_SPINNER_WHILE_REFRESHING
仅当为快速搜索框提供建议时,才使用此列。此列 指定必须显示旋转图标,而不是 SUGGEST_COLUMN_ICON_2,而此建议的快捷键为 。

以下各部分将进一步讨论其中大部分列。

声明用于提供建议的 intent

当用户从 搜索对话框或搜索微件时,系统会将自定义 Intent 发送到您的 搜索活动。您必须为 intent 定义操作和数据。

声明 intent 操作

自定义建议最常见的 intent 操作是 ACTION_VIEW:适合在您想要打开的应用时使用, 例如某个字词的定义、某人的联系信息或某个网页。 不过,intent 操作可以是其他任何操作,并且对于每个操作可以有所不同 建议。

根据您是否希望所有建议使用相同的 intent 操作, 可以通过以下两种方式定义操作:

  • 使用 android:searchSuggestIntentAction 属性 可搜索的配置文件,为所有建议定义操作,例如 如以下示例中所示:
    <?xml version="1.0" encoding="utf-8"?>
    <searchable xmlns:android="http://schemas.android.com/apk/res/android"
        android:label="@string/app_label"
        android:hint="@string/search_hint"
        android:searchSuggestAuthority="com.example.MyCustomSuggestionProvider"
        android:searchSuggestIntentAction="android.intent.action.VIEW" >
    </searchable>
    
  • 使用 SUGGEST_COLUMN_INTENT_ACTION 列定义 操作。为此,请将 在建议表格中添加 SUGGEST_COLUMN_INTENT_ACTION 列 然后为每条建议添加要使用的操作,例如 "android.intent.action.VIEW"

您还可以结合使用这两种方法。例如,您可以将 android:searchSuggestIntentAction 属性,其中包含待执行的操作 则默认将此操作用于所有建议, 通过在 SUGGEST_COLUMN_INTENT_ACTION 列。如果不添加值 SUGGEST_COLUMN_INTENT_ACTION 列中,则 intent android:searchSuggestIntentAction 属性中提供的参数是 。

<ph type="x-smartling-placeholder">

声明 intent 数据

当用户选择一条建议时,您的可搜索 Activity 会收到 intent 带有您定义的操作,如前文所述 部分,但是 intent 还必须携带可供 activity 识别的数据 选择的是哪一条建议具体而言,数据必须是唯一的 (例如 SQLite 表格中相应建议的行 ID)。 收到 intent 后,您可以使用 getData()getDataString()

您可以通过两种方式来定义 intent 中包含的数据:

  • 在 建议表格中的SUGGEST_COLUMN_INTENT_DATA列。

    在建议中为每个意图提供所有必要的数据信息 添加 SUGGEST_COLUMN_INTENT_DATA 列和 然后在其中填充每行的唯一数据此列中的数据 会完全按照您在此列中的定义附加到 intent。您可以 然后使用 getData() 进行检索,或者 getDataString()

    <ph type="x-smartling-placeholder">
  • 将数据 URI 分成两部分:所有建议共有的部分 以及每条建议独有的部分将这些部分放入 可搜索项的 android:searchSuggestintentData 属性 配置和 SUGGEST_COLUMN_INTENT_DATA_ID 列 分别显示在建议表格中

    以下示例展示了如何声明 可搜索内容的android:searchSuggestIntentData属性 配置:

      <?xml version="1.0" encoding="utf-8"?>
      <searchable xmlns:android="http://schemas.android.com/apk/res/android"
          android:label="@string/app_label"
          android:hint="@string/search_hint"
          android:searchSuggestAuthority="com.example.MyCustomSuggestionProvider"
          android:searchSuggestIntentAction="android.intent.action.VIEW"
          android:searchSuggestIntentData="content://com.example/datatable" >
      </searchable>
      

    为每条建议添加最终路径,也就是 建议的“SUGGEST_COLUMN_INTENT_DATA_ID”列 表格。当用户选择一条建议时,系统会从该建议字符串中提取字符串 android:searchSuggestIntentData,附加一个斜杠 (/), 然后将 SUGGEST_COLUMN_INTENT_DATA_ID 列,形成完整内容 URI然后,您可以使用Uri getData()

添加更多数据

如果您需要通过 intent 表达更多信息,可以再添加一个 例如 SUGGEST_COLUMN_INTENT_EXTRA_DATA, 存储有关建议的附加信息。此列中保存的数据 会放在 intent 额外软件包的 EXTRA_DATA_KEY 中。

处理 intent

在使用自定义 intent 提供自定义搜索建议后,您需要 在用户选择了一个可搜索 activity 时,处理这些 intent 建议。这是除了处理 ACTION_SEARCH 之外, intent,而可搜索 activity 已经执行了这项操作。这里的示例说明了 您可以在 activity 运行 activity 期间处理 intent, onCreate() 回调:

Kotlin

when(intent.action) {
    Intent.ACTION_SEARCH -> {
        // Handle the normal search query case.
        intent.getStringExtra(SearchManager.QUERY)?.also { query ->
            doSearch(query)
        }
    }
    Intent.ACTION_VIEW -> {
        // Handle a suggestions click, because the suggestions all use ACTION_VIEW.
        showResult(intent.data)
    }
}

Java

Intent intent = getIntent();
if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
    // Handle the normal search query case.
    String query = intent.getStringExtra(SearchManager.QUERY);
    doSearch(query);
} else if (Intent.ACTION_VIEW.equals(intent.getAction())) {
    // Handle a suggestions click, because the suggestions all use ACTION_VIEW.
    Uri data = intent.getData();
    showResult(data);
}

在此示例中,intent 操作是 ACTION_VIEW,数据 含有指向建议项的完整 URI,该 URI 由 android:searchSuggestIntentData 字符串和 SUGGEST_COLUMN_INTENT_DATA_ID 列。URI 随后会传递给 本地 showResult() 方法,用于在 content provider 中查询 所有项目。

<ph type="x-smartling-placeholder">

重写查询文本

默认情况下,如果用户使用 方向控件(例如使用轨迹球或方向键),则查询文本 更新。不过,您可以暂时重新编写显示的用户查询文本 以及与焦点中的建议相匹配的查询。这样, 用户会看到系统建议的查询,并可选择搜索框并进行修改 然后再将其作为搜索进行分派。

您可以通过以下方式重新编写查询文本:

  • android:searchMode 属性添加到可搜索内容中 具有 "queryRewriteFromText" 值的配置。在本课中, 例如,建议的 SUGGEST_COLUMN_TEXT_1 中的内容 列用于重写查询文本。
  • android:searchMode 属性添加到可搜索路径中\ 具有 "queryRewriteFromData" 值的配置。在本课中, 在这种情况下,建议的 SUGGEST_COLUMN_INTENT_DATA 列用于重写查询 文本。只能将其用于 URI 或其他预期 例如 HTTP 网址。请勿使用内部 URI scheme 重写 以这种方式处理查询。
  • 在 建议表格中的SUGGEST_COLUMN_QUERY列。如果 列,并且包含当前建议的值, 用于重写查询文本,并覆盖之前的 实现。

在快速搜索框中显示搜索建议

配置好应用以提供自定义搜索建议后, 可供全球可访问的快速搜索框使用,就像修改 包含可搜索配置 将 android:includeInGlobalSearch 替换为值 "true"

唯一需要进行额外工作的情况是,您的内容 provider 需要读取权限。在这种情况下,您需要添加 <path-permission> 元素,以便提供方授予 Quick 搜索框对内容提供程序的读取权限,如下所示 示例:

<provider android:name="MySuggestionProvider"
          android:authorities="com.example.MyCustomSuggestionProvider"
          android:readPermission="com.example.provider.READ_MY_DATA"
          android:writePermission="com.example.provider.WRITE_MY_DATA">
  <path-permission android:pathPrefix="/search_suggest_query"
                   android:readPermission="android.permission.GLOBAL_SEARCH" />
</provider>

在此示例中,提供程序会限制对内容的读写权限。 <path-permission> 元素会按以下方式修正限制: 授予对 "/search_suggest_query" 内内容的读取权限 "android.permission.GLOBAL_SEARCH" 权限时的路径前缀 存在。这会授予对快速搜索框的访问权限,以便查询您的内容 获取建议。

如果您的内容提供方未强制规定读取权限,则快速搜索 默认情况下,Box 会读取消息。

启用设备上的建议功能

默认情况下,应用不会在快速搜索框中提供建议, 即使它们已配置为用户可选择是否添加 打开可搜索 项—位于设置 >搜索,并支持您的 作为可搜索项。

可供快速搜索框使用的每个应用程序在 可搜索项设置页面。条目包含应用的名称 并简要说明哪些内容可从该应用中搜索到 ,可在快速搜索框中获得建议。定义广告内容描述文字 请为可搜索应用添加 android:searchSettingsDescription 属性添加到可搜索配置中,如下所示: 示例:

<?xml version="1.0" encoding="utf-8"?>
<searchable xmlns:android="http://schemas.android.com/apk/res/android"
    android:label="@string/app_label"
    android:hint="@string/search_hint"
    android:searchSuggestAuthority="com.example.MyCustomSuggestionProvider"
    android:searchSuggestIntentAction="android.intent.action.VIEW"
    android:includeInGlobalSearch="true"
    android:searchSettingsDescription="@string/search_description" >
</searchable>

使 android:searchSettingsDescription 的字符串简明扼要 并说明可搜索的内容。例如,“Artists, 专辑和曲目”或“已保存的记事”。 提供此说明非常重要,因为这样才能让用户知道 提供的建议出现以下情况时,一律添加此属性: android:includeInGlobalSearch 为 true。

因为用户必须访问设置菜单才能启用搜索建议 如果搜索是应用的重要方面,请考虑如何 将这一点传达给用户。例如,您可以在首次访问网站时提供备注 用户启动了该应用,其中说明了如何启用针对“快速”的搜索建议 搜索框。

管理快速搜索框建议快捷键

用户从快速搜索框选择的建议可以自动 都变成了快捷方式这些建议是系统从您的 这样它就可以快速访问建议,而无需 重新查询您的内容提供程序。

默认情况下,系统会为“快速搜索”检索到的所有建议启用此功能 但如果您的建议数据随时间而变化,则可 快捷方式将被刷新。例如,如果您的建议涉及动态 数据(如联系人的在线状态),然后请求该建议 在向用户显示时刷新快捷方式。为此,请添加 建议表格中的SUGGEST_COLUMN_SHORTCUT_ID。您可以使用 此列用于为其中一个建议中的每条建议配置快捷方式行为 方法:

  • 使快速搜索框重新查询您的内容提供商,以获取最新的搜索结果。 建议快捷方式的版本。

    SUGGEST_COLUMN_SHORTCUT_ID 列中为以下值提供一个值: 每次创建快捷方式时要重新查询新版本的建议 。快捷方式会快速显示 直到刷新查询返回结果,此时 系统会根据新信息刷新建议。刷新查询为 发送到您的内容提供程序(URI 路径为 SUGGEST_URI_PATH_SHORTCUT - 而不是 SUGGEST_URI_PATH_QUERY

    使用Cursor 或为空,表示 快捷键已失效,在这种情况下,建议会消失 ,相应快捷方式会被移除。

    如果建议中引用的数据可能需要更长时间刷新(例如 基于网络的刷新,您还可以添加 SUGGEST_COLUMN_SPINNER_WHILE_REFRESHING列添加到您的 值为 true 的建议表,以显示 右侧图标,直到刷新完成。除 true 之外的任何值 不显示进度旋转图标

  • 完全阻止将建议复制到快捷方式。

    SUGGEST_NEVER_MAKE_SHORTCUT SUGGEST_COLUMN_SHORTCUT_ID 列。在这种情况下, 建议绝不会复制到快捷方式中。只有在以下情况下, 您绝对不希望显示之前复制的建议。如果您 为该列提供常规值,则建议快捷方式 直到刷新查询返回结果。

  • 应用默认的快捷方式行为。

    将各项的“SUGGEST_COLUMN_SHORTCUT_ID”留空 该建议不会改变,并可保存为 快捷方式。

如果您的建议没有任何变化,则您无需 SUGGEST_COLUMN_SHORTCUT_ID 列。

<ph type="x-smartling-placeholder">

关于快速搜索框建议排名

将应用的搜索建议提供给快速搜索框后, 快速搜索框的排名决定了如何将建议显示给 用户执行特定查询操作这可能取决于 以及用户选择您的结果的频率,以及 以及来自其他应用的请求无法保证您的建议效果会如何 或者针对给定查询是否显示应用的建议。在 一般而言,提供高质量的搜索结果可提高应用 提供建议的位置 质量欠佳的建议更有可能被排名较低或不显示。