當用戶使用Search Dialog或Search Widget輸入搜索查詢時,在界面上會提供搜索建議,用戶可以選擇可能的查詢,使得搜索變得更簡單。可以通過以下步驟實現這一點:
1.系統把查詢文本傳給已定義的內容提供者,該內容提供者包含搜索建議。
2.內容提供者返回一個游標,它基於查詢指向所有建議的列表。
3.系統顯示該建議。
如果用戶選擇其中一條建議,會向可搜索的活動發送intent,包含定制的操作和數據。
該API提供一種簡單的方式可以基於搜索歷史(最近的查詢記錄)顯示建議,並且提供創建定制(由應用邏輯生成)建議的途徑。
最近的查詢建議
SearchRecentSuggestionsProvider類為了搜索建議保存歷史搜索的提供者的基礎類,它涵蓋返回相應結果的絕大部分的必要邏輯。通過這種方式,可以減少實現搜索歷史建議系統所需的代碼量和配置。
要實現搜索提供建議的功能,首先創建一個類,繼承SearchRecentSuggestionsProvider類,並調用setupSuggestions方法定義權限(authority)和模式。
package com.oreilly.demo.android.pa.searchdemo; import android.content.SearchRecentSuggestionsProvider; public class CustomSearchSuggestionProvider extends SearchRecentSuggestionsProvider { public final static String AUTHORITY = \"com.oreilly.demo.android.pa.searchdemo.CustomSearchSuggestionProvider\"; public final static int MODE = DATABASE_MODE_QUERIES; public CustomSearchSuggestionProvider { super; setupSuggestions(AUTHORITY, MODE); } }
構建了提供者後,必須在manifest文件中聲明它。這裡,關鍵是引用同樣的authority字符串,該字符串是在定制的SearchRecentSuggestionsProvider中定義的。
<application> ... <provider android:name=\".searchdemo.CustomSearchSuggestionProvider\" android:authorities= \"com.oreilly.demo.android.pa.searchdemo.CustomSearchSuggestionProvider\" /> ... </application>
該權限還必須在可搜索的XML配置文件中作為android:searchSuggestAuthority屬性的引用。此外,還需要定義android:searchSuggestSelection,其值為「?」(注意前面有個空格),把查詢作為SQLite選擇參數傳給查詢。
<?xml version=\"1.0\" encoding=\"utf-8\"?> <searchable xmlns:android=\"http://schemas.android.com/apk/res/android\" android:label=\"@string/app_name\" android:hint=\"@string/search_hint\" android:voiceSearchMode=\"showVoiceSearchButton|launchRecognizer\" android:searchSuggestAuthority= \"com.oreilly.demo.android.pa.searchdemo.CustomSearchSuggestionProvider\" android:searchSuggestSelection=\" ?\" > </searchable>
最後,聲明了SearchRecentSuggestionsProvider類並設置其配置後,查詢需要添加到搜索歷史中。這是通過調用SearchRecentSuggestions的saveRecentQuery方法並把查詢傳給它來實現的。
SearchRecentSuggestions suggestions = new SearchRecentSuggestions(this, CustomSearchSuggestionProvider.AUTHORITY, CustomSearchSuggestionProvider.MODE); suggestions.saveRecentQuery(query, null); // save query suggestions.clearHistory; // clear history
定制查詢建議
要創建由某些應用邏輯提供的定制查詢建議,需要考慮的主要點在於接收查詢並返回游標Cursor的內容提供者。該Cursor引用系統要顯示給用戶的建議數據的行號。在特定情況下,系統期望數據包含一些特定的列,如表14-1所示。有些列是必須的,其餘則是可選的。
表14-1:定制查詢建議的Cursor數據
表14-1:定制查詢建議的Cursor數據(續)
表14-1:定制查詢建議的Cursor數據(續)
值得注意的是,如果搜索建議不是保存成表格形式(如SQLite表),可以很容易遵循系統需要的字段,應該創建包含需要字段的MatrixCursor,使用addRow(Object)方法添加數據。
不管Cursor規範如何,內容提供者的query方法必須返回之前定義的Cursor類。query方法定義如下:
public Cursor query(Uri uri, String projection, String selection, String selectionArgs, String sortOrder)
它從系統中接收以下參數:
uri
參照以下定義。
projection
該參數值總是空。
selection
搜索配置項android:searchSuggestSelection的值。
selectionArgs
如果在可搜索配置中聲明了android:searchSuggestSelection屬性,該參數包含搜索查詢作為數組的唯一元素,否則為空。它是用戶搜索的基礎項。
sortOrder
該參數值總是空。
uri格式如下:
content://your.authority/optional.suggest.path/some_uri_path_that_you_definned/query
your.authority是之前在可搜索配置XML文件中定義的android.searchSuggestAuthority屬性。optional.suggest.path是在可搜索配置XML文件中定義的可選的android:searchSuggestPath屬性。對於同一個內容提供者,如果有多個可搜索的活動,它確保可以從多個活動中區分出查詢的潛在源文件。其中,some_uri_path_that_you_defined是定義的常量字符串,query是傳遞給用戶的真正查詢字符串。該查詢字符串可能是URI編碼,因而需要解碼。
以下是query方法示例。
還需要在manifest文件中指定內容提供者。
<application> ... <provider android:name=\".searchdemo.SearchDBProvider\" android:authorities= \"com.oreilly.demo.android.pa.searchdemo.SearchDBProvider\" /> ... </application>
然後配置可搜索配置項,至少把android:searchSuggestAuthority項設置成之前定義的權限字符串。
<?xml version=\"1.0\" encoding=\"utf-8\"?> <searchable xmlns:android=\"http://schemas.android.com/apk/res/android\" android:label=\"@string/app_name\" android:searchSuggestAuthority= \"com.oreilly.demo.android.pa.searchdemo.SearchDBProvider\" > </searchable>
其他方面如定制的intent可以通過android:searchSuggestIntentAction,在可搜索配置中指定。通過定制的intent,可搜索的活動可以區分常見的搜索查詢(通過android.Intent.action.SEARCH預設置)和建議的搜索查詢。以下例子使用android.Intent.action.VIEW實現定制intent。
<?xml version=\"1.0\" encoding=\"utf-8\"?> <searchable xmlns:android= \"http://schemas.android.com/apk/res/android\" android:label=\"@string/app_name\" android:searchSuggestAuthority= \"com.oreilly.demo.android.pa.searchdemo.SearchDBProvider\" android:searchSuggestIntentAction=\"android.Intent.action.VIEW\" > </searchable>
在這個例子中,可搜索的activity需要處理Intent.ACTION_VIEW以及Intent.ACTION_SEARCH。
Intent intent = getIntent; if (Intent.ACTION_SEARCH.equals(intent.getAction)) { String query = intent.getStringExtra(SearchManager.QUERY).toLowerCase; search(query); // go do the search against the searchlogic } else if (Intent.ACTION_VIEW.equals(intent.getAction)) { Uri data = intent.getData; loadData(data); // do something with this data }
最後,如果希望在快速搜索框中顯示搜索建議,可搜索的配置應該把android:includeInGlobalSearch中設置成true。系統會自動快速顯示用戶從快速搜索框中選中的搜索建議。系統已經從內容提供者緩存了這些搜索建議,因此可以快速訪問它們。一旦快速搜索框可以使用應用的搜索建議,對於特定查詢,應用的排名決定了這些搜索建議如何展現給用戶。它可能取決於其他應用包含該查詢結果,以及用戶選中哪些查詢結果。對於特定查詢,你的建議如何排序甚至是否顯示都是不確定的。一般而言,提供高質量的查詢結果會提升你的應用建議在顯著位置展示的可能性,而提供低質量的查詢建議的應用往往排名更靠後甚至不會顯示。