為Android應(yīng)用添加搜索功能
譯文【51CTO譯文】在本系列共兩篇的教程中,將指導(dǎo)開發(fā)者如何利用Android的 搜索框架進行搜索功能的開發(fā)。在***篇就是本文中,將讓開發(fā)者了解Android的搜索框架,在第二篇教程中,將展示關(guān)于搜索建議和全局搜索整合到app應(yīng)用中去。
本地搜索 VS 全局搜索
我們先來看下在Android的搜索框架中,本地搜索和全局搜索兩個概念和它們之間的區(qū)別。
本地搜索:
指的是由app應(yīng)用本身提供的搜索功能,這對任何的app應(yīng)用都應(yīng)該***提供這樣的功能,比如一個食譜的app應(yīng)用應(yīng)該能讓用戶在這個應(yīng)用中根據(jù)關(guān)鍵字去進行搜索。本地搜索是在某一app內(nèi)進行的,不同的app應(yīng)用之間不能進行互相的搜索。
全局搜索
另一方面,全局搜索能讓用戶在主屏幕中通過快速搜索框根據(jù)關(guān)鍵字,在各app中展開相關(guān)的搜索,Android使用了多種數(shù)據(jù)源來為全局搜索提供幫助。比如下圖中,展示了在Android平板系統(tǒng)中,可以看到左邊部分是用戶輸入的搜索內(nèi)容,使用的是google的搜索,檢索出來的結(jié)果中,甚至能包含用戶機器上安裝的app應(yīng)用的標題,它們展示在右邊。
用戶對于全局搜索的體驗是跟本地搜索的是完全不同的。全局搜索的功能中,可以使用google進行搜索,搜索的范圍包括安裝到本地機器的app應(yīng)用,通訊錄等,甚至包括某些允許使用全局搜索的app的檢索結(jié)果。下圖中,展示的是可以進行全局搜索的數(shù)據(jù)來源,可以看到包括了web,各app應(yīng)用,音樂,消息和通訊錄。
可以看到,一個好的app應(yīng)用,應(yīng)該盡可能在上圖中出現(xiàn),這樣用戶在搜索時,才會優(yōu)先考慮對其進行檢索,更方便用戶的操作。在本教程的第2篇中,將更詳細指導(dǎo)用戶如何去進行全局檢索。
在APP應(yīng)用中啟用搜索
在app應(yīng)用中,至少要執(zhí)行如下的三個步驟,才能讓app應(yīng)用能夠進行檢索。如果要提供搜索建議,還需要執(zhí)行第4步:
- 編寫搜索配置的XML文件
- 編寫搜索的activity類
- 在Android的manifest.xml文件中,對兩面兩個步驟的工作進行配置。
- 如果要使用搜索建議,則需要增加一個contentprovider。
配置搜索的XML配置文件
首先看下如何配置搜索的XML配置文件。先命名配置文件名稱為searchable.xml,保存在res/xml文件夾中。然后需要設(shè)置搜索框的文本,并且應(yīng)該增加一個hint的提示文本信息,如下代碼所示:
- <searchable
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:label="@string/search_label">
- android:hint="@string/search_hint"
- </searchable>
關(guān)于搜索配置文件有很多的配置選項,建議參考Android的手冊可以獲得更多:
http://developer.android.com/guide/topics/search/searchable-config.html。
增加搜索的Activity
當用戶進行搜索時,Android調(diào)用activity進行搜索,代碼如下:
- publicclass SampleSearchActivity extends ListActivity {
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- handleIntent(getIntent());
- }
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- handleIntent(getIntent());
- }
- public void onNewIntent(Intent intent) {
- setIntent(intent);
- handleIntent(intent);
- }
- public void onListItemClick(ListView l,
- View v, int position, long id) {
- // 點每個搜索結(jié)果時的處理代碼
- }
- private void handleIntent(Intent intent) {
- if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
- String query =
- intent.getStringExtra(SearchManager.QUERY);
- doSearch(query);
- }
- }
- private void doSearch(String queryStr) {
- //執(zhí)行真正的查詢結(jié)果處理
- }
- }
在上面的代碼中,在handleIntent方法中,當按下搜索按鈕,系統(tǒng)就會自動發(fā)送Intent,action是Intent.ACTION_SEARCH,然后通過intent.getStringExtra(SearchManager.QUERY);獲得要搜索的字符串。
其中為什么要包含onNewIntent()方法呢?主要是因為Android的back后退機制。Android會默認把每一個新的activity放到activity棧的頂部。如果用戶點了后退鍵,則會關(guān)閉棧頂部的activity。嘗試考慮一種情況,用戶搜索一個內(nèi)容并且系統(tǒng)列出了結(jié)果,如果用戶發(fā)現(xiàn)結(jié)果不是他所要的,或者希望重新檢索,則會重新點擊搜索按鍵,這樣將會產(chǎn)生一個新的搜索activity的實例,在activity棧中就會有兩個搜索的activity,這是開發(fā)者并不期待的,所以,需要將這個搜索的activity聲明為singleTop類型的activity,這樣的話,無論用戶按返回鍵還是盡心個多次的搜索,在acitivty棧中始終保持的是一個搜索activity的實例。因為當activity被設(shè)置為singleTop的加載模式時,如果堆棧的頂部已經(jīng)存在了該Activity,那么,它便不會重新創(chuàng)建,而是調(diào)用onNewIntent。如果,該Activity存在,但不是在頂部,那么該Activity依然要重新創(chuàng)建。
mainifest配置文件
接下來,需要對manifest配置文件進行配置,必須要對其中進行如下配置:
- 搜索的activity.
- 使用搜索的intent
- activity啟動模式
- searchable.xml中的元數(shù)據(jù)
- 更多的定義搜索的元數(shù)據(jù)
下面是典型的一個搜索的配置
- <application
- android:icon="@drawable/icon"
- android:label="@string/app_name"
- android:name=".YourApp" >
- <meta-data
- android:name="android.app.default_searchable"
- android:value=".YourSearchActivity" />
- <activity
- android:label="@string/app_name"
- android:launchMode="singleTop"
- android:name=".YourSearchActivity" >
- <intent-filter >
- <action android:name="android.intent.action.SEARCH" />
- </intent-filter>
- <intent-filter >
- <action android:name="android.intent.action.VIEW" />
- </intent-filter>
- <meta-data
- android:name="android.app.searchable"
- android:resource="@xml/searchable" />
- </activity>
- </application>
在上面的典型配置中,要注意如下幾點:
1)由于當調(diào)用搜索activity時,Android調(diào)用的是android.intent.action.SEARCH作為搜索的intent,所以必須在intent-filter中包含android.intent.action.SEARCH。
2)在<meta-data>中,指出了searchable.xml的位置
3)同樣在<meta-data>中,通過:
- <meta-data
- android:name="android.app.default_searchable"
- android:value=".YourSearchActivity" />
指出了當執(zhí)行搜索的字符串提交時,將調(diào)用哪一個activity去進行處理。
自定義搜索
對于app應(yīng)用來說,***的還是能自定義搜索功能,并且能清晰告訴用戶:你的app應(yīng)用能支持搜索。
要注意的是,在Android的Honeycomb 和Ice Cream Sndewich版本中,已經(jīng)不再有一個搜索的按鈕了。取而代之的是在action bar中顯示搜索的按鈕。因此,一種很好的方式是通過在actionbar中同時加入搜索按鈕,好像如下圖,是在Android 2.2上運行的效果。
當用戶開始搜索時,在activity中要打開一個搜索的對話框,這可以通過調(diào)用onSearchRequested()實現(xiàn),這個是Android中Activity類的方法,并且會調(diào)用startsearch()方法,這個接下來會討論。
在搜索中加入指定數(shù)據(jù)
默認的搜索有時不能滿足需要,可能要需要使用全局搜索,也可能需要一些額外的數(shù)據(jù),在這個情況下,可以重寫onSearchRequestd()方法并且自己調(diào)用startSearch方法,其中startSearch的方法中定義的參數(shù)如下:
參數(shù) |
類型 |
含義 |
initialQuery |
string |
搜索框中默認的字符串 |
selectInitialQuery |
boolean |
這個標志表明搜索框中的內(nèi)容是否可以被選擇,如果設(shè)置為true,則會覆蓋initialQuery |
appSearchData |
Bundle |
其他傳遞到搜索activity中的數(shù)據(jù) |
globalSearch |
boolean |
決定是否使用全局搜索 |
在默認調(diào)用startSearch()方法時,會默認使用如下的值:null, false, null, false,其含義為只使用本地搜索,不附加任何的其他的值。
讓APP應(yīng)用支持語音搜索
如果讓APP應(yīng)用支持用戶使用語音進行搜索,那對用戶來說就更方便了!在Android中,這只需要增加一些代碼就可以實現(xiàn)了。下圖是當使用了語音設(shè)置后,Android會出現(xiàn)一個麥克風,讓用戶使用語音。
但要注意,不是所有的設(shè)備都支持語音搜索的,要使用語音搜索,需要設(shè)置配置選項如下:
- android:voiceSearchMode=
- "showVoiceSearchButton|launchRecognizer"
其中voiceSearchMode有兩個選項,showVoiceSearchButton和launchRecognizer,其中showVoiceSearchButton是必須的,建議使用launchRecognizer這個選項。而另外一個重要的選項是android:voiceLanguageModel,它有兩個選項分別是:web_search和free_form,***建議用戶使用web_search,意思是使用語言模型在Web上搜索,這很適合用戶不是很準確朗讀短語句子的情景,而free_form選項則適合比如在一些應(yīng)用中如SMS或郵件中使用。還要注意的是,使用語音檢索,必須要在聯(lián)網(wǎng)的環(huán)境下使用。
小結(jié)
本文介紹了Android搜索的基本框架的使用,也介紹了語音搜索中要注意的問題,在下一篇教程中,將介紹如何為搜索添加自動提示幫助,以及如何讓你的APP在Android的搜索菜單中出現(xiàn)。敬請期待51CTO下篇譯文吧。