你可以在 Android 搜索对话框或搜索微件中提供基于最近搜索查询的搜索建议。例如,如果用户查询了“puppies”,当他们再次输入相同的查询时,该查询会作为建议出现。图 1 显示了一个带有最近查询建议的搜索对话框示例。
在开始之前,请在应用中实现搜索对话框或搜索微件以进行基本搜索。要了解具体操作,请参阅创建搜索界面。
基础知识

图 1. 显示最近查询建议的搜索对话框截图。
最近查询建议是已保存的搜索。当用户选择建议时,你的可搜索 Activity 会收到一个 ACTION_SEARCH
Intent,其中包含该建议作为你的可搜索 Activity 已处理的搜索查询。
要提供最近查询建议,你需要
- 实现一个可搜索 Activity。
- 创建一个继承自
SearchRecentSuggestionsProvider
的内容提供程序,并在应用清单中声明它。 - 修改可搜索配置,添加提供搜索建议的内容提供程序的相关信息。
- 每次执行搜索时,将查询保存到你的内容提供程序。
Android 系统会显示搜索对话框,同样也会在对话框或搜索微件下方显示搜索建议。你提供系统从中检索建议的来源。
当系统识别出你的 Activity 是可搜索的并且提供搜索建议时,用户输入查询时会发生以下情况
- 系统获取搜索查询文本(用户开始输入的任何内容),并向包含你的建议的内容提供程序执行查询。
- 你的内容提供程序返回一个指向所有匹配搜索查询文本的建议的
Cursor
。 - 系统显示由
Cursor
提供的建议列表。
显示最近查询建议后,可能会发生以下情况
- 如果用户输入其他键或以任何方式更改查询,将重复上述步骤并更新建议列表。
- 如果用户执行搜索,将忽略建议,并使用正常的
ACTION_SEARCH
Intent 将搜索发送到你的可搜索 Activity。 - 如果用户选择一个建议,将使用建议的文本作为查询,向你的可搜索 Activity 发送一个
ACTION_SEARCH
Intent。
你为内容提供程序继承的 SearchRecentSuggestionsProvider
类会自动执行上述步骤中的工作,因此需要编写的代码很少。
创建内容提供程序
提供最近查询建议的内容提供程序是 SearchRecentSuggestionsProvider
的一个实现。这个类为你完成了所有工作。你只需要编写一个执行一行代码的类构造函数。
例如,以下是一个完整的最近查询建议内容提供程序实现
Kotlin
class MySuggestionProvider : SearchRecentSuggestionsProvider() { init { setupSuggestions(AUTHORITY, MODE) } companion object { const val AUTHORITY = "com.example.MySuggestionProvider" const val MODE: Int = SearchRecentSuggestionsProvider.DATABASE_MODE_QUERIES } }
Java
public class MySuggestionProvider extends SearchRecentSuggestionsProvider { public final static String AUTHORITY = "com.example.MySuggestionProvider"; public final static int MODE = DATABASE_MODE_QUERIES; public MySuggestionProvider() { setupSuggestions(AUTHORITY, MODE); } }
对 setupSuggestions()
的调用会传递搜索授权机构的名称和数据库模式。搜索授权机构可以是任何唯一的字符串,但最佳实践是使用内容提供程序的完全限定名称,例如包名后跟提供程序的类名。例如,"com.example.MySuggestionProvider"
。
数据库模式必须包含 DATABASE_MODE_QUERIES
,并且可以选择包含 DATABASE_MODE_2LINES
,后者会在建议表中添加一列,以便你可以为每个建议提供第二行文本。如果你想在每个建议中提供两行,请参阅以下示例
Kotlin
const val MODE: Int = DATABASE_MODE_QUERIES or DATABASE_MODE_2LINES
Java
public final static int MODE = DATABASE_MODE_QUERIES | DATABASE_MODE_2LINES;
在应用清单中声明内容提供程序,其授权字符串与你的 SearchRecentSuggestionsProvider
类和可搜索配置中使用的授权字符串相同。例如
<application> <provider android:name=".MySuggestionProvider" android:authorities="com.example.MySuggestionProvider" /> ... </application>
修改可搜索配置
要将系统配置为使用你的建议提供程序,请在可搜索配置文件中的 <searchable>
元素中添加 android:searchSuggestAuthority
和 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.MySuggestionProvider" android:searchSuggestSelection=" ?" > </searchable>
的 android:searchSuggestAuthority
值必须是你的内容提供程序的完全限定名称,该名称必须与内容提供程序中使用的授权名称完全匹配,例如前面示例中的 "com.example.MySuggestionProvider"
。
的 android:searchSuggestSelection
值必须是一个问号,前面有一个空格:" ?"
。这是 SQLite 选择参数的占位符,它会自动被用户输入的查询文本替换。
保存查询
要填充你的最近查询集合,请将可搜索 Activity 收到的每个查询添加到你的 SearchRecentSuggestionsProvider
。为此,创建一个 SearchRecentSuggestions
实例,并在你的可搜索 Activity 收到查询时调用 saveRecentQuery()
。例如,你可以在 Activity 的 onCreate()
方法中这样保存查询
Kotlin
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.main) if (Intent.ACTION_SEARCH == intent.action) { intent.getStringExtra(SearchManager.QUERY)?.also { query -> SearchRecentSuggestions(this, MySuggestionProvider.AUTHORITY, MySuggestionProvider.MODE) .saveRecentQuery(query, null) } } }
Java
@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); Intent intent = getIntent(); if (Intent.ACTION_SEARCH.equals(intent.getAction())) { String query = intent.getStringExtra(SearchManager.QUERY); SearchRecentSuggestions suggestions = new SearchRecentSuggestions(this, MySuggestionProvider.AUTHORITY, MySuggestionProvider.MODE); suggestions.saveRecentQuery(query, null); } }
SearchRecentSuggestionsProvider
构造函数需要与内容提供程序声明的授权和数据库模式相同的值。
saveRecentQuery()
方法将搜索查询字符串作为第一个参数,第二个参数可选,用于作为建议的第二行字符串或 null。第二个参数仅在你使用 DATABASE_MODE_2LINES
为搜索建议启用双行模式时使用。如果你启用双行模式,则系统查找匹配建议时,查询文本会与第二行进行匹配。
清除建议数据
为保护用户隐私,请始终提供用户清除最近查询建议的方法。要清除查询历史记录,请调用 clearHistory()
。例如
Kotlin
SearchRecentSuggestions(this, HelloSuggestionsProvider.AUTHORITY, HelloSuggestionsProvider.MODE) .clearHistory()
Java
SearchRecentSuggestions suggestions = new SearchRecentSuggestions(this, HelloSuggestionProvider.AUTHORITY, HelloSuggestionProvider.MODE); suggestions.clearHistory();
可以从菜单项、偏好设置项或按钮(如“清除搜索历史记录”)中执行此操作。提供一个确认对话框,以验证用户是否要删除其搜索历史记录。