1823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang/* 2823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang * Copyright (C) 2010 The Android Open Source Project 3823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang * 4823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang * Licensed under the Apache License, Version 2.0 (the "License"); 5823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang * you may not use this file except in compliance with the License. 6823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang * You may obtain a copy of the License at 7823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang * 8823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang * http://www.apache.org/licenses/LICENSE-2.0 9823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang * 10823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang * Unless required by applicable law or agreed to in writing, software 11823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang * distributed under the License is distributed on an "AS IS" BASIS, 12823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang * See the License for the specific language governing permissions and 14823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang * limitations under the License. 15823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang */ 16823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang 17823b6f3516076b92f78c3fc27037d24bb514e653Ying Wangpackage com.android.common; 18823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang 19430286ba80ebaa23ffa591cbbd6951d5f9fe69faBjorn Bringertimport android.app.SearchManager; 20430286ba80ebaa23ffa591cbbd6951d5f9fe69faBjorn Bringertimport android.app.SearchableInfo; 21430286ba80ebaa23ffa591cbbd6951d5f9fe69faBjorn Bringertimport android.content.ContentResolver; 22430286ba80ebaa23ffa591cbbd6951d5f9fe69faBjorn Bringertimport android.content.Context; 23430286ba80ebaa23ffa591cbbd6951d5f9fe69faBjorn Bringertimport android.database.Cursor; 24430286ba80ebaa23ffa591cbbd6951d5f9fe69faBjorn Bringertimport android.net.Uri; 25430286ba80ebaa23ffa591cbbd6951d5f9fe69faBjorn Bringert 26823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang/** 27823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang * Utilities for search implementations. 28823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang * 29823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang * @see android.app.SearchManager 30823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang */ 31823b6f3516076b92f78c3fc27037d24bb514e653Ying Wangpublic class Search { 32823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang 33823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang /** 34823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang * Key for the source identifier set by the application that launched a search intent. 35823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang * The identifier is search-source specific string. It can be used 36823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang * by the search provider to keep statistics of where searches are started from. 37823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang * 38823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang * The source identifier is stored in the {@link android.app.SearchManager#APP_DATA} 39823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang * Bundle in {@link android.content.Intent#ACTION_SEARCH} and 40823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang * {@link android.content.Intent#ACTION_WEB_SEARCH} intents. 41823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang */ 42823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang public final static String SOURCE = "source"; 43823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang 4491b05eafd38f6fbbf87440c6b96c7d4b434ab3dbMark Brophy /** 4591b05eafd38f6fbbf87440c6b96c7d4b434ab3dbMark Brophy * Column name for suggestions cursor. <i>Optional.</i> This column may be 4691b05eafd38f6fbbf87440c6b96c7d4b434ab3dbMark Brophy * used to specify the time in {@link System#currentTimeMillis 4791b05eafd38f6fbbf87440c6b96c7d4b434ab3dbMark Brophy * System.currentTimeMillis()} (wall time in UTC) when an item was last 4891b05eafd38f6fbbf87440c6b96c7d4b434ab3dbMark Brophy * accessed within the results-providing application. If set, this may be 4991b05eafd38f6fbbf87440c6b96c7d4b434ab3dbMark Brophy * used to show more-recently-used items first. 5091b05eafd38f6fbbf87440c6b96c7d4b434ab3dbMark Brophy * 5191b05eafd38f6fbbf87440c6b96c7d4b434ab3dbMark Brophy * See {@code SearchManager.SUGGEST_COLUMN_LAST_ACCESS_HINT} in ICS. 5291b05eafd38f6fbbf87440c6b96c7d4b434ab3dbMark Brophy */ 5391b05eafd38f6fbbf87440c6b96c7d4b434ab3dbMark Brophy public final static String SUGGEST_COLUMN_LAST_ACCESS_HINT = "suggest_last_access_hint"; 5491b05eafd38f6fbbf87440c6b96c7d4b434ab3dbMark Brophy 55823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang private Search() { } // don't instantiate 56430286ba80ebaa23ffa591cbbd6951d5f9fe69faBjorn Bringert 57430286ba80ebaa23ffa591cbbd6951d5f9fe69faBjorn Bringert /** 58430286ba80ebaa23ffa591cbbd6951d5f9fe69faBjorn Bringert * Gets a cursor with search suggestions. 59430286ba80ebaa23ffa591cbbd6951d5f9fe69faBjorn Bringert * 60430286ba80ebaa23ffa591cbbd6951d5f9fe69faBjorn Bringert * @param searchable Information about how to get the suggestions. 61430286ba80ebaa23ffa591cbbd6951d5f9fe69faBjorn Bringert * @param query The search text entered (so far). 62430286ba80ebaa23ffa591cbbd6951d5f9fe69faBjorn Bringert * @return a cursor with suggestions, or <code>null</null> the suggestion query failed. 63430286ba80ebaa23ffa591cbbd6951d5f9fe69faBjorn Bringert */ 64430286ba80ebaa23ffa591cbbd6951d5f9fe69faBjorn Bringert public static Cursor getSuggestions(Context context, SearchableInfo searchable, String query) { 65430286ba80ebaa23ffa591cbbd6951d5f9fe69faBjorn Bringert return getSuggestions(context, searchable, query, -1); 66430286ba80ebaa23ffa591cbbd6951d5f9fe69faBjorn Bringert } 67430286ba80ebaa23ffa591cbbd6951d5f9fe69faBjorn Bringert 68430286ba80ebaa23ffa591cbbd6951d5f9fe69faBjorn Bringert /** 69430286ba80ebaa23ffa591cbbd6951d5f9fe69faBjorn Bringert * Gets a cursor with search suggestions. 70430286ba80ebaa23ffa591cbbd6951d5f9fe69faBjorn Bringert * 71430286ba80ebaa23ffa591cbbd6951d5f9fe69faBjorn Bringert * @param searchable Information about how to get the suggestions. 72430286ba80ebaa23ffa591cbbd6951d5f9fe69faBjorn Bringert * @param query The search text entered (so far). 73430286ba80ebaa23ffa591cbbd6951d5f9fe69faBjorn Bringert * @param limit The query limit to pass to the suggestion provider. This is advisory, 74430286ba80ebaa23ffa591cbbd6951d5f9fe69faBjorn Bringert * the returned cursor may contain more rows. Pass {@code -1} for no limit. 75430286ba80ebaa23ffa591cbbd6951d5f9fe69faBjorn Bringert * @return a cursor with suggestions, or <code>null</null> the suggestion query failed. 76430286ba80ebaa23ffa591cbbd6951d5f9fe69faBjorn Bringert */ 77430286ba80ebaa23ffa591cbbd6951d5f9fe69faBjorn Bringert public static Cursor getSuggestions(Context context, SearchableInfo searchable, 78430286ba80ebaa23ffa591cbbd6951d5f9fe69faBjorn Bringert String query, int limit) { 79430286ba80ebaa23ffa591cbbd6951d5f9fe69faBjorn Bringert if (searchable == null) { 80430286ba80ebaa23ffa591cbbd6951d5f9fe69faBjorn Bringert return null; 81430286ba80ebaa23ffa591cbbd6951d5f9fe69faBjorn Bringert } 82430286ba80ebaa23ffa591cbbd6951d5f9fe69faBjorn Bringert 83430286ba80ebaa23ffa591cbbd6951d5f9fe69faBjorn Bringert String authority = searchable.getSuggestAuthority(); 84430286ba80ebaa23ffa591cbbd6951d5f9fe69faBjorn Bringert if (authority == null) { 85430286ba80ebaa23ffa591cbbd6951d5f9fe69faBjorn Bringert return null; 86430286ba80ebaa23ffa591cbbd6951d5f9fe69faBjorn Bringert } 87430286ba80ebaa23ffa591cbbd6951d5f9fe69faBjorn Bringert 88430286ba80ebaa23ffa591cbbd6951d5f9fe69faBjorn Bringert Uri.Builder uriBuilder = new Uri.Builder() 89430286ba80ebaa23ffa591cbbd6951d5f9fe69faBjorn Bringert .scheme(ContentResolver.SCHEME_CONTENT) 90430286ba80ebaa23ffa591cbbd6951d5f9fe69faBjorn Bringert .authority(authority) 91430286ba80ebaa23ffa591cbbd6951d5f9fe69faBjorn Bringert .query("") // TODO: Remove, workaround for a bug in Uri.writeToParcel() 92430286ba80ebaa23ffa591cbbd6951d5f9fe69faBjorn Bringert .fragment(""); // TODO: Remove, workaround for a bug in Uri.writeToParcel() 93430286ba80ebaa23ffa591cbbd6951d5f9fe69faBjorn Bringert 94430286ba80ebaa23ffa591cbbd6951d5f9fe69faBjorn Bringert // if content path provided, insert it now 95430286ba80ebaa23ffa591cbbd6951d5f9fe69faBjorn Bringert final String contentPath = searchable.getSuggestPath(); 96430286ba80ebaa23ffa591cbbd6951d5f9fe69faBjorn Bringert if (contentPath != null) { 97430286ba80ebaa23ffa591cbbd6951d5f9fe69faBjorn Bringert uriBuilder.appendEncodedPath(contentPath); 98430286ba80ebaa23ffa591cbbd6951d5f9fe69faBjorn Bringert } 99430286ba80ebaa23ffa591cbbd6951d5f9fe69faBjorn Bringert 100430286ba80ebaa23ffa591cbbd6951d5f9fe69faBjorn Bringert // append standard suggestion query path 101430286ba80ebaa23ffa591cbbd6951d5f9fe69faBjorn Bringert uriBuilder.appendPath(SearchManager.SUGGEST_URI_PATH_QUERY); 102430286ba80ebaa23ffa591cbbd6951d5f9fe69faBjorn Bringert 103430286ba80ebaa23ffa591cbbd6951d5f9fe69faBjorn Bringert // get the query selection, may be null 104430286ba80ebaa23ffa591cbbd6951d5f9fe69faBjorn Bringert String selection = searchable.getSuggestSelection(); 105430286ba80ebaa23ffa591cbbd6951d5f9fe69faBjorn Bringert // inject query, either as selection args or inline 106430286ba80ebaa23ffa591cbbd6951d5f9fe69faBjorn Bringert String[] selArgs = null; 107430286ba80ebaa23ffa591cbbd6951d5f9fe69faBjorn Bringert if (selection != null) { 108430286ba80ebaa23ffa591cbbd6951d5f9fe69faBjorn Bringert selArgs = new String[] { query }; 109430286ba80ebaa23ffa591cbbd6951d5f9fe69faBjorn Bringert } else { // no selection, use REST pattern 110430286ba80ebaa23ffa591cbbd6951d5f9fe69faBjorn Bringert uriBuilder.appendPath(query); 111430286ba80ebaa23ffa591cbbd6951d5f9fe69faBjorn Bringert } 112430286ba80ebaa23ffa591cbbd6951d5f9fe69faBjorn Bringert 113430286ba80ebaa23ffa591cbbd6951d5f9fe69faBjorn Bringert if (limit > 0) { 114430286ba80ebaa23ffa591cbbd6951d5f9fe69faBjorn Bringert uriBuilder.appendQueryParameter(SearchManager.SUGGEST_PARAMETER_LIMIT, 115430286ba80ebaa23ffa591cbbd6951d5f9fe69faBjorn Bringert String.valueOf(limit)); 116430286ba80ebaa23ffa591cbbd6951d5f9fe69faBjorn Bringert } 117430286ba80ebaa23ffa591cbbd6951d5f9fe69faBjorn Bringert 118430286ba80ebaa23ffa591cbbd6951d5f9fe69faBjorn Bringert Uri uri = uriBuilder.build(); 119430286ba80ebaa23ffa591cbbd6951d5f9fe69faBjorn Bringert 120430286ba80ebaa23ffa591cbbd6951d5f9fe69faBjorn Bringert // finally, make the query 121430286ba80ebaa23ffa591cbbd6951d5f9fe69faBjorn Bringert return context.getContentResolver().query(uri, null, selection, selArgs, null); 122430286ba80ebaa23ffa591cbbd6951d5f9fe69faBjorn Bringert } 123430286ba80ebaa23ffa591cbbd6951d5f9fe69faBjorn Bringert 124823b6f3516076b92f78c3fc27037d24bb514e653Ying Wang} 125