添加自定义搜索建议
使用集合让一切井井有条
根据您的偏好保存内容并对其进行分类。
尝试使用 Compose 方式
Jetpack Compose 是推荐用于 Android 的界面工具包。了解如何在 Compose 中添加搜索功能。
您可以在 Android 搜索对话框或搜索微件中根据近期的搜索查询来提供搜索建议。例如,如果用户查询“小狗”,那么当他们再次输入相同的查询时,该查询会显示为建议。图 1 显示了包含近期查询建议的搜索对话框的示例。
开始之前,请实现搜索对话框或搜索微件,以便在您的应用中进行基本搜索。如需了解具体操作方法,请参阅创建搜索界面。
基础知识
图 1. 包含近期查询建议的搜索对话框的屏幕截图。
近期查询建议是保存的搜索。当用户选择某条建议时,可搜索 activity 会接收一个 ACTION_SEARCH
intent,它将该建议作为搜索查询,而可搜索 activity 已处理过该查询。
要提供近期查询建议,您需要执行以下操作:
就像 Android 系统显示搜索对话框一样,它也会在搜索对话框或搜索微件下方显示搜索建议。您提供系统从中检索建议的来源。
如果系统发现您的 activity 可搜索并提供搜索建议,在用户输入查询时会发生以下情况:
- 系统获取搜索查询文本(用户开始输入的所有内容),并对包含建议的内容提供程序执行查询。
- 内容提供程序返回一个
Cursor
,它指向与搜索查询文本匹配的所有建议。
- 系统显示由
Cursor
提供的建议的列表。
显示近期查询建议后,可能会发生以下情况:
- 如果用户输入其他键或以任何方式更改查询,系统会重复执行上述步骤,并更新建议列表。
- 如果用户执行搜索,系统会忽略建议,并使用正常的
ACTION_SEARCH
intent 将搜索传递给可搜索 activity。
- 如果用户选择某条建议,系统会使用建议的文本作为查询,将一个
ACTION_SEARCH
intent 传递给可搜索 Activity。
您为内容提供程序扩展的 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>
修改可搜索配置
如需配置系统以使用建议提供程序,请在可搜索配置文件中将 android:searchSuggestAuthority
和 android:searchSuggestSelection
属性添加到 <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.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();
通过由您选择的“清除搜索记录”菜单项、偏好设置项或按钮来执行此操作。
提供一个确认对话框来确认用户想要删除其搜索记录。
本页面上的内容和代码示例受内容许可部分所述许可的限制。Java 和 OpenJDK 是 Oracle 和/或其关联公司的注册商标。
最后更新时间 (UTC):2025-08-27。
[[["易于理解","easyToUnderstand","thumb-up"],["解决了我的问题","solvedMyProblem","thumb-up"],["其他","otherUp","thumb-up"]],[["没有我需要的信息","missingTheInformationINeed","thumb-down"],["太复杂/步骤太多","tooComplicatedTooManySteps","thumb-down"],["内容需要更新","outOfDate","thumb-down"],["翻译问题","translationIssue","thumb-down"],["示例/代码问题","samplesCodeIssue","thumb-down"],["其他","otherDown","thumb-down"]],["最后更新时间 (UTC):2025-08-27。"],[],[],null,["Try the Compose way \nJetpack Compose is the recommended UI toolkit for Android. Learn how to add search functionality in Compose. \n[Search bar →](/develop/ui/compose/components/search-bar) \n\nYou can provide search suggestions based on recent search queries in the Android search dialog or\nsearch widget. For example, if a user queries \"puppies,\" the query appears as a suggestion when they\ntype the same query again. Figure 1 shows an example of a search dialog with recent query\nsuggestions.\n\nBefore you begin, implement the search dialog or a search widget for basic searches\nin your application. To learn how, see\n[Create a search interface](/develop/ui/views/search/search-dialog).\n\nThe basics \n\n**Figure 1.** Screenshot of a search dialog with recent query\nsuggestions.\n\nRecent query suggestions are saved searches. When the user selects a suggestion, your searchable\nactivity receives an\n[ACTION_SEARCH](/reference/android/content/Intent#ACTION_SEARCH) intent\nwith the suggestion as the search query that your searchable activity already handles.\n\nTo provide recent queries suggestions, you need to:\n\n- Implement a searchable activity.\n- Create a content provider that extends [SearchRecentSuggestionsProvider](/reference/android/content/SearchRecentSuggestionsProvider) and declare it in your application manifest.\n- Modify the searchable configuration with information about the content provider that provides search suggestions.\n- Save queries to your content provider each time a search is executed.\n\nJust as the Android system displays the search dialog, it displays the search suggestions below\nthe dialog or search widget. You provide the source the system retrieves the suggestions from.\n\nWhen the system identifies that your activity is searchable and provides search suggestions, the\nfollowing happens when the user types a query:\n\n1. The system takes the search query text---whatever the user begins typing---and performs a query to the content provider that contains your suggestions.\n2. Your content provider returns a [Cursor](/reference/android/database/Cursor) that points to all suggestions that match the search query text.\n3. The system displays the list of suggestions provided by the `Cursor`.\n\nOnce the recent query suggestions are displayed, the following might happen:\n\n- If the user types another key or changes the query in any way, the preceding steps are repeated and the suggestion list is updated.\n- If the user executes the search, the suggestions are ignored and the search is delivered to your searchable activity using the normal `ACTION_SEARCH` intent.\n- If the user selects a suggestion, an `ACTION_SEARCH` intent is delivered to your searchable activity using the suggested text as the query.\n\nThe `SearchRecentSuggestionsProvider` class that you extend for your content provider\nautomatically does the work in the preceding steps, so there's little code to write.\n\nCreate a content provider\n\nThe content provider you need for recent query suggestions is an implementation of\n`SearchRecentSuggestionsProvider`. This class does everything for you. You just need to\nwrite a class constructor that executes one line of code.\n\nFor example, here's a complete implementation of a content provider for recent query\nsuggestions: \n\nKotlin \n\n```kotlin\nclass MySuggestionProvider : SearchRecentSuggestionsProvider() {\n init {\n setupSuggestions(AUTHORITY, MODE)\n }\n\n companion object {\n const val AUTHORITY = \"com.example.MySuggestionProvider\"\n const val MODE: Int = SearchRecentSuggestionsProvider.DATABASE_MODE_QUERIES\n }\n}\n```\n\nJava \n\n```java\npublic class MySuggestionProvider extends SearchRecentSuggestionsProvider {\n public final static String AUTHORITY = \"com.example.MySuggestionProvider\";\n public final static int MODE = DATABASE_MODE_QUERIES;\n\n public MySuggestionProvider() {\n setupSuggestions(AUTHORITY, MODE);\n }\n}\n```\n\nThe call to\n[setupSuggestions()](/reference/android/content/SearchRecentSuggestionsProvider#setupSuggestions(java.lang.String, int))\npasses the name of the search authority and a database mode. The search authority can be any unique\nstring, but the best practice is to use a fully qualified name for your content provider, such as\nthe package name followed by the provider's class name. For example,\n`\"com.example.MySuggestionProvider\"`.\n\nThe database mode must include\n[DATABASE_MODE_QUERIES](/reference/android/content/SearchRecentSuggestionsProvider#DATABASE_MODE_QUERIES)\nand can optionally include\n[DATABASE_MODE_2LINES](/reference/android/content/SearchRecentSuggestionsProvider#DATABASE_MODE_2LINES),\nwhich adds a column to the suggestions table so you can provide a second line of text with each\nsuggestion. If you want to provide two lines in each suggestion, see the following example: \n\nKotlin \n\n```kotlin\nconst val MODE: Int = DATABASE_MODE_QUERIES or DATABASE_MODE_2LINES\n```\n\nJava \n\n```java\npublic final static int MODE = DATABASE_MODE_QUERIES | DATABASE_MODE_2LINES;\n```\n\nDeclare the content provider in your application manifest with the same authority string used in\nyour `SearchRecentSuggestionsProvider` class and in the searchable configuration. For\nexample: \n\n```xml\n\u003capplication\u003e\n \u003cprovider android:name=\".MySuggestionProvider\"\n android:authorities=\"com.example.MySuggestionProvider\" /\u003e\n ...\n\u003c/application\u003e\n```\n\nModify the searchable configuration\n\nTo configure the system to use your suggestions provider, add the\n`android:searchSuggestAuthority` and `android:searchSuggestSelection`\nattributes to the `\u003csearchable\u003e` element in your searchable configuration file. For\nexample: \n\n```xml\n\u003c?xml version=\"1.0\" encoding=\"utf-8\"?\u003e\n\u003csearchable xmlns:android=\"http://schemas.android.com/apk/res/android\"\n android:label=\"@string/app_label\"\n android:hint=\"@string/search_hint\"\n android:searchSuggestAuthority=\"com.example.MySuggestionProvider\"\n android:searchSuggestSelection=\" ?\" \u003e\n\u003c/searchable\u003e\n```\n\nThe value for `android:searchSuggestAuthority` must be a fully qualified name for your\ncontent provider that exactly matches the authority used in the content provider, such as\n`\"com.example.MySuggestionProvider\"` in the preceding examples.\n\nThe value for `android:searchSuggestSelection` must be a single question mark preceded\nby a space: `\" ?\"`. This is a placeholder for the SQLite selection argument, and it is\nautomatically replaced by the query text entered by the user.\n\nSave queries\n\nTo populate your collection of recent queries, add each query received by your searchable\nactivity to your `SearchRecentSuggestionsProvider`. To do this, create an instance of\n[SearchRecentSuggestions](/reference/android/provider/SearchRecentSuggestions)\nand call\n[saveRecentQuery()](/reference/android/provider/SearchRecentSuggestions#saveRecentQuery(java.lang.String, java.lang.String))\neach time your searchable activity receives a query. For example, here's how you can save the query\nduring your activity's\n[onCreate()](/reference/android/app/Activity#onCreate(android.os.Bundle))\nmethod: \n\nKotlin \n\n```kotlin\noverride fun onCreate(savedInstanceState: Bundle?) {\n super.onCreate(savedInstanceState)\n setContentView(R.layout.main)\n\n if (Intent.ACTION_SEARCH == intent.action) {\n intent.getStringExtra(SearchManager.QUERY)?.also { query -\u003e\n SearchRecentSuggestions(this, MySuggestionProvider.AUTHORITY, MySuggestionProvider.MODE)\n .saveRecentQuery(query, null)\n }\n }\n}\n```\n\nJava \n\n```java\n@Override\npublic void onCreate(Bundle savedInstanceState) {\n super.onCreate(savedInstanceState);\n setContentView(R.layout.main);\n\n Intent intent = getIntent();\n\n if (Intent.ACTION_SEARCH.equals(intent.getAction())) {\n String query = intent.getStringExtra(SearchManager.QUERY);\n SearchRecentSuggestions suggestions = new SearchRecentSuggestions(this,\n MySuggestionProvider.AUTHORITY, MySuggestionProvider.MODE);\n suggestions.saveRecentQuery(query, null);\n }\n}\n```\n\nThe `SearchRecentSuggestionsProvider` constructor requires the\nsame authority and database mode declared by your content provider.\n\nThe `saveRecentQuery()` method takes the search query string as the first parameter\nand, optionally, a second string to include as the second line of the suggestion or null. The second\nparameter is only used if you enable two-line mode for the search suggestions with\n`DATABASE_MODE_2LINES`. If you enable two-line mode, then the query text matches against\nthe second line when the system looks for matching suggestions.\n\nClear the suggestion data\n\nTo protect the user's privacy, always provide a way for the user to clear the recent query\nsuggestions. To clear the query history, call\n[clearHistory()](/reference/android/provider/SearchRecentSuggestions#clearHistory()).\nFor example: \n\nKotlin \n\n```kotlin\nSearchRecentSuggestions(this, HelloSuggestionsProvider.AUTHORITY, HelloSuggestionsProvider.MODE)\n .clearHistory()\n```\n\nJava \n\n```java\nSearchRecentSuggestions suggestions = new SearchRecentSuggestions(this,\n HelloSuggestionProvider.AUTHORITY, HelloSuggestionProvider.MODE);\nsuggestions.clearHistory();\n```\n\nExecute this from your choice of a \"Clear Search History\" menu item, preference item, or button.\nProvide a confirmation dialog to verify that the user wants to delete their search history."]]