Android开发指南(42) —— Adding Custom Suggestions
前言
本章内容为 Android开发者指南的 Framework Topics/Search/Adding Custom Suggestions章节,译为"添加自定义建议项",版本为Android 4.0 r1,翻译来自:"呆呆大虾",欢迎访问他的微博:"http://weibo.com/popapa",再次感谢"呆呆大虾" !期待你一起参与翻译Android的相关资料,联系我over140@gmail.com。
添加自定义建议项
译者署名: 呆呆大虾
译者微博: http://weibo.com/popapa
版本:Android 4.0 r1
原文
http://developer.android.com/guide/topics/search/adding-custom-suggestions.html
在本文中
关键类
SearchRecentSuggestionsProvider
相关示例
参阅
利用Android的搜索对话框或搜索widget,可以提供自定义搜索建议项,它的数据来源于应用程序自身。比如,假设应用程序是一个字典应用,可以把字典中最匹配已录入文本的单词作为建议项。由于能有效预测用户所查文本并能让用户直接获得字典中的释义,这种建议项是最有价值的。图1展示了使用自定义建议项的搜索对话框示例:
图1. 使用自定义对话框的搜索对话框截屏
一旦提供了自定义建议项,就可以同时让它应用于系统级的“快速搜索框”,从应用程序之外访问搜索内容。
在添加自定义建议项之前,需要先在应用程序中实现一个Android搜索对话框或搜索widget。如果还没有的话,请参阅创建搜索界面。
如果用户选中了某个自定义建议项,Android系统将向搜索activity发送一个Intent。标准的搜索请求将会发送一个附带ACTION_SEARCH action的intent,不过仍可让自定义建议项使用ACTION_VIEW(或者任何其它action),并放入相应的选中建议项数据。接着上面的字典应用示例,用户选中一个建议项时,应用程序可以立即显示单词的释义,而不是去字典检索匹配项。
为了提供自定义建议项功能,请按以下步骤操作:
· 实现一个基本的搜索activity,如创建搜索界面所述。
· 修改搜索配置文件中有关content provider的信息,用于提供自定义建议项的数据。
· 建立存放建议项的数据表(比如在SQLiteDatabase库中),根据所需数据列定义表结构。
· 创建访问建议项数据表的Content Provider,并在manifest文件中声明provider。
· 声明Intent的类型,用户选中某个建议项时可用于发送数据(包括自定义action和自定义数据)。
当搜索对话框显示出来时,Android系统同时也会显示搜索建议项。需要提供的只是系统能从中读取建议项的content provider。如果对创建content provider还不很熟悉,请先阅读Content Providers开发者指南再往下继续吧。
一旦系统识别出activity支持搜索功能且已提供搜索建议项,用户键入搜索请求时会执行以下步骤:
1. 系统读取搜索请求文本(录入了多少就读取多少),并在存放建议项的content provider中进行检索。
2. content provider返回一个Cursor,它指向匹配搜索文本的全部建议项。
3. 系统显示该Cursor提供的建议项列表。
显示完毕,将发生以下事情:
· 如果用户键入其它字符,或者以其它任何方式修改了请求文本,则上述步骤会重复执行,建议项列表将同步更新。
· 如果用户执行了搜索,建议项将被忽略,搜索文本将用正常的ACTION_SEARCH intent发送给搜索activity。
· 如果用户选中了某个建议项,带有自定义action和自定义数据的intent将会发送给搜索activity,应用程序可以打开建议项内容。
要加入对自定义建议项的支持,请在搜索配置文件的<searchable>元素中添加android:searchSuggestAuthority属性。例如:
<?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的相关知识,这在Content Provider开发者指南中描述。自定义建议项所需的content provider绝大部分都与其它content provider相同。不过,Cursor中对应每个建议项的数据行都必须包含系统可解析的数据列,用于组织建议项数据。
用户开始在搜索对话框或搜索widget里输入文本时,每键入一个字符,系统都将调用一次query(),并在content provider中检索建议项。在query()中,必须实现对content provider建议项数据的检索,并返回一个指向最佳建议项数据行的Cursor。
关于为自定义建议项创建content provider的详情,将在以下章节讨论:
系统如何向content provider发送请求及如何处理。
如何定义数据列,系统用于在每次搜索时返回Cursor 。
当系统向content provider发送建议项检索请求时,将会调用content provider的query()方法。必须在该方法中实现搜索建议项数据并返回指向最匹配建议项的Cursor。
以下是系统传给query()方法的所有参数(按照调用顺序排列):
uri
通常是content Uri,格式如下:
content://your.authority/optional.suggest.path/SUGGEST_URI_PATH_QUERY
系统的默认行为是传递URI并后跟搜索请求文本。例如:
content://your.authority/optional.suggest.path/SUGGEST_URI_PATH_QUERY/puppies
末尾的请求文本是用URI 编码规则编码过的,因此可能要在执行搜索前进行解码。
仅当搜索配置文件中用android:searchSuggestPath属性设置了路径时,URI中才要包含optional.suggest.path部分。只有多个搜索activity需共用同一个content provider时,才需要用到该配置。在这种情况下,需要解析建议项请求的来源。
注意:SUGGEST_URI_PATH_QUERY 并不属于URI的一部分,而应是用于指向此路径的常量。
projection
总为null
selection
该值由搜索配置文件中的android:searchSuggestSelection属性提供,如果未声明android:searchSuggestSelection属性则为null。更多使用信息请参见下文读取请求 。
selectionArgs
如果已在搜索配置文件中声明了android:searchSuggestSelection属性,那么数组的第一个(也只有一个)元素包含了搜索请求。如果未声明android:searchSuggestSelection,则本参数将为null。更多使用信息请参见下文读取请求 。
sortOrder
总为null。
系统可以用两种方式发送搜索请求文本。默认的方式是作为content URI路径的末尾部分(last segment)在uri参数中传递。不过,假如在搜索配置文件的android:searchSuggestSelection属性中包含了选项值,那么请求文本将作为字符串数组selectionArgs的第一个元素传递。这两种方式将在下文中一起讨论。
读取Uri中的搜索请求
默认情况下,请求文本是附加在uri参数(Uri对象)的末尾的。这时只要简单地用getLastPathSegment()即可读取请求文本了。例如:
String query = uri.getLastPathSegment().toLowerCase();
这将返回Uri的末尾部分(last segment),也就是用户录入的请求文本。
读取selection参数中的搜索请求
与URI不同,还可以采用更智能的方式,query()方法能够接收执行搜索所需的任何信息,selection和selectionArgs属性也能够传递合适的值。这种情况下,只要把SQLite查询语句作为android:searchSuggestSelection属性加入到搜索配置文件中去即可。在查询语句中,问号用作占位符,代表实际的查询请求。系统将用该查询语句作为selection参数,搜索请求作为selectionArgs数组的第一个元素,对query()进行调用。
以下是如何定义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的action。这将在后续章节为建议项声明Intent讨论。
提示:如果不需要在android:searchSuggestSelection属性中定义查询语句,但还要在selectionArgs参数中接收请求文本,则只要简单地把android:searchSuggestSelection属性赋成非空值即可。这将导致请求文本传递给selectionArgs,并且selection参数可被忽略。这样就可以不用定义实际的底层查询语句,content provider也不必再对其进行处理。
创建脱离数据库表的Cursor
如果搜索建议项不是按照系统要求的数据列存储在数据库表中的(比如SQLite表),那可以在每次发起请求时检索匹配的建议项数据并把它们格式化后保存到必要的表中。要实现这一目标,用系统要求的列名创建一个MatrixCursor,并用addRow(Object[])为每个建议项创建一行数据。Content Provider的query()方法将返回最终结果。
用Cursor向系统返回建议项时,每一行数据的列格式都是系统规定的。因此,无论是要把建议项数据存储在本地或Web服务器的SQLite数据库中,还是要以本地或web的其它格式存储,都必须把建议项格式化为表的一行数据,并用Cursor来表示。系统可以识别多个列,但有两列是必需的:
整数类型的行ID,唯一标识建议项。在ListView中显示建议项时,系统会用到该值。
代表建议项的字符串。
以下各列是可选的(大部分都会在后续章节中讨论):
字符串。如果Cursor包含该列,那么所有的建议项都提供两行模式。本列中的字符串将会显示为第二行,它的字体较小并显示主建议项文本的下方。也可以为null或空串,表示没有第二行文本。
drawable资源、content或文件URI串。如果Cursor包含该列,那么所有建议项都提供图标加文字模式,图标居左显示。该项可以为null或0,表示本行没有图标。
drawable资源、content或文件URI串。如果Cursor包含该列,那么所有建议项都提供图标加文本模式,图标居右显示。该项可以为null或0,表示本行没有图标。
intent action字符串。如果给定行中存在本列并且有值,那么此处定义的action将用于格式化建议项的intent。如果未提供本值,则会采用搜索配置文件中的android:searchSuggestIntentAction部分。如果所有建议项的action都是相同的,则更有效的方式是用android:searchSuggestIntentAction 指定action并省略本列。
数据URI字符串。如果给定行中存在本列并且有值,那么此值在格式化建议项时将作为intent的data部分来使用。如果未提供本值,则会采用搜索配置文件中的android:searchSuggestIntentData部分。如果前面两处都未提供值,则intent的data部分将为null。如果所有建议项的数据都是相同的,或者能用固定部分+ID来描述的,那么更有效的的方式是用android:searchSuggestIntentData指定,并省略本列。
URI路径字符串。如果给定行中存在本列并且有值,那么“/”加上本值将会添加到intent的data之后。仅当搜索配置文件中的android:searchSuggestIntentData属性已经设置了适当的基础数据字符串时,本项才会用到。
SUGGEST_COLUMN_INTENT_EXTRA_DATA
任何数据。如果给定行中存在本列并且有值,则表示格式化建议项intent时需要用到的extra data。如果未提供本值,则intent的extra data部分为null。本列允许建议项附带额外的数据,包含于intent的EXTRA_DATA_KEY键内。
如果给定行中存在本列并且有值,则为格式化建议项请求时需要用到的数据,包含于intent的QUERY键内。当建议项的action是ACTION_SEARCH时需要用到本值,否则则是可选列。
仅当向“快速搜索框”提供建议项时才会用到。本列标明了搜索建议项是否要存储为快捷方式,以及是否需要验证有效性。快捷方式一般是在用户从“快速搜索框”中点击建议项时生成。如果本ID缺失的话,结果将会存储为快捷方式且不再会更新。如果设置为SUGGEST_NEVER_MAKE_SHORTCUT,结果将不会存储为快捷方式。否则,快捷方式的ID将用于检查并更新建议项,这时还会用到SUGGEST_URI_PATH_SHORTCUT.。
SUGGEST_COLUMN_SPINNER_WHILE_REFRESHING
仅用于向“快速搜索框”提供建议项。本列指明当“快速搜索框”内建议项的快捷方式更新后,是否用进度滚轮(spinner)替代SUGGEST_COLUMN_ICON_2所设的图标。
以上各列中的一部分将会在后续章节中继续讨论。
声明建议项所需的Intent
当用户在搜索对话框或widget下方的列表内选中某个建议项时,系统会向搜索activity发送一个自定义的Intent。intent必须定义好action和data部分。
声明intent的action
自定义建议项最常用的intent action是ACTION_VIEW,适用于要启动某些应用的场合,类似单词的释义、联系人信息、网页等。当然,intent action也可以是其它任何action,甚至每个建议项的action都可以不同。
根据全部建议项是否共用同一种intent action,可以用以下两种方式来定义action:
a. 利用搜索配置文件的android:searchSuggestIntentAction 属性来定义所有建议项的action。
例如:
<?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>
b. 利用SUGGEST_COLUMN_INTENT_ACTION 列来定义单个建议项的action。
在建议项表中添加SUGGEST_COLUMN_INTENT_ACTION 列,并把每个建议项所用到的action放入其中(类似"android.Intent.action.VIEW")。
也可以混合使用以上两种方式。比如,可以包含android:searchSuggestIntentAction属性,为所有建议项提供默认action。然后在某些建议项的SUGGEST_COLUMN_INTENT_ACTION列中声明另一个action,以覆盖默认action。如果SUGGEST_COLUMN_INTENT_ACTION列中未包含值,将会采用android:searchSuggestIntentAction属性提供的intent。
注意:如果搜索配置文件中未包含android:searchSuggestIntentAction属性,则必须为每个建议项的SUGGEST_COLUMN_INTENT_ACTION列指定值,否则,intent将会启动失败。
声明intent的data
当用户选中一个建议项时,搜索activity将会接收到附带指定action(如上节所述)的intent,但该intent还必须同时携带data才行,这样搜索activity才能识别出选中的建议项。有一点尤为重要,data应该是能唯一标识每个建议项的信息,比如SQLite表中的行ID。在收到intent时,可以利用getData()或getDataString().来读取附带的data。
可以用以下两种方式来定义intent中的data:
a. 在建议项表的SUGGEST_COLUMN_INTENT_DATA列中为每个建议项都定义一个data。
在建议项表中包含SUGGEST_COLUMN_INTENT_DATA列,以便为每个intent 都提供必要的data信息,然后把每行的唯一信息填入。该列中的值将会原封不动地附加到intent 中。可以利用getData()或getDataString()来读取它们。
提示: 通常表的行ID最容易被用作Intent data,因为它总是唯一的。最简便的方式就是用SUGGEST_COLUMN_INTENT_DATA列名作为行ID的别名。具体示例请参阅支持检索的字典例程,其中SQLiteQueryBuilder创建了一个列名和别名的映射关系。
b. 把data URI分解为两部分:所有建议项公共的部分和每个建议项唯一的部分。把这两部分分别放入搜索配置文件的android:searchSuggestintentData属性和建议项表的SUGGEST_COLUMN_INTENT_DATA_ID 列中。
在搜索配置文件的android:searchSuggestIntentData属性中声明全部建议项公共的URI部分。例如:
<?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列中放入每个建议项的final path(唯一部分)。用户选中建议项后,系统会把android:searchSuggestIntentData中指定的字符串加上斜杠 ("/"),再加入各自SUGGEST_COLUMN_INTENT_DATA_ID列中的值,组成一个完整的content URI。然后就可以用getData()读取Uri 了。
如果需要在intent中表示更多信息,可以添加另一列SUGGEST_COLUMN_INTENT_EXTRA_DATA来存放与建议项相关的附加数据。在此列中存放的数据将被置于intent附带Bundle的EXTRA_DATA_KEY 部分中。
处理Intent
现在已经能利用自定义intent提供自定义的搜索建议项,用户选中某建议项时,需要用搜索activity来处理这些intent。在这之前,搜索activity已经对ACTION_SEARCH intent进行了处理。下面是如何在activity的onCreate()回调方法中处理intent的示例:
Intent intent = getIntent();
if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
// 处理正常的搜索请求
String query = intent.getStringExtra(SearchManager.QUERY);
doSearch(query);
} else if (Intent.ACTION_VIEW.equals(intent.getAction())) {
// 处理对建议项的点击操作(因为建议项都是使用ACTION_VIEW的)
Uri data = intent.getData();
showResult(data);
}
在上例中,intent action是ACTION_VIEW,并且通过组合android:searchSuggestIntentData字符串和SUGGEST_COLUMN_INTENT_DATA_ID列,数据已包含了指向建议项的完整URI。该URI传给本地的showResult()方法,对URI指定的建议项在content provider中执行查询。
注意:在Android manifest文件中,不需要对android:searchSuggestIntentAction属性或SUGGEST_COLUMN_INTENT_ACTION列设定的intent action添加intent 过滤器。系统将根据名称启动搜索activity并传递建议项的intent,因此activity不需要对可接受的action进行声明。
如果用户使用方向控制设备(比如轨迹球或d-pad)来浏览建议项列表,则默认情况下搜索请求文本不会被更新。不过可以暂时用当前焦点所在的建议项来改写用户请求文本,让它显示在搜索文本框中。这样就能让用户看到建议的请求文本(假如合适的话)并能在发送请求之前选中搜索框来编辑请求文本。
可以通过以下方式来改写搜索请求文本:
a. 在搜索配置文件中添加android:searchMode 属性,并赋值为"queryRewriteFromText" 。这种情况下,建议项表的SUGGEST_COLUMN_TEXT_1列中的内容将会用于改写请求文本。
b. 在搜索配置文件中添加android:searchMode 属性,并赋值为"queryRewriteFromData" 。这种情况下,建议项表的SUGGEST_COLUMN_INTENT_DATA列中的内容将会用于改写请求文本。这只适用于用户需要能看见URI或其它格式数据的场合,比如HTTP URL。内部的URI格式不应该使用这种方式来改写请求文本。
c. 在建议项表的SUGGEST_COLUMN_QUERY列内提供唯一的请求文本串。如果当前建议项的该列存在并且包含值,将被用于改写请求文本(并且覆盖上面的两种方式)。
向“快速搜索框”提供搜索建议项
一旦把应用程序配置成提供自定义搜索建议项的话,让它适用于全局访问的“快速搜索框”是很容易的,只要修改一下搜索配置文件,让其包含值为"true"的android:includeInGlobalSearch属性即可。
唯一要进行额外工作的情况,就是需要向content provider请求读权限的时候。这种情况下,需要添加<path-permission>元素,赋予“快速搜索框”对content provider的读权限。例如:
<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>
在上例中,provider先规定了对content的读和写权限。<path-permission>元素修改了这个规定,当存在"android.permission.GLOBAL_SEARCH"权限时,允许对路径前缀为"/search_suggest_query"的内容进行读取访问。这样就对“快速搜索框”赋予向content provider查询建议项的权限。
如果content provider未明确指定读权限,默认情况下“快速搜索框”是可以读取其中内容的。
即使已经把应用程序配置为向“快速搜索框”提供建议项,缺省情况下也不会真正生效。是否要在“快速搜索框”中包含应用程序所提供的建议项,是需要由用户选择的。为了启用应用程序提供的搜索建议项,必须打开“可搜索的项”(在“搜索”的“搜索设置”菜单中)并指定应用程序为可搜索项。
每个可用于“快速搜索框”的应用程序都会在“可搜索的项”设置页面中有一个条目。条目中包含了应用程序名称和简要描述信息,这些信息描述了应用程序能够搜索并提交给“快速搜索框”作为建议项的内容。通过在搜索配置文件中添加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的值应该尽可能地简明扼要,能表明可搜索的内容即可。比如:音乐程序可以用“艺术家、专辑和音轨”,记事本程序则可用“已保存的记录”。提供这些描述信息是非常重要的,这样用户就知道有哪些建议项可用。当android:includeInGlobalSearch的值为“true”时,应该确保能包含该属性。
请记住,用户必须访问设置菜单并为应用程序启用搜索建议项,然后搜索建议项才能出现在“快速搜索框中”。因此,假如搜索是应用程序的重要特性之一,则可能需要考虑通过某种方式提醒用户进行设置——可以在第一次启动应用程序时提醒一下,告诉用户如何启用“快速搜索框”中的搜索建议项。
管理“快速搜索框”建议项的快捷方式
用户在“快速搜索框”选中的建议项可以自动变为快捷方式。这些快捷方式是系统从content provider中复制过来的建议项,这样就能快速访问建议项,而不必再次查询content provider。
默认情况下,“快速搜索框”所读取的全部建议项都能启用快捷方式。如果建议项数据经过一段时间后发生了变化,可以发起刷新快捷方式的请求。举例来说,如果建议项指向动态数据,比如联系人的在线状态,那就应该在显示给用户的时候刷新建议项的快捷方式。只要在建议项表中包含SUGGEST_COLUMN_SHORTCUT_ID列即可实现这一目标。利用该列可以把每个建议项的快捷方式配置为以下动作:
a. 让“快速搜索框”重新查询content provider ,以获取建议项快捷方式的最新版本。
在SUGGEST_COLUMN_SHORTCUT_ID列中指定一个值,每次显示快捷方式时都会去查询建议项的最新版本。刷新请求返回后,快捷方式将会与最新数据一起显示出来,这时建议项已经用最新信息刷新。刷新请求利用SUGGEST_URI_PATH_SHORTCUT的URI路径发送至content provider,(而不是SUGGEST_URI_PATH_QUERY)。
返回的Cursor应该包含数据列与原来相同的一条建议项,或者为空——表示快捷方式不可用了(这时,建议项将会消失,快捷方式也会被删除)。
如果建议项指向数据的刷新可能需要耗费很长时间,比如基于网络的的刷新,则可以在建议项表中添加SUGGEST_COLUMN_SPINNER_WHILE_REFRESHING列并赋值为“true”,这样刷新时就会显示为进度滚轮图标。除“true”以外的任何值都不会显示进度滚轮。
b. 完全阻止把建议项复制为快捷方式。
把SUGGEST_COLUMN_SHORTCUT_ID列赋值为SUGGEST_NEVER_MAKE_SHORTCUT。这时,建议项就不会复制为快捷方式了。仅当确实不想让以前复制过的建议项显示出来,才会这么做。(如果在该列中提供正常的值并重新调用的话,建议项快捷方式将在刷新请求返回后才显示出来。)
c. 使用默认的快捷方式动作。
建议项不会变化且可以保存为快捷方式,则保持SUGGEST_COLUMN_SHORTCUT_ID列为空即可。
如果建议项全都不会发生变化,那就根本不需要SUGGEST_COLUMN_SHORTCUT_ID列。
注意:上述值只是被视作应用程序的需求而已,“快速搜索框”有权最终确定是否建立建议项的快捷方式,它并不保证指定的建议项快捷方式动作一定会实现。
关于“快速搜索框”建议项的级别
一旦应用程序的搜索建议项能够用于“快速搜索框”,则“快速搜索框”将会对其评级,并确定如何根据请求把建议项展现给用户。这可能会依赖于有多少其它应用程序也对该请求返回了结果,也可能会根据用户选中哪个应用程序来返回结果的频度。建议项的评级并没有固定的规则,对于给定的搜索请求是否显示应用程序的建议项也是不能保证的。可以大致这么认为,高质量的结果会增加建议项显示在显著位置的可能性,而低质的建议项则更可能会获得较低的级别或者干脆就不会显示。
关于自定义搜索建议项的完整范例,请参阅支持检索的字典例程。