天天看点

android对外提供全局搜索功能

一、本地搜索介绍  

1. 全局搜索(QuickSearchBox)介绍:

搜索是Android上的核心用户功能。用户应该能够搜索他们可用的任何数据,无论内容是位于设备还是Internet上。为了帮助用户创建一致的搜索体验,Android提供了一个搜索框架,可帮助您实现对您的应用程序的搜索,当用户单击某一个搜索出来的结果项就会打开相应的应用程序,显示搜索結果的详细信息。

2. 全局搜索(QuickSearchBox)技术架构:

Android系统的全局搜索由搜索管理器(SearchManager),全局搜索AppWidget,全局搜索应用,支持全局搜索的应用程序(联系人,音乐,浏览器等)四大部分组成:

(1)framework层的搜索管理器(SearchManager):主要功能是对Android系统全局搜索提供支持,当Android系统启动完成后会发出系统启动完成(BOOT_COMPLETED)广播,SearchManager接收到此广播后会通过PackageManager搜索系统中支持全局搜索的应用程序(应用程序如何支持全局搜索以后的文章会介绍),这此支持全局搜索的应用我们称为搜索源,SearchManager解析搜索源的配置信息并将这些配置信息封装成对象保存在List列表中供全局搜索应用程序使用。

(2)搜索框架提供两种搜索输入模式:屏幕顶部的搜索对话框或可以嵌入到活动布局中的搜索小部件(SearchView)。无论哪种情况,Android系统将通过向执行搜索的特定活动提供搜索查询来协助您的搜索实现。您还可以启用搜索对话框或窗口小部件来提供用户类型的搜索建议。

(3)支持全局搜索的应用程序:每一个支持全局搜索的应用程序都需要实现一个ContentProvider,通过这个ContentProvider向外提供数据,全局搜索应用(QuickSearchBox)会调用这些ContentProvider获取数据。

3. 搜索执行全过程:

Android系统启动完成,发出系统启动完成(BOOT_COMPLETED)广播,搜索管理器(SearchManager + Service)接收到此广播后会通过PackageManager搜索系统中支持全局搜索的应用程序,并解析这些应用程序的配置信息(配置信息中包括请求支持全局搜索应用的ContentProvider的authority及其它配置信息,这些配置信息由应用的开发人员配置),封装成对象保存到List中,当用户单击Launcher中的全局搜索的AppWidget组件后打开全局搜索应用(QuickSearchBox)的主界面,在界面中的搜索输入框中输入搜索内容,这时全局搜索应用(QuickSearchBox)会从搜索管理器(SearchManager + Service)中取出全部支持全局搜索的应用程序List,并解析它们的配置信息,根据配置信息(authority等)组将成URI,要据URI调用支持全局搜索应用的ContentProvider,ContentProvider的查询方法会根据URI搜索数据,并将搜索到的結果以Cursor型式返回,全局搜索应用会解决这些数据,并以List的形式显示到UI界面中。

二、APP配置全局搜索信息 :GoogleAPI:https://developer.android.com/guide/topics/search/searchable-config.html

1)应用程序支持全局搜索,向搜索程序提供搜索结果,成为搜索源,搜索应用程序可以通过解析配置信息组拼成URI请求应用的ContentProvider获取搜索結果

定义Android系统使用的所有搜索配置,以提供辅助搜索如下:

配置activity

<application ... >
    <activity android:name=".SearchableActivity" >
       
<!-- Receives the search request. -->
<intent-filter>
 <action android:name="android.intent.action.SEARCH" />
 <!-- No category needed, because the Intent will specify this class component-->
</intent-filter>

<!-- Points to searchable meta data. -->
<meta-data android:name="android.app.searchable"
 android:resource="@xml/searchable" />   
 </activity>
    ...
       
<!-- Points to searchable activity so the whole app can invoke search. -->
<meta-data android:name="android.app.default_searchable"
 android:value=".SearchableDictionary" /> 
</application>      

在应用程序的res目录中新建xml目录,在xml目录中新建searchable.xml文件:

<searchable xmlns:android="http://schemas.android.com/apk/res/android"
 android:label="@string/search_label"
 android:hint="@string/search_hint"
 android:searchSettingsDescription="@string/settings_description"
 android:searchSuggestAuthority="com.example.android.searchabledict.DictionaryProvider" //和提供搜索功能的Contentprovider:autherity一致
 android:searchSuggestIntentAction="android.intent.action.VIEW" // String字符串,单击搜索結果列表中的某一项时,发出Intent对象中的Action
 /也可以在数据库中加入SUGGEST_COLUMN_INTENT_ACTION字段绑定action。
 android:searchSuggestIntentData="content://com.example.android.searchabledict.DictionaryProvider/dictionary" // 配置的URI信息
 android:searchSuggestSelection=" ?" // 定义搜索时参数的占位符
 android:searchSuggestThreshold="1" // int值,输入多少个字符后开始搜索
 android:includeInGlobalSearch="true" // 是否将内容加入android的全局搜索。true,加入
 >
 </searchable>      

Android:label 标签详解:您的应用程序的名称。它应该与应用于您的<activity>或<application> manifest元素的android:label属性的名称相同。当您将android:includeInGlobalSearch设置为“true”时,此标签仅对用户可见,在这种情况下,此标签用于将您的应用程序标识为系统搜索设置中的可搜索项目。

2)在AndroidManifest.xml文件中配置ContentProvider:

<!-- Provides search suggestions for words and their definitions. -->
<provider android:name=".DictionaryProvider"
 android:exported="true"
 android:authorities="com.example.android.searchabledict.DictionaryProvider" // 和searchable.xml中的authority相对应
 />      

在ContentProvider的onCreate()方法中完成SQLiteOpenHelper数据库创建和初始化数据的操作,启动异步线程加载本地数据到数据库中。

在QuickSearchBox中通过ContentResolver调用内容提供者的query()方法进行信息搜索,应用程序必须实

现这个方法并且返回搜索到的Cursor对象。

@Override

public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,

 String sortOrder)

第一个参数(uri):

content://authority/suggestion.path/search_suggest_query/queryStr?limit=50

content://:标准前缀,用来说明一个Content Provider控制这些数据;

authority:对应searchable.xml文件中的android:searchSuggestAuthority属性,用于唯一标识这个ContentProvider,外部调用者可以根据这个标识来找到它。对于第三方应用程序,为了保证URI标识的唯一性,它必须是一个完整的、小写的类名。这个标识在元素的authorities属性中说明,一般是定义该ContentProvider的包.类的名称

suggestion.path:对应searchable.xml文件中的android:searchSuggestPath属性,就是你要操作的数据库中表的名字,或者你也可以自己定义,记得在使用的时候保持一致就可以了;

search_suggest_query : 固定字符串。

queryStr: 查询字符串。

limit :  查询条数。

第二个参数 projection:要放入光标列的列表,Null表示所有所有列

第三个参数:selection:过滤行时应用的选择条件,对应searchable.xml文件中android:searchSuggestSelection属性,ContentProvider的query方法将会调用SQLite数据,组成SQL语句中where后面的条件

第四个参数:您可以包含选择"?s"来替代来自selectionArgs的值,以便它们出现在选择中。 这些值将被绑定为字符串。多个判断条件。

第五个参数:sortOrder:游标中的行应如何排序,Null则提供者可以自由定义排序顺序

API提供的数据库关键字SearchManager类中:https://developer.android.com/reference/android/app/SearchManager.html

String

SUGGEST_COLUMN_AUDIO_CHANNEL_CONFIG

建议光标的列名。 可选的。 如果您的内容包含音频,则应提供此列指定音频通道配置。 列中的数据是格式如“channels.subchannels”(如“1.0”或“5.1”)的字符串。

String

SUGGEST_COLUMN_CONTENT_TYPE

建议光标的列名。 可选的。 如果您的内容是媒体类型,您应该提供此列,以便搜索应用可以了解有关您的内容的更多信息。 列中的数据必须指定内容的MIME类型。

String

SUGGEST_COLUMN_DURATION

建议光标的列名。 可选的。 如果您的内容是视频或音频,则应提供此列以毫秒为单位指定内容的持续时间。 列中的数据是长类型的。

String

SUGGEST_COLUMN_FLAGS

建议光标的列名。 可选的。 此列用于指定每个项目的附加标志。 可以指定多个标志。

必须是FLAG_QUERY_REFINEMENT中的一个或0表示没有标志。

String

SUGGEST_COLUMN_FORMAT

建议光标的列名。 未使用 - 可以为null或列可以省略

String

SUGGEST_COLUMN_ICON_1

建议光标的列名。 可选的。 如果您的光标包含此列,则所有建议将以包含两个小图标的空间的格式提供,其中一个位于左侧,另一个在每个建议的右侧。 列中的数据必须是可绘制的资源ID,或以下列格式之一的URI:

String

SUGGEST_COLUMN_ICON_2

建议光标的列名。 可选的。 如果您的光标包含此列,则所有建议将以包含两个小图标的空间的格式提供,其中一个位于左侧,另一个在每个建议的右侧。 列中的数据必须是可绘制的资源ID,或以下列格式之一的URI:

String

SUGGEST_COLUMN_INTENT_ACTION

建议光标的列名。 可选的。 如果此列存在,并且此元素存在于给定行,则这是在形成建议意图时将使用的操作。 如果未提供该元素,则该操作将从您的XML元数据中的android:searchSuggestIntentAction字段获取。 这些建议中至少有一个必须存在以产生意图。 注意:如果您的操作对于所有建议相同,则使用XML元数据指定它并从光标中省略更为有效。

String

SUGGEST_COLUMN_INTENT_DATA

建议光标的列名。 可选的。 如果此列存在,并且此元素存在于给定行,则这是在形成建议意图时将使用的数据。 如果未提供元素,则数据将从您的XML元数据中的android:searchSuggestIntentData字段中获取。 如果没有提供任何源,则Intent的数据字段将为空。 注意:如果您的数据对于所有建议相同,或者可以使用常量部分和特定ID进行描述,则使用XML元数据指定它并从光标中省略更为有效。

String

SUGGEST_COLUMN_INTENT_DATA_ID

建议光标的列名。 可选的。 如果此列存在且该元素存在于给定行,则“/”将该值附加到Intent中的数据字段中。 只有当数据字段已经被设置为适当的基本字符串时,才应该使用。

String

SUGGEST_COLUMN_INTENT_EXTRA_DATA

建议光标的列名。 可选的。 如果此列存在,并且此元素存在于给定行,则这是在形成建议意图时将使用的数据。 如果没有提供,则意图的额外数据字段将为空。 这个列允许提供额外的任意数据的建议,这些数据将作为EXTRA_DATA_KEY的关键字额外提供。

String

SUGGEST_COLUMN_IS_LIVE

建议光标的列名。 可选的。 如果您的内容是媒体类型,您应该提供此列,以指定您的内容是否是实况媒体,如直播视频或现场音频。 列中的值为整型,值为0表示非实时内容,或1表示实时内容。

String

SUGGEST_COLUMN_LAST_ACCESS_HINT

建议光标的列名。 可选的。 当在结果提供应用程序中上次访问项目时,此列可用于指定System.currentTImeMillis()(UTC的停留时间)中的时间。 如果设置,这可以用于显示最近使用的项目。

String

SUGGEST_COLUMN_PRODUCTION_YEAR

建议光标的列名。 可选的。 如果您的内容是视频或音频,并且具有已知的制作年份,则应提供此列以指定内容的制作年份。 列中的数据是整数类型。

String

SUGGEST_COLUMN_PURCHASE_PRICE

建议光标的列名。 可选的。 如果您的内容是可购买的,您应该提供此列以指定您的内容的购买价格的可显示字符串表示,包括货币和金额。 如果它是免费的,你应该提供本地化的字符串来指定它是免费的。 如果内容不适用于购买,则可以省略此列。

String

SUGGEST_COLUMN_QUERY

建议光标的列名。 如果操作为ACTION_SEARCH,则为必需,否则为可选项。 如果此列存在,并且此元素存在于给定行,则这是在形成建议的查询时将使用的数据。

String

SUGGEST_COLUMN_RATING_SCORE

建议光标的列名。 可选的。 如果您的内容有评分,您应该提供此列来指定内容的评分。 列中的数据为浮动类型。 查看每个评分风格的有效评分分数。

String

SUGGEST_COLUMN_RATING_STYLE

建议光标的列名。 可选的。 如果您的内容有评分,您应该提供此列以指定内容的评分风格。 列中的数据必须是“评级”中指定的常量值之一

String

SUGGEST_COLUMN_RENTAL_PRICE

建议光标的列名。 可选的。 如果您的内容可以租用,您应该提供此列,以指定您的内容的租金价格的可显示字符串表示,包括货币和金额。 如果它是免费的,你应该提供本地化的字符串来指定它是免费的。 如果内容不适用于租金,则可以省略此列。

String

SUGGEST_COLUMN_RESULT_CARD_IMAGE

建议光标的列名。 可选的。 如果您的光标包含此列,则在形成建议时将显示图像。 图像的建议尺寸为肖像模式为270x400像素,横向模式为400x225像素。 列中的数据必须是可绘制的资源ID,或以下列格式之一的URI:

String

SUGGEST_COLUMN_SHORTCUT_ID

建议光标的列名。 可选的。 该列用于指示搜索建议是否应作为快捷方式存储,以及是否应该刷新。 如果缺少,结果将被存储为快捷方式,从不验证。 如果设置为SUGGEST_NEVER_MAKE_SHORTCUT,则不会将结果存储为快捷方式。 否则,快捷方式ID将用于使用SUGGEST_URI_PATH_SHORTCUT来检查最新的建议。

String

SUGGEST_COLUMN_SPINNER_WHILE_REFRESHING

建议光标的列名。 可选的。 此列用于指定在刷新此建议的快捷方式时,显示微调框代替图标2。

String

SUGGEST_COLUMN_TEXT_1

建议光标的列名。 需要。 这是提交给用户的主要文本行。

String

SUGGEST_COLUMN_TEXT_2

建议光标的列名。 可选的。 如果您的光标包含此列,则所有建议将以两行格式提供。 第二行文字的外观要小得多。

String

SUGGEST_COLUMN_TEXT_2_URL

建议光标的列名。 可选的。 这是一个显示为第二行文字而不是SUGGEST_COLUMN_TEXT_2的网址。 这是一个单独的列,以便搜索UI知道将文本显示为URL,例如。 通过使用不同的颜色。 如果此列不存在,或者值为null,则使用SUGGEST_COLUMN_TEXT_2。

String

SUGGEST_COLUMN_VIDEO_HEIGHT

建议光标的列名。 可选的。 如果您的内容是视频,则应提供此列以指定水平线数。 列中的数据是整数类型。

String

SUGGEST_COLUMN_VIDEO_WIDTH

建议光标的列名。 可选的。 如果您的内容是视频,则应提供此列以指定垂直线数。 列中的数据是整数类型。

常用关键字:

SUGGEST_COLUMN_TEXT_1

SUGGEST_COLUMN_TEXT_2

SUGGEST_COLUMN_ICON_1

SUGGEST_COLUMN_ICON_2

SUGGEST_COLUMN_TEXT_2_URL,

验证中。。

SUGGEST_COLUMN_RESULT_CARD_IMAGE 显示建议为image

SUGGEST_COLUMN_IS_LIVE 显示建议为媒体类型(视频/音频)

android对外提供全局搜索功能

SUGGEST_COLUMN_INTENT_ACTION

:建议光标的列名。可选的。如果此列存在,并且此元素存在于给定行,则这是在形成建议意图时将使用的操作。如果未提供该元素,则该操作将从您的XML元数据中的android:searchSuggestIntentAction字段获取。这些建议中至少有一个必须存在以产生意图。注意:如果您的操作对于所有建议相同,则使用XML元数据指定它并从光标中省略更为有效。

CURSOR_EXTRA_KEY_IN_PROGRESS

:建议提供者在getExtras()中返回的Boolean额外数据键,表示搜索尚未完成。 搜索用户界面可以使用它来指示正在进行搜索。 建议提供者可以通过这种方式返回部分结果,并在更多结果可用时向游标发送更改通知。

QUERY

:意图额外的数据密钥:使用此键与content.Intent.getStringExtra()从Intent.ACTION_SEARCH获取查询字符串。