SearchManager.java revision 32d580c360da0a0f15e7a080f4ebd0b7b514fe4c
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License.
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License.
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.app;
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
193c50ef6f665ab22cdb50c76bb31283e6bac47fc6Bjorn Bringertimport android.Manifest;
203c50ef6f665ab22cdb50c76bb31283e6bac47fc6Bjorn Bringertimport android.content.ActivityNotFoundException;
219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.ComponentName;
22875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaenimport android.content.ContentResolver;
239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context;
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.DialogInterface;
253c50ef6f665ab22cdb50c76bb31283e6bac47fc6Bjorn Bringertimport android.content.Intent;
263c50ef6f665ab22cdb50c76bb31283e6bac47fc6Bjorn Bringertimport android.content.pm.ActivityInfo;
273c50ef6f665ab22cdb50c76bb31283e6bac47fc6Bjorn Bringertimport android.content.pm.PackageManager;
283c50ef6f665ab22cdb50c76bb31283e6bac47fc6Bjorn Bringertimport android.content.pm.ResolveInfo;
29875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaenimport android.database.Cursor;
30875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaenimport android.net.Uri;
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Bundle;
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Handler;
33875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaenimport android.os.RemoteException;
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.ServiceManager;
353fc7c67de192a5baee2b4510fdb464b0fec72dcaBjorn Bringertimport android.text.TextUtils;
368d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringertimport android.util.Log;
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.KeyEvent;
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
396d72e029cb6e5a9cf26aa3314c3dca83614fc91bBjorn Bringertimport java.util.List;
406d72e029cb6e5a9cf26aa3314c3dca83614fc91bBjorn Bringert
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This class provides access to the system search services.
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>In practice, you won't interact with this class directly, as search
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * services are provided through methods in {@link android.app.Activity Activity}
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * methods and the the {@link android.content.Intent#ACTION_SEARCH ACTION_SEARCH}
479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link android.content.Intent Intent}.  This class does provide a basic
489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * overview of search services and how to integrate them with your activities.
498c91dd7ec8b3d277a42bccab075241468c9f980dMike LeBeau * If you do require direct access to the SearchManager, do not instantiate
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * this class directly; instead, retrieve it through
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link android.content.Context#getSystemService
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * context.getSystemService(Context.SEARCH_SERVICE)}.
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>Topics covered here:
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <ol>
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <li><a href="#DeveloperGuide">Developer Guide</a>
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <li><a href="#HowSearchIsInvoked">How Search Is Invoked</a>
588c91dd7ec8b3d277a42bccab075241468c9f980dMike LeBeau * <li><a href="#ImplementingSearchForYourApp">Implementing Search for Your App</a>
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <li><a href="#Suggestions">Search Suggestions</a>
60590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen * <li><a href="#ExposingSearchSuggestionsToQuickSearchBox">Exposing Search Suggestions to
61590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen * Quick Search Box</a></li>
629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <li><a href="#ActionKeys">Action Keys</a>
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <li><a href="#SearchabilityMetadata">Searchability Metadata</a>
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <li><a href="#PassingSearchContext">Passing Search Context</a>
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <li><a href="#ProtectingUserPrivacy">Protecting User Privacy</a>
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * </ol>
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <a name="DeveloperGuide"></a>
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <h3>Developer Guide</h3>
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>The ability to search for user, system, or network based data is considered to be
728c91dd7ec8b3d277a42bccab075241468c9f980dMike LeBeau * a core user-level feature of the Android platform.  At any time, the user should be
739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * able to use a familiar command, button, or keystroke to invoke search, and the user
748c91dd7ec8b3d277a42bccab075241468c9f980dMike LeBeau * should be able to search any data which is available to them.
759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
768c91dd7ec8b3d277a42bccab075241468c9f980dMike LeBeau * <p>To make search appear to the user as a seamless system-wide feature, the application
778c91dd7ec8b3d277a42bccab075241468c9f980dMike LeBeau * framework centrally controls it, offering APIs to individual applications to control how they
788c91dd7ec8b3d277a42bccab075241468c9f980dMike LeBeau * are searched. Applications can customize how search is invoked, how the search dialog looks,
798c91dd7ec8b3d277a42bccab075241468c9f980dMike LeBeau * and what type of search results are available, including suggestions that are available as the
808c91dd7ec8b3d277a42bccab075241468c9f980dMike LeBeau * user types.
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
828c91dd7ec8b3d277a42bccab075241468c9f980dMike LeBeau * <p>Even applications which are not searchable will by default support the invocation of
838c91dd7ec8b3d277a42bccab075241468c9f980dMike LeBeau * search to trigger Quick Search Box, the system's 'global search'.
849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <a name="HowSearchIsInvoked"></a>
869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <h3>How Search Is Invoked</h3>
879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>Unless impossible or inapplicable, all applications should support
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * invoking the search UI.  This means that when the user invokes the search command,
909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * a search UI will be presented to them.  The search command is currently defined as a menu
918c91dd7ec8b3d277a42bccab075241468c9f980dMike LeBeau * item called "Search" (with an alphabetic shortcut key of "S"), or on many devices, a dedicated
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * search button key.
938c91dd7ec8b3d277a42bccab075241468c9f980dMike LeBeau * <p>If your application is not inherently searchable, the default implementation will cause
948c91dd7ec8b3d277a42bccab075241468c9f980dMike LeBeau * the search UI to be invoked in a "global search" mode known as Quick Search Box.  As the user
958c91dd7ec8b3d277a42bccab075241468c9f980dMike LeBeau * types, search suggestions from across the device and the web will be surfaced, and if they
968c91dd7ec8b3d277a42bccab075241468c9f980dMike LeBeau * click the "Search" button, this will bring the browser to the front and will launch a web-based
979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * search.  The user will be able to click the "Back" button and return to your application.
989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>In general this is implemented by your activity, or the {@link android.app.Activity Activity}
998c91dd7ec8b3d277a42bccab075241468c9f980dMike LeBeau * base class, which captures the search command and invokes the SearchManager to
1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * display and operate the search UI.  You can also cause the search UI to be presented in response
1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * to user keystrokes in your activity (for example, to instantly start filter searching while
1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * viewing a list and typing any key).
1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>The search UI is presented as a floating
1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * window and does not cause any change in the activity stack.  If the user
1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * cancels search, the previous activity re-emerges.  If the user launches a
1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * search, this will be done by sending a search {@link android.content.Intent Intent} (see below),
1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * and the normal intent-handling sequence will take place (your activity will pause,
1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * etc.)
1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p><b>What you need to do:</b> First, you should consider the way in which you want to
1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * handle invoking search.  There are four broad (and partially overlapping) categories for
1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you to choose from.
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <ul><li>You can capture the search command yourself, by including a <i>search</i>
1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * button or menu item - and invoking the search UI directly.</li>
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <li>You can provide a <i>type-to-search</i> feature, in which search is invoked automatically
1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * when the user enters any characters.</li>
1168c91dd7ec8b3d277a42bccab075241468c9f980dMike LeBeau * <li>Even if your application is not inherently searchable, you can allow global search,
1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * via the search key (or even via a search menu item).
1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <li>You can disable search entirely.  This should only be used in very rare circumstances,
1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * as search is a system-wide feature and users will expect it to be available in all contexts.</li>
1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * </ul>
1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p><b>How to define a search menu.</b>  The system provides the following resources which may
1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * be useful when adding a search item to your menu:
1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <ul><li>android.R.drawable.ic_search_category_default is an icon you can use in your menu.</li>
1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <li>{@link #MENU_KEY SearchManager.MENU_KEY} is the recommended alphabetic shortcut.</li>
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * </ul>
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p><b>How to invoke search directly.</b>  In order to invoke search directly, from a button
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * or menu item, you can launch a generic search by calling
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link android.app.Activity#onSearchRequested onSearchRequested} as shown:
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <pre class="prettyprint">
1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * onSearchRequested();</pre>
1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p><b>How to implement type-to-search.</b>  While setting up your activity, call
1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link android.app.Activity#setDefaultKeyMode setDefaultKeyMode}:
1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <pre class="prettyprint">
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * setDefaultKeyMode(DEFAULT_KEYS_SEARCH_LOCAL);   // search within your activity
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * setDefaultKeyMode(DEFAULT_KEYS_SEARCH_GLOBAL);  // search using platform global search</pre>
1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
1408c91dd7ec8b3d277a42bccab075241468c9f980dMike LeBeau * <p><b>How to enable global search with Quick Search Box.</b>  In addition to searching within
1418c91dd7ec8b3d277a42bccab075241468c9f980dMike LeBeau * your activity or application, you can also use the Search Manager to invoke a platform-global
1428c91dd7ec8b3d277a42bccab075241468c9f980dMike LeBeau * search, which uses Quick Search Box to search across the device and the web. There are two ways
1438c91dd7ec8b3d277a42bccab075241468c9f980dMike LeBeau * to do this:
1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <ul><li>You can simply define "search" within your application or activity to mean global search.
1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This is described in more detail in the
1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <a href="#SearchabilityMetadata">Searchability Metadata</a> section.  Briefly, you will
1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * add a single meta-data entry to your manifest, declaring that the default search
1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * for your application is "*".  This indicates to the system that no application-specific
1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * search activity is provided, and that it should launch web-based search instead.</li>
1508c91dd7ec8b3d277a42bccab075241468c9f980dMike LeBeau * <li>Simply do nothing and the default implementation of
1518c91dd7ec8b3d277a42bccab075241468c9f980dMike LeBeau * {@link android.app.Activity#onSearchRequested} will cause global search to be triggered.
1528c91dd7ec8b3d277a42bccab075241468c9f980dMike LeBeau * (You can also always trigger search via a direct call to {@link android.app.Activity#startSearch}.
1538c91dd7ec8b3d277a42bccab075241468c9f980dMike LeBeau * This is most useful if you wish to provide local searchability <i>and</i> access to global
1548c91dd7ec8b3d277a42bccab075241468c9f980dMike LeBeau * search.)</li></ul>
1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
1568c91dd7ec8b3d277a42bccab075241468c9f980dMike LeBeau * <p><b>How to disable search from your activity.</b> Search is a system-wide feature and users
1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * will expect it to be available in all contexts.  If your UI design absolutely precludes
1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * launching search, override {@link android.app.Activity#onSearchRequested onSearchRequested}
1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * as shown:
1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <pre class="prettyprint">
1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * &#64;Override
1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * public boolean onSearchRequested() {
1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *    return false;
1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * }</pre>
1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
1668c91dd7ec8b3d277a42bccab075241468c9f980dMike LeBeau * <p><b>Managing focus and knowing if search is active.</b>  The search UI is not a separate
1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * activity, and when the UI is invoked or dismissed, your activity will not typically be paused,
1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * resumed, or otherwise notified by the methods defined in
1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <a href="{@docRoot}guide/topics/fundamentals.html#actlife">Application Fundamentals:
1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Activity Lifecycle</a>.  The search UI is
1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * handled in the same way as other system UI elements which may appear from time to time, such as
1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * notifications, screen locks, or other system alerts:
1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>When the search UI appears, your activity will lose input focus.
1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>When the search activity is dismissed, there are three possible outcomes:
1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <ul><li>If the user simply canceled the search UI, your activity will regain input focus and
1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * proceed as before.  See {@link #setOnDismissListener} and {@link #setOnCancelListener} if you
1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * required direct notification of search dialog dismissals.</li>
1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <li>If the user launched a search, and this required switching to another activity to receive
1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * and process the search {@link android.content.Intent Intent}, your activity will receive the
1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * normal sequence of activity pause or stop notifications.</li>
1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <li>If the user launched a search, and the current activity is the recipient of the search
1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link android.content.Intent Intent}, you will receive notification via the
1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link android.app.Activity#onNewIntent onNewIntent()} method.</li></ul>
1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>This list is provided in order to clarify the ways in which your activities will interact with
1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the search UI.  More details on searchable activities and search intents are provided in the
1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * sections below.
1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
1888c91dd7ec8b3d277a42bccab075241468c9f980dMike LeBeau * <a name="ImplementingSearchForYourApp"></a>
1898c91dd7ec8b3d277a42bccab075241468c9f980dMike LeBeau * <h3>Implementing Search for Your App</h3>
1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
1918c91dd7ec8b3d277a42bccab075241468c9f980dMike LeBeau * <p>The following steps are necessary in order to implement search.
1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <ul>
1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <li>Implement search invocation as described above.  (Strictly speaking,
1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * these are decoupled, but it would make little sense to be "searchable" but not
1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * "search-invoking".)</li>
1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <li>Your application should have an activity that takes a search string and
1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * converts it to a list of results.  This could be your primary display activity
1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * or it could be a dedicated search results activity.  This is your <i>searchable</i>
1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * activity and every query-search application must have one.</li>
2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <li>In the searchable activity, in onCreate(), you must receive and handle the
2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link android.content.Intent#ACTION_SEARCH ACTION_SEARCH}
2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link android.content.Intent Intent}.  The text to search (query string) for is provided by
2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * calling
2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link #QUERY getStringExtra(SearchManager.QUERY)}.</li>
2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <li>To identify and support your searchable activity, you'll need to
2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * provide an XML file providing searchability configuration parameters, a reference to that
2078c91dd7ec8b3d277a42bccab075241468c9f980dMike LeBeau * in your searchable activity's
2088c91dd7ec8b3d277a42bccab075241468c9f980dMike LeBeau * <a href="{@docRoot}guide/topics/manifest/manifest-intro.html">manifest</a> entry, and an
2098c91dd7ec8b3d277a42bccab075241468c9f980dMike LeBeau * intent-filter declaring that you can receive ACTION_SEARCH intents. This is described in more
2108c91dd7ec8b3d277a42bccab075241468c9f980dMike LeBeau * detail in the <a href="#SearchabilityMetadata">Searchability Metadata</a> section.</li>
2118c91dd7ec8b3d277a42bccab075241468c9f980dMike LeBeau * <li>Your <a href="{@docRoot}guide/topics/manifest/manifest-intro.html">manifest</a> also needs a
2128c91dd7ec8b3d277a42bccab075241468c9f980dMike LeBeau * metadata entry providing a global reference to the searchable activity. This is the "glue"
2138c91dd7ec8b3d277a42bccab075241468c9f980dMike LeBeau * directing the search UI, when invoked from any of your <i>other</i> activities, to use your
2148c91dd7ec8b3d277a42bccab075241468c9f980dMike LeBeau * application as the default search context.  This is also described in more detail in the
2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <a href="#SearchabilityMetadata">Searchability Metadata</a> section.</li>
2168c91dd7ec8b3d277a42bccab075241468c9f980dMike LeBeau * <li>Finally, you may want to define your search results activity as single-top with the
2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link android.R.attr#launchMode singleTop} launchMode flag.  This allows the system
2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * to launch searches from/to the same activity without creating a pile of them on the
2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * activity stack.  If you do this, be sure to also override
2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link android.app.Activity#onNewIntent onNewIntent} to handle the
2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * updated intents (with new queries) as they arrive.</li>
2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * </ul>
2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>Code snippet showing handling of intents in your search activity:
2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <pre class="prettyprint">
2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * &#64;Override
2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * protected void onCreate(Bundle icicle) {
2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *     super.onCreate(icicle);
2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *     final Intent queryIntent = getIntent();
2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *     final String queryAction = queryIntent.getAction();
2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *     if (Intent.ACTION_SEARCH.equals(queryAction)) {
2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *         doSearchWithIntent(queryIntent);
2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *     }
2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * }
2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * private void doSearchWithIntent(final Intent queryIntent) {
2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *     final String queryString = queryIntent.getStringExtra(SearchManager.QUERY);
2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *     doSearchWithQuery(queryString);
2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * }</pre>
2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <a name="Suggestions"></a>
2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <h3>Search Suggestions</h3>
2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
2458c91dd7ec8b3d277a42bccab075241468c9f980dMike LeBeau * <p>A powerful feature of the search system is the ability of any application to easily provide
2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * live "suggestions" in order to prompt the user.  Each application implements suggestions in a
2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * different, unique, and appropriate way.  Suggestions be drawn from many sources, including but
2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * not limited to:
2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <ul>
2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <li>Actual searchable results (e.g. names in the address book)</li>
2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <li>Recently entered queries</li>
2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <li>Recently viewed data or results</li>
2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <li>Contextually appropriate queries or results</li>
2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <li>Summaries of possible results</li>
2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * </ul>
2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
257590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen * <p>Once an application is configured to provide search suggestions, those same suggestions can
258590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen * easily be made available to the system-wide Quick Search Box, providing faster access to its
25905b775e0b7180e33df0303b9e132931f4895357cMike LeBeau * content from one central prominent place. See
260590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen * <a href="#ExposingSearchSuggestionsToQuickSearchBox">Exposing Search Suggestions to Quick Search
261590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen * Box</a> for more details.
262590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen *
2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>The primary form of suggestions is known as <i>queried suggestions</i> and is based on query
2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * text that the user has already typed.  This would generally be based on partial matches in
2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the available data.  In certain situations - for example, when no query text has been typed yet -
2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * an application may also opt to provide <i>zero-query suggestions</i>.
2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * These would typically be drawn from the same data source, but because no partial query text is
2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * available, they should be weighted based on other factors - for example, most recent queries
2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * or most recent results.
2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
2718c91dd7ec8b3d277a42bccab075241468c9f980dMike LeBeau * <p><b>Overview of how suggestions are provided.</b>  Suggestions are accessed via a
2728c91dd7ec8b3d277a42bccab075241468c9f980dMike LeBeau * {@link android.content.ContentProvider Content Provider}. When the search manager identifies a
2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * particular activity as searchable, it will check for certain metadata which indicates that
2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * there is also a source of suggestions.  If suggestions are provided, the following steps are
2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * taken.
2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <ul><li>Using formatting information found in the metadata, the user's query text (whatever
2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * has been typed so far) will be formatted into a query and sent to the suggestions
2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link android.content.ContentProvider Content Provider}.</li>
2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <li>The suggestions {@link android.content.ContentProvider Content Provider} will create a
2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link android.database.Cursor Cursor} which can iterate over the possible suggestions.</li>
2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <li>The search manager will populate a list using display data found in each row of the cursor,
2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * and display these suggestions to the user.</li>
2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <li>If the user types another key, or changes the query in any way, the above steps are repeated
2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * and the suggestions list is updated or repopulated.</li>
2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <li>If the user clicks or touches the "GO" button, the suggestions are ignored and the search is
2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * launched using the normal {@link android.content.Intent#ACTION_SEARCH ACTION_SEARCH} type of
2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link android.content.Intent Intent}.</li>
2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <li>If the user uses the directional controls to navigate the focus into the suggestions list,
2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the query text will be updated while the user navigates from suggestion to suggestion.  The user
2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * can then click or touch the updated query and edit it further.  If the user navigates back to
2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the edit field, the original typed query is restored.</li>
2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <li>If the user clicks or touches a particular suggestion, then a combination of data from the
2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * cursor and
2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * values found in the metadata are used to synthesize an Intent and send it to the application.
2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Depending on the design of the activity and the way it implements search, this might be a
2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link android.content.Intent#ACTION_SEARCH ACTION_SEARCH} (in order to launch a query), or it
2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * might be a {@link android.content.Intent#ACTION_VIEW ACTION_VIEW}, in order to proceed directly
2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * to display of specific data.</li>
2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * </ul>
3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p><b>Simple Recent-Query-Based Suggestions.</b>  The Android framework provides a simple Search
3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Suggestions provider, which simply records and replays recent queries.  For many applications,
3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * this will be sufficient.  The basic steps you will need to
3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * do, in order to use the built-in recent queries suggestions provider, are as follows:
3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <ul>
3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <li>Implement and test query search, as described in the previous sections.</li>
3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <li>Create a Provider within your application by extending
3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link android.content.SearchRecentSuggestionsProvider}.</li>
3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <li>Create a manifest entry describing your provider.</li>
3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <li>Update your searchable activity's XML configuration file with information about your
3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * provider.</li>
3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <li>In your searchable activities, capture any user-generated queries and record them
3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * for future searches by calling {@link android.provider.SearchRecentSuggestions#saveRecentQuery}.
3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * </li>
3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * </ul>
3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>For complete implementation details, please refer to
3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link android.content.SearchRecentSuggestionsProvider}.  The rest of the information in this
3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * section should not be necessary, as it refers to custom suggestions providers.
3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p><b>Creating a Customized Suggestions Provider:</b>  In order to create more sophisticated
3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * suggestion providers, you'll need to take the following steps:
3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <ul>
3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <li>Implement and test query search, as described in the previous sections.</li>
3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <li>Decide how you wish to <i>receive</i> suggestions.  Just like queries that the user enters,
3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * suggestions will be delivered to your searchable activity as
3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link android.content.Intent Intent} messages;  Unlike simple queries, you have quite a bit of
3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * flexibility in forming those intents.  A query search application will probably
3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * wish to continue receiving the {@link android.content.Intent#ACTION_SEARCH ACTION_SEARCH}
3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link android.content.Intent Intent}, which will launch a query search using query text as
3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * provided by the suggestion.  A filter search application will probably wish to
3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * receive the {@link android.content.Intent#ACTION_VIEW ACTION_VIEW}
3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link android.content.Intent Intent}, which will take the user directly to a selected entry.
3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Other interesting suggestions, including hybrids, are possible, and the suggestion provider
3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * can easily mix-and-match results to provide a richer set of suggestions for the user.  Finally,
3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you'll need to update your searchable activity (or other activities) to receive the intents
3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * as you've defined them.</li>
3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <li>Implement a Content Provider that provides suggestions.  If you already have one, and it
3386b13bc043e715b5415b701e93141daa0d49fa364Dirk Dougherty * has access to your suggestions data, you can use that provider. If not, you'll have to create
3396b13bc043e715b5415b701e93141daa0d49fa364Dirk Dougherty * one. You'll also provide information about your Content Provider in your
3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * package's <a href="{@docRoot}guide/topics/manifest/manifest-intro.html">manifest</a>.</li>
3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <li>Update your searchable activity's XML configuration file.  There are two categories of
3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * information used for suggestions:
3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <ul><li>The first is (required) data that the search manager will
3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * use to format the queries which are sent to the Content Provider.</li>
3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <li>The second is (optional) parameters to configure structure
3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * if intents generated by suggestions.</li></li>
3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * </ul>
3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * </ul>
3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p><b>Configuring your Content Provider to Receive Suggestion Queries.</b>  The basic job of
3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * a search suggestions {@link android.content.ContentProvider Content Provider} is to provide
3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * "live" (while-you-type) conversion of the user's query text into a set of zero or more
3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * suggestions.  Each application is free to define the conversion, and as described above there are
3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * many possible solutions.  This section simply defines how to communicate with the suggestion
3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * provider.
3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>The Search Manager must first determine if your package provides suggestions.  This is done
3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * by examination of your searchable meta-data XML file.  The android:searchSuggestAuthority
3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * attribute, if provided, is the signal to obtain & display suggestions.
3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>Every query includes a Uri, and the Search Manager will format the Uri as shown:
3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p><pre class="prettyprint">
3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * content:// your.suggest.authority / your.suggest.path / SearchManager.SUGGEST_URI_PATH_QUERY</pre>
3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>Your Content Provider can receive the query text in one of two ways.
3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <ul>
3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <li><b>Query provided as a selection argument.</b>  If you define the attribute value
3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * android:searchSuggestSelection and include a string, this string will be passed as the
3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <i>selection</i> parameter to your Content Provider's query function.  You must define a single
3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * selection argument, using the '?' character.  The user's query text will be passed to you
3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * as the first element of the selection arguments array.</li>
3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <li><b>Query provided with Data Uri.</b>  If you <i>do not</i> define the attribute value
3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * android:searchSuggestSelection, then the Search Manager will append another "/" followed by
3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the user's query to the query Uri.  The query will be encoding using Uri encoding rules - don't
3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * forget to decode it.  (See {@link android.net.Uri#getPathSegments} and
3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link android.net.Uri#getLastPathSegment} for helpful utilities you can use here.)</li>
3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * </ul>
378b5041368524045b6714081d14ff3c6b22598aab1Karl Rosaen *
379b5041368524045b6714081d14ff3c6b22598aab1Karl Rosaen * <p><b>Providing access to Content Providers that require permissions.</b>  If your content
380b5041368524045b6714081d14ff3c6b22598aab1Karl Rosaen * provider declares an android:readPermission in your application's manifest, you must provide
381b5041368524045b6714081d14ff3c6b22598aab1Karl Rosaen * access to the search infrastructure to the search suggestion path by including a path-permission
382b5041368524045b6714081d14ff3c6b22598aab1Karl Rosaen * that grants android:readPermission access to "android.permission.GLOBAL_SEARCH".  Granting access
383b5041368524045b6714081d14ff3c6b22598aab1Karl Rosaen * explicitly to the search infrastructure ensures it will be able to access the search suggestions
384b5041368524045b6714081d14ff3c6b22598aab1Karl Rosaen * without needing to know ahead of time any other details of the permissions protecting your
385b5041368524045b6714081d14ff3c6b22598aab1Karl Rosaen * provider.  Content providers that require no permissions are already available to the search
386b5041368524045b6714081d14ff3c6b22598aab1Karl Rosaen * infrastructure.  Here is an example of a provider that protects access to it with permissions,
387b5041368524045b6714081d14ff3c6b22598aab1Karl Rosaen * and provides read access to the search infrastructure to the path that it expects to receive the
388b5041368524045b6714081d14ff3c6b22598aab1Karl Rosaen * suggestion query on:
389b5041368524045b6714081d14ff3c6b22598aab1Karl Rosaen * <pre class="prettyprint">
390b5041368524045b6714081d14ff3c6b22598aab1Karl Rosaen * &lt;provider android:name="MyProvider" android:authorities="myprovider"
391b5041368524045b6714081d14ff3c6b22598aab1Karl Rosaen *        android:readPermission="android.permission.READ_MY_DATA"
392b5041368524045b6714081d14ff3c6b22598aab1Karl Rosaen *        android:writePermission="android.permission.WRITE_MY_DATA"&gt;
393b5041368524045b6714081d14ff3c6b22598aab1Karl Rosaen *    &lt;path-permission android:path="/search_suggest_query"
394b5041368524045b6714081d14ff3c6b22598aab1Karl Rosaen *            android:readPermission="android.permission.GLOBAL_SEARCH" /&gt;
395b5041368524045b6714081d14ff3c6b22598aab1Karl Rosaen * &lt;/provider&gt;
396b5041368524045b6714081d14ff3c6b22598aab1Karl Rosaen * </pre>
397b5041368524045b6714081d14ff3c6b22598aab1Karl Rosaen *
3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p><b>Handling empty queries.</b>  Your application should handle the "empty query"
3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * (no user text entered) case properly, and generate useful suggestions in this case.  There are a
4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * number of ways to do this;  Two are outlined here:
4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <ul><li>For a simple filter search of local data, you could simply present the entire dataset,
4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * unfiltered.  (example: People)</li>
4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <li>For a query search, you could simply present the most recent queries.  This allows the user
4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * to quickly repeat a recent search.</li></ul>
405b5041368524045b6714081d14ff3c6b22598aab1Karl Rosaen *
4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p><b>The Format of Individual Suggestions.</b>  Your suggestions are communicated back to the
4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Search Manager by way of a {@link android.database.Cursor Cursor}.  The Search Manager will
4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * usually pass a null Projection, which means that your provider can simply return all appropriate
4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * columns for each suggestion.  The columns currently defined are:
4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <table border="2" width="85%" align="center" frame="hsides" rules="rows">
4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *     <thead>
4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *     <tr><th>Column Name</th> <th>Description</th> <th>Required?</th></tr>
4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *     </thead>
4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *     <tbody>
4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *     <tr><th>{@link #SUGGEST_COLUMN_FORMAT}</th>
4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *         <td><i>Unused - can be null.</i></td>
4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *         <td align="center">No</td>
4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *     </tr>
4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *     <tr><th>{@link #SUGGEST_COLUMN_TEXT_1}</th>
4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *         <td>This is the line of text that will be presented to the user as the suggestion.</td>
4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *         <td align="center">Yes</td>
4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *     </tr>
4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *     <tr><th>{@link #SUGGEST_COLUMN_TEXT_2}</th>
4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *         <td>If your cursor includes this column, then all suggestions will be provided in a
4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *             two-line format.  The data in this column will be displayed as a second, smaller
4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *             line of text below the primary suggestion, or it can be null or empty to indicate no
4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *             text in this row's suggestion.</td>
4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *         <td align="center">No</td>
4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *     </tr>
4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *     <tr><th>{@link #SUGGEST_COLUMN_ICON_1}</th>
4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *         <td>If your cursor includes this column, then all suggestions will be provided in an
438875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen *             icons+text format.  This value should be a reference to the icon to
4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *             draw on the left side, or it can be null or zero to indicate no icon in this row.
4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *             </td>
441875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen *         <td align="center">No.</td>
4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *     </tr>
4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *     <tr><th>{@link #SUGGEST_COLUMN_ICON_2}</th>
4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *         <td>If your cursor includes this column, then all suggestions will be provided in an
446875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen *             icons+text format.  This value should be a reference to the icon to
4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *             draw on the right side, or it can be null or zero to indicate no icon in this row.
4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *             </td>
449875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen *         <td align="center">No.</td>
4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *     </tr>
4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *     <tr><th>{@link #SUGGEST_COLUMN_INTENT_ACTION}</th>
4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *         <td>If this column exists <i>and</i> this element exists at the given row, this is the
4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *             action that will be used when forming the suggestion's intent.  If the element is
4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *             not provided, the action will be taken from the android:searchSuggestIntentAction
4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *             field in your XML metadata.  <i>At least one of these must be present for the
4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *             suggestion to generate an intent.</i>  Note:  If your action is the same for all
4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *             suggestions, it is more efficient to specify it using XML metadata and omit it from
4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *             the cursor.</td>
4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *         <td align="center">No</td>
4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *     </tr>
4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *     <tr><th>{@link #SUGGEST_COLUMN_INTENT_DATA}</th>
4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *         <td>If this column exists <i>and</i> this element exists at the given row, this is the
4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *             data that will be used when forming the suggestion's intent.  If the element is not
4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *             provided, the data will be taken from the android:searchSuggestIntentData field in
4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *             your XML metadata.  If neither source is provided, the Intent's data field will be
4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *             null.  Note:  If your data is the same for all suggestions, or can be described
4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *             using a constant part and a specific ID, it is more efficient to specify it using
4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *             XML metadata and omit it from the cursor.</td>
4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *         <td align="center">No</td>
4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *     </tr>
4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *     <tr><th>{@link #SUGGEST_COLUMN_INTENT_DATA_ID}</th>
4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *         <td>If this column exists <i>and</i> this element exists at the given row, then "/" and
4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *             this value will be appended to the data field in the Intent.  This should only be
4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *             used if the data field has already been set to an appropriate base string.</td>
4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *         <td align="center">No</td>
4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *     </tr>
4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
481b5041368524045b6714081d14ff3c6b22598aab1Karl Rosaen *     <tr><th>{@link #SUGGEST_COLUMN_INTENT_EXTRA_DATA}</th>
482b5041368524045b6714081d14ff3c6b22598aab1Karl Rosaen *         <td>If this column exists <i>and</i> this element exists at a given row, this is the
483b5041368524045b6714081d14ff3c6b22598aab1Karl Rosaen *             data that will be used when forming the suggestion's intent.  If not provided,
484b5041368524045b6714081d14ff3c6b22598aab1Karl Rosaen *             the Intent's extra data field will be null.  This column allows suggestions to
485b5041368524045b6714081d14ff3c6b22598aab1Karl Rosaen *             provide additional arbitrary data which will be included as an extra under the
486b5041368524045b6714081d14ff3c6b22598aab1Karl Rosaen *             key {@link #EXTRA_DATA_KEY}.</td>
487b5041368524045b6714081d14ff3c6b22598aab1Karl Rosaen *         <td align="center">No.</td>
488b5041368524045b6714081d14ff3c6b22598aab1Karl Rosaen *     </tr>
489b5041368524045b6714081d14ff3c6b22598aab1Karl Rosaen *
4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *     <tr><th>{@link #SUGGEST_COLUMN_QUERY}</th>
4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *         <td>If this column exists <i>and</i> this element exists at the given row, this is the
4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *             data that will be used when forming the suggestion's query.</td>
4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *         <td align="center">Required if suggestion's action is
4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *             {@link android.content.Intent#ACTION_SEARCH ACTION_SEARCH}, optional otherwise.</td>
4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *     </tr>
496b5041368524045b6714081d14ff3c6b22598aab1Karl Rosaen *
497590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen *     <tr><th>{@link #SUGGEST_COLUMN_SHORTCUT_ID}</th>
498590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen *         <td>This column is used to indicate whether a search suggestion should be stored as a
499590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen *             shortcut, and whether it should be validated.  Shortcuts are usually formed when the
500590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen *             user clicks a suggestion from Quick Search Box.  If missing, the result will be
501590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen *             stored as a shortcut and never refreshed.  If set to
502590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen *             {@link #SUGGEST_NEVER_MAKE_SHORTCUT}, the result will not be stored as a shortcut.
503590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen *             Otherwise, the shortcut id will be used to check back for for an up to date
504590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen *             suggestion using {@link #SUGGEST_URI_PATH_SHORTCUT}. Read more about shortcut
505590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen *             refreshing in the section about
506590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen *             <a href="#ExposingSearchSuggestionsToQuickSearchBox">exposing search suggestions to
507590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen *             Quick Search Box</a>.</td>
508590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen *         <td align="center">No.  Only applicable to sources included in Quick Search Box.</td>
509590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen *     </tr>
510590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen *
511590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen *     <tr><th>{@link #SUGGEST_COLUMN_SPINNER_WHILE_REFRESHING}</th>
512590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen *         <td>This column is used to specify that a spinner should be shown in lieu of an icon2
51305b775e0b7180e33df0303b9e132931f4895357cMike LeBeau *             while the shortcut of this suggestion is being refreshed in Quick Search Box.</td>
514590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen *         <td align="center">No.  Only applicable to sources included in Quick Search Box.</td>
515590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen *     </tr>
516590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen *
5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *     <tr><th><i>Other Columns</i></th>
5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *         <td>Finally, if you have defined any <a href="#ActionKeys">Action Keys</a> and you wish
5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *             for them to have suggestion-specific definitions, you'll need to define one
5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *             additional column per action key.  The action key will only trigger if the
5219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *             currently-selection suggestion has a non-empty string in the corresponding column.
5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *             See the section on <a href="#ActionKeys">Action Keys</a> for additional details and
5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *             implementation steps.</td>
5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *         <td align="center">No</td>
5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *     </tr>
5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *     </tbody>
5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * </table>
5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>Clearly there are quite a few permutations of your suggestion data, but in the next section
5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * we'll look at a few simple combinations that you'll select from.
5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p><b>The Format Of Intents Sent By Search Suggestions.</b>  Although there are many ways to
5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * configure these intents, this document will provide specific information on just a few of them.
5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <ul><li><b>Launch a query.</b>  In this model, each suggestion represents a query that your
5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * searchable activity can perform, and the {@link android.content.Intent Intent} will be formatted
5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * exactly like those sent when the user enters query text and clicks the "GO" button:
5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *   <ul>
5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *   <li><b>Action:</b> {@link android.content.Intent#ACTION_SEARCH ACTION_SEARCH} provided
5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *   using your XML metadata (android:searchSuggestIntentAction).</li>
5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *   <li><b>Data:</b> empty (not used).</li>
5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *   <li><b>Query:</b> query text supplied by the cursor.</li>
5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *   </ul>
5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * </li>
5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <li><b>Go directly to a result, using a complete Data Uri.</b>  In this model, the user will be
5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * taken directly to a specific result.
5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *   <ul>
5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *   <li><b>Action:</b> {@link android.content.Intent#ACTION_VIEW ACTION_VIEW}</li>
5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *   <li><b>Data:</b> a complete Uri, supplied by the cursor, that identifies the desired data.</li>
5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *   <li><b>Query:</b> query text supplied with the suggestion (probably ignored)</li>
5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *   </ul>
5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * </li>
5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <li><b>Go directly to a result, using a synthesized Data Uri.</b>  This has the same result
5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * as the previous suggestion, but provides the Data Uri in a different way.
5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *   <ul>
5569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *   <li><b>Action:</b> {@link android.content.Intent#ACTION_VIEW ACTION_VIEW}</li>
5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *   <li><b>Data:</b> The search manager will assemble a Data Uri using the following elements:
5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *   a Uri fragment provided in your XML metadata (android:searchSuggestIntentData), followed by
5599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *   a single "/", followed by the value found in the {@link #SUGGEST_COLUMN_INTENT_DATA_ID}
5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *   entry in your cursor.</li>
5619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *   <li><b>Query:</b> query text supplied with the suggestion (probably ignored)</li>
5629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *   </ul>
5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * </li>
5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * </ul>
5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>This list is not meant to be exhaustive.  Applications should feel free to define other types
5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * of suggestions.  For example, you could reduce long lists of results to summaries, and use one
5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * of the above intents (or one of your own) with specially formatted Data Uri's to display more
5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * detailed results.  Or you could display textual shortcuts as suggestions, but launch a display
5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * in a more data-appropriate format such as media artwork.
5709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
5719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p><b>Suggestion Rewriting.</b>  If the user navigates through the suggestions list, the UI
5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * may temporarily rewrite the user's query with a query that matches the currently selected
5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * suggestion.  This enables the user to see what query is being suggested, and also allows the user
5749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * to click or touch in the entry EditText element and make further edits to the query before
5759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * dispatching it.  In order to perform this correctly, the Search UI needs to know exactly what
5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * text to rewrite the query with.
5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>For each suggestion, the following logic is used to select a new query string:
5799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <ul><li>If the suggestion provides an explicit value in the {@link #SUGGEST_COLUMN_QUERY}
5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * column, this value will be used.</li>
5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <li>If the metadata includes the queryRewriteFromData flag, and the suggestion provides an
5829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * explicit value for the intent Data field, this Uri will be used.  Note that this should only be
5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * used with Uri's that are intended to be user-visible, such as HTTP.  Internal Uri schemes should
5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * not be used in this way.</li>
5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <li>If the metadata includes the queryRewriteFromText flag, the text in
5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link #SUGGEST_COLUMN_TEXT_1} will be used.  This should be used for suggestions in which no
5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * query text is provided and the SUGGEST_COLUMN_INTENT_DATA values are not suitable for user
5889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * inspection and editing.</li></ul>
5899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
590590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen * <a name="ExposingSearchSuggestionsToQuickSearchBox"></a>
591590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen * <h3>Exposing Search Suggestions to Quick Search Box</h3>
592590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen *
59305b775e0b7180e33df0303b9e132931f4895357cMike LeBeau * <p>Once your application is set up to provide search suggestions, making them available to the
594590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen * globally accessable Quick Search Box is as easy as setting android:includeInGlobalSearch to
595590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen * "true" in your searchable metadata file.  Beyond that, here are some more details of how
596590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen * suggestions interact with Quick Search Box, and optional ways that you may customize suggestions
597590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen * for your application.
59805b775e0b7180e33df0303b9e132931f4895357cMike LeBeau *
59905b775e0b7180e33df0303b9e132931f4895357cMike LeBeau * <p><b>Important Note:</b>  By default, your application will not be enabled as a suggestion
60005b775e0b7180e33df0303b9e132931f4895357cMike LeBeau * provider (or "searchable item") in Quick Search Box. Once your app is installed, the user must
60105b775e0b7180e33df0303b9e132931f4895357cMike LeBeau * enable it as a "searchable item" in the Search settings in order to receive your app's
60205b775e0b7180e33df0303b9e132931f4895357cMike LeBeau * suggestions in Quick Search Box. You should consider how to message this to users of your app -
60305b775e0b7180e33df0303b9e132931f4895357cMike LeBeau * perhaps with a note to the user the first time they launch the app about how to enable search
60405b775e0b7180e33df0303b9e132931f4895357cMike LeBeau * suggestions. This gives your app a chance to be queried for suggestions as the user types into
60505b775e0b7180e33df0303b9e132931f4895357cMike LeBeau * Quick Search Box, though exactly how or if your suggestions will be surfaced is decided by Quick
60605b775e0b7180e33df0303b9e132931f4895357cMike LeBeau * Search Box.
607590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen *
608590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen * <p><b>Source Ranking:</b>  Once your application's search results are made available to Quick
60905b775e0b7180e33df0303b9e132931f4895357cMike LeBeau * Search Box, how they surface to the user for a particular query will be determined as appropriate
61005b775e0b7180e33df0303b9e132931f4895357cMike LeBeau * by Quick Search Box ranking. This may depend on how many other apps have results for that query,
61105b775e0b7180e33df0303b9e132931f4895357cMike LeBeau * and how often the user has clicked on your results compared to the other apps - but there is no
61205b775e0b7180e33df0303b9e132931f4895357cMike LeBeau * guarantee about how ranking will occur, or whether your app's suggestions will show at all for
61305b775e0b7180e33df0303b9e132931f4895357cMike LeBeau * a given query.  In general, you can expect that providing quality results will increase the
61405b775e0b7180e33df0303b9e132931f4895357cMike LeBeau * likelihood that your app's suggestions are provided in a prominent position, and apps that
61505b775e0b7180e33df0303b9e132931f4895357cMike LeBeau * provide lower quality suggestions will be more likely to be ranked lower and/or not displayed.
616590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen *
617590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen * <p><b>Search Settings:</b>  Each app that is available to Quick Search Box has an entry in the
618590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen * system settings where the user can enable or disable the inclusion of its results.  Below the
619590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen * name of the application, each application may provide a brief description of what kind of
620590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen * information will be made available via a search settings description string pointed to by the
62105b775e0b7180e33df0303b9e132931f4895357cMike LeBeau * android:searchSettingsDescription attribute in the searchable metadata. Note that the
62205b775e0b7180e33df0303b9e132931f4895357cMike LeBeau * user will need to visit this settings menu to enable search suggestions for your app before your
62305b775e0b7180e33df0303b9e132931f4895357cMike LeBeau * app will have a chance to provide search suggestions to Quick Search Box - see the section
62405b775e0b7180e33df0303b9e132931f4895357cMike LeBeau * called "Important Note" above.
625590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen *
62605b775e0b7180e33df0303b9e132931f4895357cMike LeBeau * <p><b>Shortcuts:</b>  Suggestions that are clicked on by the user may be automatically made into
62705b775e0b7180e33df0303b9e132931f4895357cMike LeBeau * shortcuts, which are suggestions that have been copied from your provider in order to be quickly
62805b775e0b7180e33df0303b9e132931f4895357cMike LeBeau * displayed without the need to re-query the original sources. Shortcutted suggestions may be
62905b775e0b7180e33df0303b9e132931f4895357cMike LeBeau * displayed for the query that yielded the suggestion and for any prefixes of that query. You can
63005b775e0b7180e33df0303b9e132931f4895357cMike LeBeau * request how to have your app's suggestions made into shortcuts, and whether they should be
63105b775e0b7180e33df0303b9e132931f4895357cMike LeBeau * refreshed, using the {@link #SUGGEST_COLUMN_SHORTCUT_ID} column:
632590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen * <ul><li>Suggestions that do not include a shortcut id column will be made into shortcuts and
633590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen * never refreshed.  This makes sense for suggestions that refer to data that will never be changed
634590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen * or removed.</li>
635590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen * <li>Suggestions that include a shortcut id will be re-queried for a fresh version of the
636590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen * suggestion each time the shortcut is displayed.  The shortcut will be quickly displayed with
637590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen * whatever data was most recently available until the refresh query returns, after which the
638590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen * suggestion will be dynamically refreshed with the up to date information.  The shortcut refresh
639590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen * query will be sent to your suggestion provider with a uri of {@link #SUGGEST_URI_PATH_SHORTCUT}.
640590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen * The result should contain one suggestion using the same columns as the suggestion query, or be
641590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen * empty, indicating that the shortcut is no longer valid.  Shortcut ids make sense when referring
642590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen * to data that may change over time, such as a contact's presence status.  If a suggestion refers
643590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen * to data that could take longer to refresh, such as a network based refresh of a stock quote, you
644590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen * may include {@link #SUGGEST_COLUMN_SPINNER_WHILE_REFRESHING} to show a progress spinner for the
645590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen * right hand icon until the refresh is complete.</li>
646590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen * <li>Finally, to prevent a suggestion from being copied into a shortcut, you may provide a
647590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen * shortcut id with a value of {@link #SUGGEST_NEVER_MAKE_SHORTCUT}.</li></ul>
648590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen *
64905b775e0b7180e33df0303b9e132931f4895357cMike LeBeau * Note that Quick Search Box will ultimately decide whether to shortcut your app's suggestions,
65005b775e0b7180e33df0303b9e132931f4895357cMike LeBeau * considering these values as a strong request from your application.
65105b775e0b7180e33df0303b9e132931f4895357cMike LeBeau *
6529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <a name="ActionKeys"></a>
6539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <h3>Action Keys</h3>
6549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
6559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>Searchable activities may also wish to provide shortcuts based on the various action keys
6569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * available on the device.  The most basic example of this is the contacts app, which enables the
6579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * green "dial" key for quick access during searching.  Not all action keys are available on
6589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * every device, and not all are allowed to be overriden in this way.  (For example, the "Home"
6599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * key must always return to the home screen, with no exceptions.)
6609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
6619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>In order to define action keys for your searchable application, you must do two things.
6629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
6639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <ul>
6649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <li>You'll add one or more <i>actionkey</i> elements to your searchable metadata configuration
6659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * file.  Each element defines one of the keycodes you are interested in,
6669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * defines the conditions under which they are sent, and provides details
6679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * on how to communicate the action key event back to your searchable activity.</li>
6689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <li>In your broadcast receiver, if you wish, you can check for action keys by checking the
6699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * extras field of the {@link android.content.Intent Intent}.</li>
6709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * </ul>
6719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
6729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p><b>Updating metadata.</b>  For each keycode of interest, you must add an &lt;actionkey&gt;
6739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * element.  Within this element you must define two or three attributes.  The first attribute,
6749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * &lt;android:keycode&gt;, is required;  It is the key code of the action key event, as defined in
6759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link android.view.KeyEvent}.  The remaining two attributes define the value of the actionkey's
6769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <i>message</i>, which will be passed to your searchable activity in the
6779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link android.content.Intent Intent} (see below for more details).  Although each of these
6789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * attributes is optional, you must define one or both for the action key to have any effect.
6799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * &lt;android:queryActionMsg&gt; provides the message that will be sent if the action key is
6809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * pressed while the user is simply entering query text.  &lt;android:suggestActionMsgColumn&gt;
6819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * is used when action keys are tied to specific suggestions.  This attribute provides the name
6829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * of a <i>column</i> in your suggestion cursor;  The individual suggestion, in that column,
6839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * provides the message.  (If the cell is empty or null, that suggestion will not work with that
6849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * action key.)
6859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>See the <a href="#SearchabilityMetadata">Searchability Metadata</a> section for more details
6869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * and examples.
6879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
6889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p><b>Receiving Action Keys</b>  Intents launched by action keys will be specially marked
6899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * using a combination of values.  This enables your searchable application to examine the intent,
6909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * if necessary, and perform special processing.  For example, clicking a suggested contact might
6919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * simply display them;  Selecting a suggested contact and clicking the dial button might
6929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * immediately call them.
6939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
6949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>When a search {@link android.content.Intent Intent} is launched by an action key, two values
6959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * will be added to the extras field.
6969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <ul>
6979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <li>To examine the key code, use {@link android.content.Intent#getIntExtra
6989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * getIntExtra(SearchManager.ACTION_KEY)}.</li>
6999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <li>To examine the message string, use {@link android.content.Intent#getStringExtra
7009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * getStringExtra(SearchManager.ACTION_MSG)}</li>
7019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * </ul>
7029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
7039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <a name="SearchabilityMetadata"></a>
7049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <h3>Searchability Metadata</h3>
7059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
7069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>Every activity that is searchable must provide a small amount of additional information
7079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * in order to properly configure the search system.  This controls the way that your search
7089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * is presented to the user, and controls for the various modalities described previously.
7099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
7109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>If your application is not searchable,
7119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * then you do not need to provide any search metadata, and you can skip the rest of this section.
7129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * When this search metadata cannot be found, the search manager will assume that the activity
7139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * does not implement search.  (Note: to implement web-based search, you will need to add
7149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the android.app.default_searchable metadata to your manifest, as shown below.)
7159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
7169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>Values you supply in metadata apply only to each local searchable activity.  Each
7179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * searchable activity can define a completely unique search experience relevant to its own
7189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * capabilities and user experience requirements, and a single application can even define multiple
7199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * searchable activities.
7209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
7219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p><b>Metadata for searchable activity.</b>  As with your search implementations described
7229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * above, you must first identify which of your activities is searchable.  In the
7239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <a href="{@docRoot}guide/topics/manifest/manifest-intro.html">manifest</a> entry for this activity, you must
7249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * provide two elements:
7259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <ul><li>An intent-filter specifying that you can receive and process the
7269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link android.content.Intent#ACTION_SEARCH ACTION_SEARCH} {@link android.content.Intent Intent}.
7279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * </li>
7289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <li>A reference to a small XML file (typically called "searchable.xml") which contains the
7299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * remaining configuration information for how your application implements search.</li></ul>
7309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
7319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>Here is a snippet showing the necessary elements in the
7329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <a href="{@docRoot}guide/topics/manifest/manifest-intro.html">manifest</a> entry for your searchable activity.
7339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <pre class="prettyprint">
7349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *        &lt;!-- Search Activity - searchable --&gt;
7359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *        &lt;activity android:name="MySearchActivity"
7369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *                  android:label="Search"
7379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *                  android:launchMode="singleTop"&gt;
7389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *            &lt;intent-filter&gt;
7399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *                &lt;action android:name="android.intent.action.SEARCH" /&gt;
7409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *                &lt;category android:name="android.intent.category.DEFAULT" /&gt;
7419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *            &lt;/intent-filter&gt;
7429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *            &lt;meta-data android:name="android.app.searchable"
7439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *                       android:resource="@xml/searchable" /&gt;
7449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *        &lt;/activity&gt;</pre>
7459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
7469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>Next, you must provide the rest of the searchability configuration in
7479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the small XML file, stored in the ../xml/ folder in your build.  The XML file is a
7489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * simple enumeration of the search configuration parameters for searching within this activity,
7499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * application, or package.  Here is a sample XML file (named searchable.xml, for use with
7509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the above manifest) for a query-search activity.
7519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
7529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <pre class="prettyprint">
7539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * &lt;searchable xmlns:android="http://schemas.android.com/apk/res/android"
7549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *     android:label="@string/search_label"
7559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *     android:hint="@string/search_hint" &gt;
7569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * &lt;/searchable&gt;</pre>
7579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
7589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>Note that all user-visible strings <i>must</i> be provided in the form of "@string"
7599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * references.  Hard-coded strings, which cannot be localized, will not work properly in search
7609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * metadata.
7619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
7629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>Attributes you can set in search metadata:
7639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <table border="2" width="85%" align="center" frame="hsides" rules="rows">
7649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
7659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *     <thead>
7669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *     <tr><th>Attribute</th> <th>Description</th> <th>Required?</th></tr>
7679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *     </thead>
7689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
7699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *     <tbody>
7709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *     <tr><th>android:label</th>
7719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *         <td>This is the name for your application that will be presented to the user in a
7729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *             list of search targets, or in the search box as a label.</td>
7739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *         <td align="center">Yes</td>
7749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *     </tr>
7759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
7769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *     <tr><th>android:icon</th>
777dbc7e27ef10349f11ac940d59ff4f812319fce51Scott Main *         <td><strong>This is deprecated.</strong><br/>The default
778dbc7e27ef10349f11ac940d59ff4f812319fce51Scott Main *           application icon is now always used, so this attribute is
779dbc7e27ef10349f11ac940d59ff4f812319fce51Scott Main *           obsolete.</td>
7809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *         <td align="center">No</td>
7819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *     </tr>
7829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
7839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *     <tr><th>android:hint</th>
784dbc7e27ef10349f11ac940d59ff4f812319fce51Scott Main *         <td>This is the text to display in the search text field when no text
785dbc7e27ef10349f11ac940d59ff4f812319fce51Scott Main *             has been entered by the user.</td>
7869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *         <td align="center">No</td>
7879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *     </tr>
7889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
7899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *     <tr><th>android:searchMode</th>
7909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *         <td>If provided and non-zero, sets additional modes for control of the search
7919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *             presentation.  The following mode bits are defined:
7929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *             <table border="2" align="center" frame="hsides" rules="rows">
7939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *                 <tbody>
7949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *                 <tr><th>showSearchLabelAsBadge</th>
7959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *                     <td>If set, this flag enables the display of the search target (label)
796dbc7e27ef10349f11ac940d59ff4f812319fce51Scott Main *                         above the search box. As an alternative, you may
797dbc7e27ef10349f11ac940d59ff4f812319fce51Scott Main *                         want to instead use "hint" text in the search box.
798dbc7e27ef10349f11ac940d59ff4f812319fce51Scott Main *                         See the "android:hint" attribute above.</td>
7999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *                 </tr>
8009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *                 <tr><th>showSearchIconAsBadge</th>
801dbc7e27ef10349f11ac940d59ff4f812319fce51Scott Main *                     <td><strong>This is deprecated.</strong><br/>The default
802dbc7e27ef10349f11ac940d59ff4f812319fce51Scott Main *                         application icon is now always used, so this
803dbc7e27ef10349f11ac940d59ff4f812319fce51Scott Main *                         option is obsolete.</td>
8049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *                 </tr>
8059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *                 <tr><th>queryRewriteFromData</th>
8069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *                     <td>If set, this flag causes the suggestion column SUGGEST_COLUMN_INTENT_DATA
8079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *                         to be considered as the text for suggestion query rewriting.  This should
8089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *                         only be used when the values in SUGGEST_COLUMN_INTENT_DATA are suitable
8099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *                         for user inspection and editing - typically, HTTP/HTTPS Uri's.</td>
8109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *                 </tr>
8119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *                 <tr><th>queryRewriteFromText</th>
8129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *                     <td>If set, this flag causes the suggestion column SUGGEST_COLUMN_TEXT_1 to
8139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *                         be considered as the text for suggestion query rewriting.  This should
8149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *                         be used for suggestions in which no query text is provided and the
8159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *                         SUGGEST_COLUMN_INTENT_DATA values are not suitable for user inspection
8169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *                         and editing.</td>
8179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *                 </tr>
8189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *                 </tbody>
81905b775e0b7180e33df0303b9e132931f4895357cMike LeBeau *            </table>
82005b775e0b7180e33df0303b9e132931f4895357cMike LeBeau *            Note that the icon of your app will likely be shown alongside any badge you specify,
82105b775e0b7180e33df0303b9e132931f4895357cMike LeBeau *            to differentiate search in your app from Quick Search Box. The display of this icon
82205b775e0b7180e33df0303b9e132931f4895357cMike LeBeau *            is not under the app's control.
82305b775e0b7180e33df0303b9e132931f4895357cMike LeBeau *         </td>
82405b775e0b7180e33df0303b9e132931f4895357cMike LeBeau *
8259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *         <td align="center">No</td>
8269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *     </tr>
8279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
8289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *     <tr><th>android:inputType</th>
8299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *         <td>If provided, supplies a hint about the type of search text the user will be
8309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *             entering.  For most searches, in which free form text is expected, this attribute
8319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *             need not be provided.  Suitable values for this attribute are described in the
8329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *             <a href="../R.attr.html#inputType">inputType</a> attribute.</td>
8339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *         <td align="center">No</td>
8349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *     </tr>
8359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *     <tr><th>android:imeOptions</th>
8369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *         <td>If provided, supplies additional options for the input method.
8379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *             For most searches, in which free form text is expected, this attribute
8389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *             need not be provided, and will default to "actionSearch".
8399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *             Suitable values for this attribute are described in the
8409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *             <a href="../R.attr.html#imeOptions">imeOptions</a> attribute.</td>
8419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *         <td align="center">No</td>
8429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *     </tr>
8439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
8449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *     </tbody>
8459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * </table>
8469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
8479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p><b>Styleable Resources in your Metadata.</b>  It's possible to provide alternate strings
8489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * for your searchable application, in order to provide localization and/or to better visual
8499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * presentation on different device configurations.  Each searchable activity has a single XML
8509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * metadata file, but any resource references can be replaced at runtime based on device
8519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * configuration, language setting, and other system inputs.
8529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
8539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>A concrete example is the "hint" text you supply using the android:searchHint attribute.
8549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * In portrait mode you'll have less screen space and may need to provide a shorter string, but
8559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * in landscape mode you can provide a longer, more descriptive hint.  To do this, you'll need to
8569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * define two or more strings.xml files, in the following directories:
8579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <ul><li>.../res/values-land/strings.xml</li>
8589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <li>.../res/values-port/strings.xml</li>
8599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <li>.../res/values/strings.xml</li></ul>
8609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
8619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>For more complete documentation on this capability, see
8629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <a href="{@docRoot}guide/topics/resources/resources-i18n.html#AlternateResources">Resources and
8639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Internationalization: Alternate Resources</a>.
8649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
8659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p><b>Metadata for non-searchable activities.</b>  Activities which are part of a searchable
8669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * application, but don't implement search itself, require a bit of "glue" in order to cause
8679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * them to invoke search using your searchable activity as their primary context.  If this is not
8689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * provided, then searches from these activities will use the system default search context.
8699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
8709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>The simplest way to specify this is to add a <i>search reference</i> element to the
8719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * application entry in the <a href="{@docRoot}guide/topics/manifest/manifest-intro.html">manifest</a> file.
8729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The value of this reference can be either of:
8739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <ul><li>The name of your searchable activity.
8749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * It is typically prefixed by '.' to indicate that it's in the same package.</li>
8759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <li>A "*" indicates that the system may select a default searchable activity, in which
8769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * case it will typically select web-based search.</li>
8779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * </ul>
8789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
8799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>Here is a snippet showing the necessary addition to the manifest entry for your
8809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * non-searchable activities.
8819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <pre class="prettyprint">
8829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *        &lt;application&gt;
8839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *            &lt;meta-data android:name="android.app.default_searchable"
8849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *                       android:value=".MySearchActivity" /&gt;
8859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
8869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *            &lt;!-- followed by activities, providers, etc... --&gt;
8879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *        &lt;/application&gt;</pre>
8889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
8899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>You can also specify android.app.default_searchable on a per-activity basis, by including
8909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the meta-data element (as shown above) in one or more activity sections.  If found, these will
8919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * override the reference in the application section.  The only reason to configure your application
8929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * this way would be if you wish to partition it into separate sections with different search
8939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * behaviors;  Otherwise this configuration is not recommended.
8949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
8954c156ec6ec9adcb407189ee57e0c205039b60148Andy Stadler * <p><b>Additional metadata for search suggestions.</b>  If you have defined a content provider
8969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * to generate search suggestions, you'll need to publish it to the system, and you'll need to
8979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * provide a bit of additional XML metadata in order to configure communications with it.
8989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
8999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>First, in your <a href="{@docRoot}guide/topics/manifest/manifest-intro.html">manifest</a>, you'll add the
9009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * following lines.
9019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <pre class="prettyprint">
9029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *        &lt;!-- Content provider for search suggestions --&gt;
9039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *        &lt;provider android:name="YourSuggestionProviderClass"
9049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *                android:authorities="your.suggestion.authority" /&gt;</pre>
9059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
9069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>Next, you'll add a few lines to your XML metadata file, as shown:
9079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <pre class="prettyprint">
9089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *     &lt;!-- Required attribute for any suggestions provider --&gt;
9099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *     android:searchSuggestAuthority="your.suggestion.authority"
9109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
9119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *     &lt;!-- Optional attribute for configuring queries --&gt;
9129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *     android:searchSuggestSelection="field =?"
9139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
9149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *     &lt;!-- Optional attributes for configuring intent construction --&gt;
9159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *     android:searchSuggestIntentAction="intent action string"
9169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *     android:searchSuggestIntentData="intent data Uri" /&gt;</pre>
9179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
9189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>Elements of search metadata that support suggestions:
9199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <table border="2" width="85%" align="center" frame="hsides" rules="rows">
9209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
9219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *     <thead>
9229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *     <tr><th>Attribute</th> <th>Description</th> <th>Required?</th></tr>
9239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *     </thead>
9249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
9259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *     <tbody>
9269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *     <tr><th>android:searchSuggestAuthority</th>
9279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *         <td>This value must match the authority string provided in the <i>provider</i> section
9289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *             of your <a href="{@docRoot}guide/topics/manifest/manifest-intro.html">manifest</a>.</td>
9299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *         <td align="center">Yes</td>
9309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *     </tr>
9319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
9329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *     <tr><th>android:searchSuggestPath</th>
9339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *         <td>If provided, this will be inserted in the suggestions query Uri, after the authority
9349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *             you have provide but before the standard suggestions path.  This is only required if
9359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *             you have a single content provider issuing different types of suggestions (e.g. for
9369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *             different data types) and you need a way to disambiguate the suggestions queries
9379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *             when they are received.</td>
9389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *         <td align="center">No</td>
9399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *     </tr>
9409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
9419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *     <tr><th>android:searchSuggestSelection</th>
9429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *         <td>If provided, this value will be passed into your query function as the
9439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *             <i>selection</i> parameter.  Typically this will be a WHERE clause for your database,
9449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *             and will contain a single question mark, which represents the actual query string
9459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *             that has been typed by the user.  However, you can also use any non-null value
9469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *             to simply trigger the delivery of the query text (via selection arguments), and then
9479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *             use the query text in any way appropriate for your provider (ignoring the actual
9489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *             text of the selection parameter.)</td>
9499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *         <td align="center">No</td>
9509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *     </tr>
9519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
9529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *     <tr><th>android:searchSuggestIntentAction</th>
9539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *         <td>If provided, and not overridden by the selected suggestion, this value will be
9549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *             placed in the action field of the {@link android.content.Intent Intent} when the
9559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *             user clicks a suggestion.</td>
9569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *         <td align="center">No</td>
9579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
9589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *     <tr><th>android:searchSuggestIntentData</th>
9599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *         <td>If provided, and not overridden by the selected suggestion, this value will be
9609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *             placed in the data field of the {@link android.content.Intent Intent} when the user
9619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *             clicks a suggestion.</td>
9629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *         <td align="center">No</td>
9639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *     </tr>
9649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
9659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *     </tbody>
9669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * </table>
967b5041368524045b6714081d14ff3c6b22598aab1Karl Rosaen *
968590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen * <p>Elements of search metadata that configure search suggestions being available to Quick Search
969590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen * Box:
970590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen * <table border="2" width="85%" align="center" frame="hsides" rules="rows">
971590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen *
972590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen *     <thead>
973590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen *     <tr><th>Attribute</th> <th>Description</th> <th>Required?</th></tr>
974590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen *     </thead>
975590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen *
976590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen *     <tr><th>android:includeInGlobalSearch</th>
977590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen *         <td>If true, indicates the search suggestions provided by your application should be
978590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen *             included in the globally accessible Quick Search Box.  The attributes below are only
979590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen *             applicable if this is set to true.</td>
980590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen *         <td align="center">Yes</td>
981590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen *     </tr>
982590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen *
983590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen *     <tr><th>android:searchSettingsDescription</th>
984590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen *         <td>If provided, provides a brief description of the search suggestions that are provided
985590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen *             by your application to Quick Search Box, and will be displayed in the search settings
986590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen *             entry for your application.</td>
987590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen *         <td align="center">No</td>
988590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen *     </tr>
989590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen *
990590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen *     <tr><th>android:queryAfterZeroResults</th>
991590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen *         <td>Indicates whether a source should be invoked for supersets of queries it has
992590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen *             returned zero results for in the past.  For example, if a source returned zero
993590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen *             results for "bo", it would be ignored for "bob".  If set to false, this source
994590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen *             will only be ignored for a single session; the next time the search dialog is
995590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen *             invoked, all sources will be queried.  The default value is false.</td>
996590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen *         <td align="center">No</td>
997590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen *     </tr>
998590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen *
999590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen *     <tr><th>android:searchSuggestThreshold</th>
1000590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen *         <td>Indicates the minimum number of characters needed to trigger a source from Quick
1001590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen *             Search Box.  Only guarantees that a source will not be queried for anything shorter
1002590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen *             than the threshold.  The default value is 0.</td>
1003590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen *         <td align="center">No</td>
1004590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen *     </tr>
1005590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen *
1006590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen *     </tbody>
1007590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen * </table>
1008590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen *
10094c156ec6ec9adcb407189ee57e0c205039b60148Andy Stadler * <p><b>Additional metadata for search action keys.</b>  For each action key that you would like to
10109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * define, you'll need to add an additional element defining that key, and using the attributes
10119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * discussed in <a href="#ActionKeys">Action Keys</a>.  A simple example is shown here:
10129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
10139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <pre class="prettyprint">&lt;actionkey
10149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *     android:keycode="KEYCODE_CALL"
10159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *     android:queryActionMsg="call"
10169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *     android:suggestActionMsg="call"
10179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *     android:suggestActionMsgColumn="call_column" /&gt;</pre>
10189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
10199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>Elements of search metadata that support search action keys.  Note that although each of the
10209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * action message elements are marked as <i>optional</i>, at least one must be present for the
10219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * action key to have any effect.
10229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
10239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <table border="2" width="85%" align="center" frame="hsides" rules="rows">
10249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
10259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *     <thead>
10269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *     <tr><th>Attribute</th> <th>Description</th> <th>Required?</th></tr>
10279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *     </thead>
10289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
10299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *     <tbody>
10309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *     <tr><th>android:keycode</th>
10319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *         <td>This attribute denotes the action key you wish to respond to.  Note that not
10329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *             all action keys are actually supported using this mechanism, as many of them are
10339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *             used for typing, navigation, or system functions.  This will be added to the
10349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *             {@link android.content.Intent#ACTION_SEARCH ACTION_SEARCH} intent that is passed to
10359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *             your searchable activity.  To examine the key code, use
10369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *             {@link android.content.Intent#getIntExtra getIntExtra(SearchManager.ACTION_KEY)}.
10379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *             <p>Note, in addition to the keycode, you must also provide one or more of the action
10389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *             specifier attributes.</td>
10399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *         <td align="center">Yes</td>
10409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *     </tr>
10419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
10429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *     <tr><th>android:queryActionMsg</th>
10439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *         <td>If you wish to handle an action key during normal search query entry, you
10449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *          must define an action string here.  This will be added to the
10459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *          {@link android.content.Intent#ACTION_SEARCH ACTION_SEARCH} intent that is passed to your
10469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *          searchable activity.  To examine the string, use
10479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *          {@link android.content.Intent#getStringExtra
10489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *          getStringExtra(SearchManager.ACTION_MSG)}.</td>
10499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *         <td align="center">No</td>
10509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *     </tr>
10519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
10529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *     <tr><th>android:suggestActionMsg</th>
10539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *         <td>If you wish to handle an action key while a suggestion is being displayed <i>and
10549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *             selected</i>, there are two ways to handle this.  If <i>all</i> of your suggestions
10559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *             can handle the action key, you can simply define the action message using this
10569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *             attribute.  This will be added to the
10579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *             {@link android.content.Intent#ACTION_SEARCH ACTION_SEARCH} intent that is passed to
10589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *             your searchable activity.  To examine the string, use
10599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *             {@link android.content.Intent#getStringExtra
10609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *             getStringExtra(SearchManager.ACTION_MSG)}.</td>
10619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *         <td align="center">No</td>
10629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *     </tr>
10639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
10649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *     <tr><th>android:suggestActionMsgColumn</th>
10659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *         <td>If you wish to handle an action key while a suggestion is being displayed <i>and
10669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *             selected</i>, but you do not wish to enable this action key for every suggestion,
10679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *             then you can use this attribute to control it on a suggestion-by-suggestion basis.
10689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *             First, you must define a column (and name it here) where your suggestions will
10699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *             include the action string.  Then, in your content provider, you must provide this
10709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *             column, and when desired, provide data in this column.
10719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *             The search manager will look at your suggestion cursor, using the string
10729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *             provided here in order to select a column, and will use that to select a string from
10739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *             the cursor.  That string will be added to the
10749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *             {@link android.content.Intent#ACTION_SEARCH ACTION_SEARCH} intent that is passed to
10759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *             your searchable activity.  To examine the string, use
10769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *             {@link android.content.Intent#getStringExtra
10779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *             getStringExtra(SearchManager.ACTION_MSG)}.  <i>If the data does not exist for the
10789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *             selection suggestion, the action key will be ignored.</i></td>
10799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *         <td align="center">No</td>
10809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *     </tr>
10819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
10829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *     </tbody>
10839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * </table>
10849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
10854c156ec6ec9adcb407189ee57e0c205039b60148Andy Stadler * <p><b>Additional metadata for enabling voice search.</b>  To enable voice search for your
10864c156ec6ec9adcb407189ee57e0c205039b60148Andy Stadler * activity, you can add fields to the metadata that enable and configure voice search.  When
10874c156ec6ec9adcb407189ee57e0c205039b60148Andy Stadler * enabled (and available on the device), a voice search button will be displayed in the
10884c156ec6ec9adcb407189ee57e0c205039b60148Andy Stadler * Search UI.  Clicking this button will launch a voice search activity.  When the user has
10894c156ec6ec9adcb407189ee57e0c205039b60148Andy Stadler * finished speaking, the voice search phrase will be transcribed into text and presented to the
10904c156ec6ec9adcb407189ee57e0c205039b60148Andy Stadler * searchable activity as if it were a typed query.
10914c156ec6ec9adcb407189ee57e0c205039b60148Andy Stadler *
10924c156ec6ec9adcb407189ee57e0c205039b60148Andy Stadler * <p>Elements of search metadata that support voice search:
10934c156ec6ec9adcb407189ee57e0c205039b60148Andy Stadler * <table border="2" width="85%" align="center" frame="hsides" rules="rows">
10944c156ec6ec9adcb407189ee57e0c205039b60148Andy Stadler *
10954c156ec6ec9adcb407189ee57e0c205039b60148Andy Stadler *     <thead>
10964c156ec6ec9adcb407189ee57e0c205039b60148Andy Stadler *     <tr><th>Attribute</th> <th>Description</th> <th>Required?</th></tr>
10974c156ec6ec9adcb407189ee57e0c205039b60148Andy Stadler *     </thead>
10984c156ec6ec9adcb407189ee57e0c205039b60148Andy Stadler *
10994c156ec6ec9adcb407189ee57e0c205039b60148Andy Stadler *     <tr><th>android:voiceSearchMode</th>
11004c156ec6ec9adcb407189ee57e0c205039b60148Andy Stadler *         <td>If provided and non-zero, enables voice search.  (Voice search may not be
11014c156ec6ec9adcb407189ee57e0c205039b60148Andy Stadler *             provided by the device, in which case these flags will have no effect.)  The
11024c156ec6ec9adcb407189ee57e0c205039b60148Andy Stadler *             following mode bits are defined:
11034c156ec6ec9adcb407189ee57e0c205039b60148Andy Stadler *             <table border="2" align="center" frame="hsides" rules="rows">
11044c156ec6ec9adcb407189ee57e0c205039b60148Andy Stadler *                 <tbody>
11054c156ec6ec9adcb407189ee57e0c205039b60148Andy Stadler *                 <tr><th>showVoiceSearchButton</th>
11064c156ec6ec9adcb407189ee57e0c205039b60148Andy Stadler *                     <td>If set, display a voice search button.  This only takes effect if voice
11074c156ec6ec9adcb407189ee57e0c205039b60148Andy Stadler *                         search is available on the device.  If set, then launchWebSearch or
11084c156ec6ec9adcb407189ee57e0c205039b60148Andy Stadler *                         launchRecognizer must also be set.</td>
11094c156ec6ec9adcb407189ee57e0c205039b60148Andy Stadler *                 </tr>
11104c156ec6ec9adcb407189ee57e0c205039b60148Andy Stadler *                 <tr><th>launchWebSearch</th>
11114c156ec6ec9adcb407189ee57e0c205039b60148Andy Stadler *                     <td>If set, the voice search button will take the user directly to a
11124c156ec6ec9adcb407189ee57e0c205039b60148Andy Stadler *                         built-in voice web search activity.  Most applications will not use this
11134c156ec6ec9adcb407189ee57e0c205039b60148Andy Stadler *                         flag, as it will take the user away from the activity in which search
11144c156ec6ec9adcb407189ee57e0c205039b60148Andy Stadler *                         was invoked.</td>
11154c156ec6ec9adcb407189ee57e0c205039b60148Andy Stadler *                 </tr>
11164c156ec6ec9adcb407189ee57e0c205039b60148Andy Stadler *                 <tr><th>launchRecognizer</th>
11174c156ec6ec9adcb407189ee57e0c205039b60148Andy Stadler *                     <td>If set, the voice search button will take the user directly to a
11184c156ec6ec9adcb407189ee57e0c205039b60148Andy Stadler *                         built-in voice recording activity.  This activity will prompt the user
11194c156ec6ec9adcb407189ee57e0c205039b60148Andy Stadler *                         to speak, transcribe the spoken text, and forward the resulting query
11204c156ec6ec9adcb407189ee57e0c205039b60148Andy Stadler *                         text to the searchable activity, just as if the user had typed it into
11214c156ec6ec9adcb407189ee57e0c205039b60148Andy Stadler *                         the search UI and clicked the search button.</td>
11224c156ec6ec9adcb407189ee57e0c205039b60148Andy Stadler *                 </tr>
11234c156ec6ec9adcb407189ee57e0c205039b60148Andy Stadler *                 </tbody>
11244c156ec6ec9adcb407189ee57e0c205039b60148Andy Stadler *            </table></td>
11254c156ec6ec9adcb407189ee57e0c205039b60148Andy Stadler *         <td align="center">No</td>
11264c156ec6ec9adcb407189ee57e0c205039b60148Andy Stadler *     </tr>
11274c156ec6ec9adcb407189ee57e0c205039b60148Andy Stadler *
11284c156ec6ec9adcb407189ee57e0c205039b60148Andy Stadler *     <tr><th>android:voiceLanguageModel</th>
11294c156ec6ec9adcb407189ee57e0c205039b60148Andy Stadler *         <td>If provided, this specifies the language model that should be used by the voice
11304c156ec6ec9adcb407189ee57e0c205039b60148Andy Stadler *             recognition system.
11314c156ec6ec9adcb407189ee57e0c205039b60148Andy Stadler *             See {@link android.speech.RecognizerIntent#EXTRA_LANGUAGE_MODEL}
11324c156ec6ec9adcb407189ee57e0c205039b60148Andy Stadler *             for more information.  If not provided, the default value
11334c156ec6ec9adcb407189ee57e0c205039b60148Andy Stadler *             {@link android.speech.RecognizerIntent#LANGUAGE_MODEL_FREE_FORM} will be used.</td>
11344c156ec6ec9adcb407189ee57e0c205039b60148Andy Stadler *         <td align="center">No</td>
11354c156ec6ec9adcb407189ee57e0c205039b60148Andy Stadler *     </tr>
11364c156ec6ec9adcb407189ee57e0c205039b60148Andy Stadler *
11374c156ec6ec9adcb407189ee57e0c205039b60148Andy Stadler *     <tr><th>android:voicePromptText</th>
11384c156ec6ec9adcb407189ee57e0c205039b60148Andy Stadler *         <td>If provided, this specifies a prompt that will be displayed during voice input.
11394c156ec6ec9adcb407189ee57e0c205039b60148Andy Stadler *             (If not provided, a default prompt will be displayed.)</td>
11404c156ec6ec9adcb407189ee57e0c205039b60148Andy Stadler *         <td align="center">No</td>
11414c156ec6ec9adcb407189ee57e0c205039b60148Andy Stadler *     </tr>
11424c156ec6ec9adcb407189ee57e0c205039b60148Andy Stadler *
11434c156ec6ec9adcb407189ee57e0c205039b60148Andy Stadler *     <tr><th>android:voiceLanguage</th>
11444c156ec6ec9adcb407189ee57e0c205039b60148Andy Stadler *         <td>If provided, this specifies the spoken language to be expected.  This is only
11454c156ec6ec9adcb407189ee57e0c205039b60148Andy Stadler *             needed if it is different from the current value of
11464c156ec6ec9adcb407189ee57e0c205039b60148Andy Stadler *             {@link java.util.Locale#getDefault()}.
11474c156ec6ec9adcb407189ee57e0c205039b60148Andy Stadler *             </td>
11484c156ec6ec9adcb407189ee57e0c205039b60148Andy Stadler *         <td align="center">No</td>
11494c156ec6ec9adcb407189ee57e0c205039b60148Andy Stadler *     </tr>
11504c156ec6ec9adcb407189ee57e0c205039b60148Andy Stadler *
11514c156ec6ec9adcb407189ee57e0c205039b60148Andy Stadler *     <tr><th>android:voiceMaxResults</th>
11524c156ec6ec9adcb407189ee57e0c205039b60148Andy Stadler *         <td>If provided, enforces the maximum number of results to return, including the "best"
11534c156ec6ec9adcb407189ee57e0c205039b60148Andy Stadler *             result which will always be provided as the SEARCH intent's primary query.  Must be
11544c156ec6ec9adcb407189ee57e0c205039b60148Andy Stadler *             one or greater.  Use {@link android.speech.RecognizerIntent#EXTRA_RESULTS}
11554c156ec6ec9adcb407189ee57e0c205039b60148Andy Stadler *             to get the results from the intent.  If not provided, the recognizer will choose
11564c156ec6ec9adcb407189ee57e0c205039b60148Andy Stadler *             how many results to return.</td>
11574c156ec6ec9adcb407189ee57e0c205039b60148Andy Stadler *         <td align="center">No</td>
11584c156ec6ec9adcb407189ee57e0c205039b60148Andy Stadler *     </tr>
11594c156ec6ec9adcb407189ee57e0c205039b60148Andy Stadler *
11604c156ec6ec9adcb407189ee57e0c205039b60148Andy Stadler *     </tbody>
11614c156ec6ec9adcb407189ee57e0c205039b60148Andy Stadler * </table>
11624c156ec6ec9adcb407189ee57e0c205039b60148Andy Stadler *
11639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <a name="PassingSearchContext"></a>
11649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <h3>Passing Search Context</h3>
11659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
11669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>In order to improve search experience, an application may wish to specify
11679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * additional data along with the search, such as local history or context.  For
11689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * example, a maps search would be improved by including the current location.
11699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * In order to simplify the structure of your activities, this can be done using
11709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the search manager.
11719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
11729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>Any data can be provided at the time the search is launched, as long as it
11739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * can be stored in a {@link android.os.Bundle Bundle} object.
11749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
11759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>To pass application data into the Search Manager, you'll need to override
11769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link android.app.Activity#onSearchRequested onSearchRequested} as follows:
11779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
11789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <pre class="prettyprint">
11799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * &#64;Override
11809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * public boolean onSearchRequested() {
11819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *     Bundle appData = new Bundle();
11829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *     appData.put...();
11839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *     appData.put...();
11846b13bc043e715b5415b701e93141daa0d49fa364Dirk Dougherty *     startSearch(null, false, appData, false);
11859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *     return true;
11869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * }</pre>
11879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
11889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>To receive application data from the Search Manager, you'll extract it from
11899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the {@link android.content.Intent#ACTION_SEARCH ACTION_SEARCH}
11909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link android.content.Intent Intent} as follows:
11919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
11929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <pre class="prettyprint">
11939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * final Bundle appData = queryIntent.getBundleExtra(SearchManager.APP_DATA);
11949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * if (appData != null) {
11959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *     appData.get...();
11969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *     appData.get...();
11979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * }</pre>
11989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
11999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <a name="ProtectingUserPrivacy"></a>
12009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <h3>Protecting User Privacy</h3>
12019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
12029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>Many users consider their activities on the phone, including searches, to be private
12039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * information.  Applications that implement search should take steps to protect users' privacy
12049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * wherever possible.  This section covers two areas of concern, but you should consider your search
12059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * design carefully and take any additional steps necessary.
12069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
12079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p><b>Don't send personal information to servers, and if you do, don't log it.</b>
12089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * "Personal information" is information that can personally identify your users, such as name,
12099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * email address or billing information, or other data which can be reasonably linked to such
12109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * information.  If your application implements search with the assistance of a server, try to
12119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * avoid sending personal information with your searches.  For example, if you are searching for
12129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * businesses near a zip code, you don't need to send the user ID as well - just send the zip code
12139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * to the server.  If you do need to send personal information, you should take steps to avoid
12149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * logging it.  If you must log it, you should protect that data very carefully, and erase it as
12159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * soon as possible.
12169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
12179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p><b>Provide the user with a way to clear their search history.</b>  The Search Manager helps
12189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * your application provide context-specific suggestions.  Sometimes these suggestions are based
12199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * on previous searches, or other actions taken by the user in an earlier session.  A user may not
12209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * wish for previous searches to be revealed to other users, for instance if they share their phone
12219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * with a friend.  If your application provides suggestions that can reveal previous activities,
12229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you should implement a "Clear History" menu, preference, or button.  If you are using
12239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link android.provider.SearchRecentSuggestions}, you can simply call its
12249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link android.provider.SearchRecentSuggestions#clearHistory() clearHistory()} method from
12259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * your "Clear History" UI.  If you are implementing your own form of recent suggestions, you'll
12269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * need to provide a similar a "clear history" API in your provider, and call it from your
12279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * "Clear History" UI.
12289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
12299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class SearchManager
12309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        implements DialogInterface.OnDismissListener, DialogInterface.OnCancelListener
12319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
12328d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert
12338d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert    private static final boolean DBG = false;
12348d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert    private static final String TAG = "SearchManager";
12358d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert
12369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
12379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * This is a shortcut definition for the default menu key to use for invoking search.
12389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
12399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * See Menu.Item.setAlphabeticShortcut() for more information.
12409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
12419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public final static char MENU_KEY = 's';
12429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
12449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * This is a shortcut definition for the default menu key to use for invoking search.
12459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
12469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * See Menu.Item.setAlphabeticShortcut() for more information.
12479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
12489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public final static int MENU_KEYCODE = KeyEvent.KEYCODE_S;
12499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
12519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Intent extra data key: Use this key with
12529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link android.content.Intent#getStringExtra
12539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *  content.Intent.getStringExtra()}
12549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * to obtain the query string from Intent.ACTION_SEARCH.
12559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
12569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public final static String QUERY = "query";
12579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
12595f80605a0b866f34c74955e190909bd6ab5d992eBjorn Bringert     * Intent extra data key: Use this key with
12605f80605a0b866f34c74955e190909bd6ab5d992eBjorn Bringert     * {@link android.content.Intent#getStringExtra
12615f80605a0b866f34c74955e190909bd6ab5d992eBjorn Bringert     *  content.Intent.getStringExtra()}
12625f80605a0b866f34c74955e190909bd6ab5d992eBjorn Bringert     * to obtain the query string typed in by the user.
12635f80605a0b866f34c74955e190909bd6ab5d992eBjorn Bringert     * This may be different from the value of {@link #QUERY}
12645f80605a0b866f34c74955e190909bd6ab5d992eBjorn Bringert     * if the intent is the result of selecting a suggestion.
12655f80605a0b866f34c74955e190909bd6ab5d992eBjorn Bringert     * In that case, {@link #QUERY} will contain the value of
12665f80605a0b866f34c74955e190909bd6ab5d992eBjorn Bringert     * {@link #SUGGEST_COLUMN_QUERY} for the suggestion, and
12675f80605a0b866f34c74955e190909bd6ab5d992eBjorn Bringert     * {@link #USER_QUERY} will contain the string typed by the
12685f80605a0b866f34c74955e190909bd6ab5d992eBjorn Bringert     * user.
12695f80605a0b866f34c74955e190909bd6ab5d992eBjorn Bringert     */
12705f80605a0b866f34c74955e190909bd6ab5d992eBjorn Bringert    public final static String USER_QUERY = "user_query";
12715f80605a0b866f34c74955e190909bd6ab5d992eBjorn Bringert
12725f80605a0b866f34c74955e190909bd6ab5d992eBjorn Bringert    /**
12739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Intent extra data key: Use this key with Intent.ACTION_SEARCH and
12749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link android.content.Intent#getBundleExtra
12759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *  content.Intent.getBundleExtra()}
12769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * to obtain any additional app-specific data that was inserted by the
12779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * activity that launched the search.
12789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
12799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public final static String APP_DATA = "app_data";
12809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
12829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Intent app_data bundle key: Use this key with the bundle from
12839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link android.content.Intent#getBundleExtra
12849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * content.Intent.getBundleExtra(APP_DATA)} to obtain the source identifier
12859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * set by the activity that launched the search.
12869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
12879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @hide
12889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
12899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public final static String SOURCE = "source";
1290a058f02b591d971a829cb1e28d48a992e46ad85eKarl Rosaen
12919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1292be5b73c5926cbebd508d8323bdeaafa2e048a93cBjorn Bringert     * Intent extra data key: Use {@link android.content.Intent#getBundleExtra
1293be5b73c5926cbebd508d8323bdeaafa2e048a93cBjorn Bringert     * content.Intent.getBundleExtra(SEARCH_MODE)} to get the search mode used
1294be5b73c5926cbebd508d8323bdeaafa2e048a93cBjorn Bringert     * to launch the intent.
1295be5b73c5926cbebd508d8323bdeaafa2e048a93cBjorn Bringert     * The only current value for this is {@link #MODE_GLOBAL_SEARCH_SUGGESTION}.
1296be5b73c5926cbebd508d8323bdeaafa2e048a93cBjorn Bringert     *
1297be5b73c5926cbebd508d8323bdeaafa2e048a93cBjorn Bringert     * @hide
1298be5b73c5926cbebd508d8323bdeaafa2e048a93cBjorn Bringert     */
1299be5b73c5926cbebd508d8323bdeaafa2e048a93cBjorn Bringert    public final static String SEARCH_MODE = "search_mode";
1300be5b73c5926cbebd508d8323bdeaafa2e048a93cBjorn Bringert
1301be5b73c5926cbebd508d8323bdeaafa2e048a93cBjorn Bringert    /**
1302be5b73c5926cbebd508d8323bdeaafa2e048a93cBjorn Bringert     * Value for the {@link #SEARCH_MODE} key.
1303be5b73c5926cbebd508d8323bdeaafa2e048a93cBjorn Bringert     * This is used if the intent was launched by clicking a suggestion in global search
1304be5b73c5926cbebd508d8323bdeaafa2e048a93cBjorn Bringert     * mode (Quick Search Box).
1305be5b73c5926cbebd508d8323bdeaafa2e048a93cBjorn Bringert     *
1306be5b73c5926cbebd508d8323bdeaafa2e048a93cBjorn Bringert     * @hide
1307be5b73c5926cbebd508d8323bdeaafa2e048a93cBjorn Bringert     */
1308be5b73c5926cbebd508d8323bdeaafa2e048a93cBjorn Bringert    public static final String MODE_GLOBAL_SEARCH_SUGGESTION = "global_search_suggestion";
1309be5b73c5926cbebd508d8323bdeaafa2e048a93cBjorn Bringert
1310be5b73c5926cbebd508d8323bdeaafa2e048a93cBjorn Bringert    /**
13119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Intent extra data key: Use this key with Intent.ACTION_SEARCH and
13129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link android.content.Intent#getIntExtra content.Intent.getIntExtra()}
13139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * to obtain the keycode that the user used to trigger this query.  It will be zero if the
13149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * user simply pressed the "GO" button on the search UI.  This is primarily used in conjunction
13159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * with the keycode attribute in the actionkey element of your searchable.xml configuration
13169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * file.
13179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
13189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public final static String ACTION_KEY = "action_key";
13199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1321bf23fe062ab4321143717c21827d329e087cc72fSatish Sampath     * Intent component name key: This key will be used for the extra populated by the
1322bf23fe062ab4321143717c21827d329e087cc72fSatish Sampath     * {@link #SUGGEST_COLUMN_INTENT_COMPONENT_NAME} column.
1323bf23fe062ab4321143717c21827d329e087cc72fSatish Sampath     *
1324bf23fe062ab4321143717c21827d329e087cc72fSatish Sampath     * {@hide}
1325bf23fe062ab4321143717c21827d329e087cc72fSatish Sampath     */
1326bf23fe062ab4321143717c21827d329e087cc72fSatish Sampath    public final static String COMPONENT_NAME_KEY = "intent_component_name_key";
1327bf23fe062ab4321143717c21827d329e087cc72fSatish Sampath
1328bf23fe062ab4321143717c21827d329e087cc72fSatish Sampath    /**
1329875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen     * Intent extra data key: This key will be used for the extra populated by the
1330875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen     * {@link #SUGGEST_COLUMN_INTENT_EXTRA_DATA} column.
1331875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen     */
1332875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen    public final static String EXTRA_DATA_KEY = "intent_extra_data_key";
1333a058f02b591d971a829cb1e28d48a992e46ad85eKarl Rosaen
1334a058f02b591d971a829cb1e28d48a992e46ad85eKarl Rosaen    /**
13353c50ef6f665ab22cdb50c76bb31283e6bac47fc6Bjorn Bringert     * String extra data key for {@link Intent#ACTION_GLOBAL_SEARCH} intents. Contains the initial
13363c50ef6f665ab22cdb50c76bb31283e6bac47fc6Bjorn Bringert     * query to show in the global search activity.
13373c50ef6f665ab22cdb50c76bb31283e6bac47fc6Bjorn Bringert     *
13383c50ef6f665ab22cdb50c76bb31283e6bac47fc6Bjorn Bringert     * @hide Pending API council approval
13393c50ef6f665ab22cdb50c76bb31283e6bac47fc6Bjorn Bringert     */
13403c50ef6f665ab22cdb50c76bb31283e6bac47fc6Bjorn Bringert    public final static String INITIAL_QUERY = "initial_query";
13413c50ef6f665ab22cdb50c76bb31283e6bac47fc6Bjorn Bringert
13423c50ef6f665ab22cdb50c76bb31283e6bac47fc6Bjorn Bringert    /**
13433c50ef6f665ab22cdb50c76bb31283e6bac47fc6Bjorn Bringert     * Boolean extra data key for {@link Intent#ACTION_GLOBAL_SEARCH} intents. If {@code true},
13443c50ef6f665ab22cdb50c76bb31283e6bac47fc6Bjorn Bringert     * the initial query should be selected.
13453c50ef6f665ab22cdb50c76bb31283e6bac47fc6Bjorn Bringert     *
13463c50ef6f665ab22cdb50c76bb31283e6bac47fc6Bjorn Bringert     * @hide Pending API council approval
13473c50ef6f665ab22cdb50c76bb31283e6bac47fc6Bjorn Bringert     */
13483c50ef6f665ab22cdb50c76bb31283e6bac47fc6Bjorn Bringert    public final static String SELECT_INITIAL_QUERY = "select_initial_query";
134932d580c360da0a0f15e7a080f4ebd0b7b514fe4cBjorn Bringert
13503c50ef6f665ab22cdb50c76bb31283e6bac47fc6Bjorn Bringert    /**
13511c54cf0903cd81467ca41ec6733c459e10b22763Karl Rosaen     * Defines the constants used in the communication between {@link android.app.SearchDialog} and
13521c54cf0903cd81467ca41ec6733c459e10b22763Karl Rosaen     * the global search provider via {@link Cursor#respond(android.os.Bundle)}.
1353a058f02b591d971a829cb1e28d48a992e46ad85eKarl Rosaen     *
13541c54cf0903cd81467ca41ec6733c459e10b22763Karl Rosaen     * @hide
1355a058f02b591d971a829cb1e28d48a992e46ad85eKarl Rosaen     */
13561c54cf0903cd81467ca41ec6733c459e10b22763Karl Rosaen    public static class DialogCursorProtocol {
1357a058f02b591d971a829cb1e28d48a992e46ad85eKarl Rosaen
13581c54cf0903cd81467ca41ec6733c459e10b22763Karl Rosaen        /**
13591c54cf0903cd81467ca41ec6733c459e10b22763Karl Rosaen         * The sent bundle will contain this integer key, with a value set to one of the events
13601c54cf0903cd81467ca41ec6733c459e10b22763Karl Rosaen         * below.
13611c54cf0903cd81467ca41ec6733c459e10b22763Karl Rosaen         */
13621c54cf0903cd81467ca41ec6733c459e10b22763Karl Rosaen        public final static String METHOD = "DialogCursorProtocol.method";
1363a058f02b591d971a829cb1e28d48a992e46ad85eKarl Rosaen
13641c54cf0903cd81467ca41ec6733c459e10b22763Karl Rosaen        /**
13651c54cf0903cd81467ca41ec6733c459e10b22763Karl Rosaen         * After data has been refreshed.
13661c54cf0903cd81467ca41ec6733c459e10b22763Karl Rosaen         */
13671c54cf0903cd81467ca41ec6733c459e10b22763Karl Rosaen        public final static int POST_REFRESH = 0;
13681c54cf0903cd81467ca41ec6733c459e10b22763Karl Rosaen        public final static String POST_REFRESH_RECEIVE_ISPENDING
13691c54cf0903cd81467ca41ec6733c459e10b22763Karl Rosaen                = "DialogCursorProtocol.POST_REFRESH.isPending";
13701c54cf0903cd81467ca41ec6733c459e10b22763Karl Rosaen        public final static String POST_REFRESH_RECEIVE_DISPLAY_NOTIFY
13711c54cf0903cd81467ca41ec6733c459e10b22763Karl Rosaen                = "DialogCursorProtocol.POST_REFRESH.displayNotify";
13721c54cf0903cd81467ca41ec6733c459e10b22763Karl Rosaen
13731c54cf0903cd81467ca41ec6733c459e10b22763Karl Rosaen        /**
13741c54cf0903cd81467ca41ec6733c459e10b22763Karl Rosaen         * When a position has been clicked.
13751c54cf0903cd81467ca41ec6733c459e10b22763Karl Rosaen         */
13761c54cf0903cd81467ca41ec6733c459e10b22763Karl Rosaen        public final static int CLICK = 2;
13771c54cf0903cd81467ca41ec6733c459e10b22763Karl Rosaen        public final static String CLICK_SEND_POSITION
13781c54cf0903cd81467ca41ec6733c459e10b22763Karl Rosaen                = "DialogCursorProtocol.CLICK.sendPosition";
13796ddaa3497ce7af2c303771365449501e2be52511Bjorn Bringert        public final static String CLICK_SEND_MAX_DISPLAY_POS
13806ddaa3497ce7af2c303771365449501e2be52511Bjorn Bringert                = "DialogCursorProtocol.CLICK.sendDisplayPosition";
13815417f09c141713c62be697fe10fe149d6d3d0eb4Bjorn Bringert        public final static String CLICK_SEND_ACTION_KEY
13825417f09c141713c62be697fe10fe149d6d3d0eb4Bjorn Bringert                = "DialogCursorProtocol.CLICK.sendActionKey";
13835417f09c141713c62be697fe10fe149d6d3d0eb4Bjorn Bringert        public final static String CLICK_SEND_ACTION_MSG
13845417f09c141713c62be697fe10fe149d6d3d0eb4Bjorn Bringert                = "DialogCursorProtocol.CLICK.sendActionMsg";
13851c54cf0903cd81467ca41ec6733c459e10b22763Karl Rosaen        public final static String CLICK_RECEIVE_SELECTED_POS
13861c54cf0903cd81467ca41ec6733c459e10b22763Karl Rosaen                = "DialogCursorProtocol.CLICK.receiveSelectedPosition";
13871c54cf0903cd81467ca41ec6733c459e10b22763Karl Rosaen
13881c54cf0903cd81467ca41ec6733c459e10b22763Karl Rosaen        /**
13891c54cf0903cd81467ca41ec6733c459e10b22763Karl Rosaen         * When the threshold received in {@link #POST_REFRESH_RECEIVE_DISPLAY_NOTIFY} is displayed.
13901c54cf0903cd81467ca41ec6733c459e10b22763Karl Rosaen         */
13911c54cf0903cd81467ca41ec6733c459e10b22763Karl Rosaen        public final static int THRESH_HIT = 3;
13922fcaf79a1856186e3823390c488e806c5955c8a6Bjorn Bringert
13932fcaf79a1856186e3823390c488e806c5955c8a6Bjorn Bringert        /**
13942fcaf79a1856186e3823390c488e806c5955c8a6Bjorn Bringert         * When a search is started without using a suggestion.
13952fcaf79a1856186e3823390c488e806c5955c8a6Bjorn Bringert         */
13962fcaf79a1856186e3823390c488e806c5955c8a6Bjorn Bringert        public final static int SEARCH = 4;
13972fcaf79a1856186e3823390c488e806c5955c8a6Bjorn Bringert        public final static String SEARCH_SEND_MAX_DISPLAY_POS
13982fcaf79a1856186e3823390c488e806c5955c8a6Bjorn Bringert                = "DialogCursorProtocol.SEARCH.sendDisplayPosition";
13992fcaf79a1856186e3823390c488e806c5955c8a6Bjorn Bringert        public final static String SEARCH_SEND_QUERY = "DialogCursorProtocol.SEARCH.query";
14001c54cf0903cd81467ca41ec6733c459e10b22763Karl Rosaen    }
1401a058f02b591d971a829cb1e28d48a992e46ad85eKarl Rosaen
1402875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen    /**
14039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Intent extra data key: Use this key with Intent.ACTION_SEARCH and
14049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link android.content.Intent#getStringExtra content.Intent.getStringExtra()}
14059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * to obtain the action message that was defined for a particular search action key and/or
14069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * suggestion.  It will be null if the search was launched by typing "enter", touched the the
14079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * "GO" button, or other means not involving any action key.
14089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
14099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public final static String ACTION_MSG = "action_msg";
14109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
14129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Uri path for queried suggestions data.  This is the path that the search manager
14139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * will use when querying your content provider for suggestions data based on user input
14149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * (e.g. looking for partial matches).
14159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Typically you'll use this with a URI matcher.
14169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
14179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public final static String SUGGEST_URI_PATH_QUERY = "search_suggest_query";
1418b2a5011578d4a64df2f39bdeeedfe9f37e7aecc4Karl Rosaen
1419b2a5011578d4a64df2f39bdeeedfe9f37e7aecc4Karl Rosaen    /**
1420b619c9198efa0108a692d352b0e7eaa534f922f3Karl Rosaen     * MIME type for suggestions data.  You'll use this in your suggestions content provider
1421b619c9198efa0108a692d352b0e7eaa534f922f3Karl Rosaen     * in the getType() function.
1422b619c9198efa0108a692d352b0e7eaa534f922f3Karl Rosaen     */
1423b619c9198efa0108a692d352b0e7eaa534f922f3Karl Rosaen    public final static String SUGGEST_MIME_TYPE =
1424b619c9198efa0108a692d352b0e7eaa534f922f3Karl Rosaen            "vnd.android.cursor.dir/vnd.android.search.suggest";
1425b619c9198efa0108a692d352b0e7eaa534f922f3Karl Rosaen
1426b619c9198efa0108a692d352b0e7eaa534f922f3Karl Rosaen    /**
1427b2a5011578d4a64df2f39bdeeedfe9f37e7aecc4Karl Rosaen     * Uri path for shortcut validation.  This is the path that the search manager will use when
1428b2a5011578d4a64df2f39bdeeedfe9f37e7aecc4Karl Rosaen     * querying your content provider to refresh a shortcutted suggestion result and to check if it
1429b2a5011578d4a64df2f39bdeeedfe9f37e7aecc4Karl Rosaen     * is still valid.  When asked, a source may return an up to date result, or no result.  No
1430b2a5011578d4a64df2f39bdeeedfe9f37e7aecc4Karl Rosaen     * result indicates the shortcut refers to a no longer valid sugggestion.
1431b2a5011578d4a64df2f39bdeeedfe9f37e7aecc4Karl Rosaen     *
1432b2a5011578d4a64df2f39bdeeedfe9f37e7aecc4Karl Rosaen     * @see #SUGGEST_COLUMN_SHORTCUT_ID
1433b2a5011578d4a64df2f39bdeeedfe9f37e7aecc4Karl Rosaen     */
1434b2a5011578d4a64df2f39bdeeedfe9f37e7aecc4Karl Rosaen    public final static String SUGGEST_URI_PATH_SHORTCUT = "search_suggest_shortcut";
14359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1437b619c9198efa0108a692d352b0e7eaa534f922f3Karl Rosaen     * MIME type for shortcut validation.  You'll use this in your suggestions content provider
14389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * in the getType() function.
14399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1440b619c9198efa0108a692d352b0e7eaa534f922f3Karl Rosaen    public final static String SHORTCUT_MIME_TYPE =
1441b619c9198efa0108a692d352b0e7eaa534f922f3Karl Rosaen            "vnd.android.cursor.item/vnd.android.search.suggest";
1442d4c98c4c450a95b67fe9746675984333b7653713Karl Rosaen
1443d4c98c4c450a95b67fe9746675984333b7653713Karl Rosaen
1444d4c98c4c450a95b67fe9746675984333b7653713Karl Rosaen    /**
1445d4c98c4c450a95b67fe9746675984333b7653713Karl Rosaen     * The authority of the provider to report clicks to when a click is detected after pivoting
1446d4c98c4c450a95b67fe9746675984333b7653713Karl Rosaen     * into a specific app's search from global search.
1447d4c98c4c450a95b67fe9746675984333b7653713Karl Rosaen     *
1448d4c98c4c450a95b67fe9746675984333b7653713Karl Rosaen     * In addition to the columns below, the suggestion columns are used to pass along the full
1449d4c98c4c450a95b67fe9746675984333b7653713Karl Rosaen     * suggestion so it can be shortcutted.
1450d4c98c4c450a95b67fe9746675984333b7653713Karl Rosaen     *
1451590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen     * @hide
1452d4c98c4c450a95b67fe9746675984333b7653713Karl Rosaen     */
1453d4c98c4c450a95b67fe9746675984333b7653713Karl Rosaen    public final static String SEARCH_CLICK_REPORT_AUTHORITY =
1454d4c98c4c450a95b67fe9746675984333b7653713Karl Rosaen            "com.android.globalsearch.stats";
1455d4c98c4c450a95b67fe9746675984333b7653713Karl Rosaen
1456d4c98c4c450a95b67fe9746675984333b7653713Karl Rosaen    /**
1457d4c98c4c450a95b67fe9746675984333b7653713Karl Rosaen     * The path the write goes to.
1458d4c98c4c450a95b67fe9746675984333b7653713Karl Rosaen     *
1459590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen     * @hide
1460d4c98c4c450a95b67fe9746675984333b7653713Karl Rosaen     */
1461d4c98c4c450a95b67fe9746675984333b7653713Karl Rosaen    public final static String SEARCH_CLICK_REPORT_URI_PATH = "click";
1462d4c98c4c450a95b67fe9746675984333b7653713Karl Rosaen
1463d4c98c4c450a95b67fe9746675984333b7653713Karl Rosaen    /**
1464d4c98c4c450a95b67fe9746675984333b7653713Karl Rosaen     * The column storing the query for the click.
1465d4c98c4c450a95b67fe9746675984333b7653713Karl Rosaen     *
1466590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen     * @hide
1467d4c98c4c450a95b67fe9746675984333b7653713Karl Rosaen     */
1468d4c98c4c450a95b67fe9746675984333b7653713Karl Rosaen    public final static String SEARCH_CLICK_REPORT_COLUMN_QUERY = "query";
1469d4c98c4c450a95b67fe9746675984333b7653713Karl Rosaen
1470d4c98c4c450a95b67fe9746675984333b7653713Karl Rosaen    /**
1471d4c98c4c450a95b67fe9746675984333b7653713Karl Rosaen     * The column storing the component name of the application that was pivoted into.
1472d4c98c4c450a95b67fe9746675984333b7653713Karl Rosaen     *
1473590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen     * @hide
1474d4c98c4c450a95b67fe9746675984333b7653713Karl Rosaen     */
1475d4c98c4c450a95b67fe9746675984333b7653713Karl Rosaen    public final static String SEARCH_CLICK_REPORT_COLUMN_COMPONENT = "component";
1476d4c98c4c450a95b67fe9746675984333b7653713Karl Rosaen
14779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
14789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Column name for suggestions cursor.  <i>Unused - can be null or column can be omitted.</i>
14799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
14809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public final static String SUGGEST_COLUMN_FORMAT = "suggest_format";
14819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
14829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Column name for suggestions cursor.  <i>Required.</i>  This is the primary line of text that
14839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * will be presented to the user as the suggestion.
14849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
14859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public final static String SUGGEST_COLUMN_TEXT_1 = "suggest_text_1";
14869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
14879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Column name for suggestions cursor.  <i>Optional.</i>  If your cursor includes this column,
14889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *  then all suggestions will be provided in a two-line format.  The second line of text is in
14899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *  a much smaller appearance.
14909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
14919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public final static String SUGGEST_COLUMN_TEXT_2 = "suggest_text_2";
14929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
14939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Column name for suggestions cursor.  <i>Optional.</i>  If your cursor includes this column,
1494875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen     *  then all suggestions will be provided in a format that includes space for two small icons,
14959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *  one at the left and one at the right of each suggestion.  The data in the column must
1496875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen     *  be a resource ID of a drawable, or a URI in one of the following formats:
1497875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen     *
1498875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen     * <ul>
1499875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen     * <li>content ({@link android.content.ContentResolver#SCHEME_CONTENT})</li>
1500875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen     * <li>android.resource ({@link android.content.ContentResolver#SCHEME_ANDROID_RESOURCE})</li>
1501875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen     * <li>file ({@link android.content.ContentResolver#SCHEME_FILE})</li>
1502875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen     * </ul>
1503875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen     *
1504875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen     * See {@link android.content.ContentResolver#openAssetFileDescriptor(Uri, String)}
1505875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen     * for more information on these schemes.
15069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
15079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public final static String SUGGEST_COLUMN_ICON_1 = "suggest_icon_1";
15089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
15099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Column name for suggestions cursor.  <i>Optional.</i>  If your cursor includes this column,
1510875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen     *  then all suggestions will be provided in a format that includes space for two small icons,
15119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *  one at the left and one at the right of each suggestion.  The data in the column must
1512875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen     *  be a resource ID of a drawable, or a URI in one of the following formats:
1513875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen     *
1514875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen     * <ul>
1515875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen     * <li>content ({@link android.content.ContentResolver#SCHEME_CONTENT})</li>
1516875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen     * <li>android.resource ({@link android.content.ContentResolver#SCHEME_ANDROID_RESOURCE})</li>
1517875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen     * <li>file ({@link android.content.ContentResolver#SCHEME_FILE})</li>
1518875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen     * </ul>
1519875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen     *
1520875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen     * See {@link android.content.ContentResolver#openAssetFileDescriptor(Uri, String)}
1521875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen     * for more information on these schemes.
15229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
15239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public final static String SUGGEST_COLUMN_ICON_2 = "suggest_icon_2";
15249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
15259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Column name for suggestions cursor.  <i>Optional.</i>  If this column exists <i>and</i>
15269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * this element exists at the given row, this is the action that will be used when
15279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * forming the suggestion's intent.  If the element is not provided, the action will be taken
15289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * from the android:searchSuggestIntentAction field in your XML metadata.  <i>At least one of
15299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * these must be present for the suggestion to generate an intent.</i>  Note:  If your action is
15309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the same for all suggestions, it is more efficient to specify it using XML metadata and omit
15319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * it from the cursor.
15329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
15339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public final static String SUGGEST_COLUMN_INTENT_ACTION = "suggest_intent_action";
15349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
15359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Column name for suggestions cursor.  <i>Optional.</i>  If this column exists <i>and</i>
15369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * this element exists at the given row, this is the data that will be used when
15379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * forming the suggestion's intent.  If the element is not provided, the data will be taken
15389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * from the android:searchSuggestIntentData field in your XML metadata.  If neither source
15399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * is provided, the Intent's data field will be null.  Note:  If your data is
15409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the same for all suggestions, or can be described using a constant part and a specific ID,
15419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * it is more efficient to specify it using XML metadata and omit it from the cursor.
15429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
15439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public final static String SUGGEST_COLUMN_INTENT_DATA = "suggest_intent_data";
15449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1545bf23fe062ab4321143717c21827d329e087cc72fSatish Sampath     * Column name for suggestions cursor.  <i>Optional.</i>  If this column exists <i>and</i>
1546bf23fe062ab4321143717c21827d329e087cc72fSatish Sampath     * this element exists at the given row, this is the data that will be used when
1547bf23fe062ab4321143717c21827d329e087cc72fSatish Sampath     * forming the suggestion's intent. If not provided, the Intent's extra data field will be null.
1548bf23fe062ab4321143717c21827d329e087cc72fSatish Sampath     * This column allows suggestions to provide additional arbitrary data which will be included as
1549131234c6f134c586208ec94bfe4ae021b057cf66Mike LeBeau     * an extra under the key {@link #EXTRA_DATA_KEY}.
1550bf23fe062ab4321143717c21827d329e087cc72fSatish Sampath     */
1551bf23fe062ab4321143717c21827d329e087cc72fSatish Sampath    public final static String SUGGEST_COLUMN_INTENT_EXTRA_DATA = "suggest_intent_extra_data";
1552bf23fe062ab4321143717c21827d329e087cc72fSatish Sampath    /**
1553875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen     * Column name for suggestions cursor.  <i>Optional.</i>  This column allows suggestions
1554875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen     *  to provide additional arbitrary data which will be included as an extra under the key
1555bf23fe062ab4321143717c21827d329e087cc72fSatish Sampath     *  {@link #COMPONENT_NAME_KEY}. For use by the global search system only - if other providers
155621fd5f144a3e6919ff6b4e8a1a733c940d5dd6dfMike LeBeau     *  attempt to use this column, the value will be overwritten by global search.
1557a058f02b591d971a829cb1e28d48a992e46ad85eKarl Rosaen     *
1558590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen     * @hide
1559875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen     */
1560bf23fe062ab4321143717c21827d329e087cc72fSatish Sampath    public final static String SUGGEST_COLUMN_INTENT_COMPONENT_NAME = "suggest_intent_component";
1561875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen    /**
15629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Column name for suggestions cursor.  <i>Optional.</i>  If this column exists <i>and</i>
15639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * this element exists at the given row, then "/" and this value will be appended to the data
15649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * field in the Intent.  This should only be used if the data field has already been set to an
15659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * appropriate base string.
15669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
15679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public final static String SUGGEST_COLUMN_INTENT_DATA_ID = "suggest_intent_data_id";
15689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
15699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Column name for suggestions cursor.  <i>Required if action is
15709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link android.content.Intent#ACTION_SEARCH ACTION_SEARCH}, optional otherwise.</i>  If this
15719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * column exists <i>and</i> this element exists at the given row, this is the data that will be
15729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * used when forming the suggestion's query.
15739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
15749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public final static String SUGGEST_COLUMN_QUERY = "suggest_intent_query";
15759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1576875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen    /**
1577b2a5011578d4a64df2f39bdeeedfe9f37e7aecc4Karl Rosaen     * Column name for suggestions cursor. <i>Optional.</i>  This column is used to indicate whether
1578b5041368524045b6714081d14ff3c6b22598aab1Karl Rosaen     * a search suggestion should be stored as a shortcut, and whether it should be refreshed.  If
1579b2a5011578d4a64df2f39bdeeedfe9f37e7aecc4Karl Rosaen     * missing, the result will be stored as a shortcut and never validated.  If set to
1580b2a5011578d4a64df2f39bdeeedfe9f37e7aecc4Karl Rosaen     * {@link #SUGGEST_NEVER_MAKE_SHORTCUT}, the result will not be stored as a shortcut.
1581b5041368524045b6714081d14ff3c6b22598aab1Karl Rosaen     * Otherwise, the shortcut id will be used to check back for an up to date suggestion using
1582b2a5011578d4a64df2f39bdeeedfe9f37e7aecc4Karl Rosaen     * {@link #SUGGEST_URI_PATH_SHORTCUT}.
1583b2a5011578d4a64df2f39bdeeedfe9f37e7aecc4Karl Rosaen     */
1584b2a5011578d4a64df2f39bdeeedfe9f37e7aecc4Karl Rosaen    public final static String SUGGEST_COLUMN_SHORTCUT_ID = "suggest_shortcut_id";
1585b2a5011578d4a64df2f39bdeeedfe9f37e7aecc4Karl Rosaen
1586b2a5011578d4a64df2f39bdeeedfe9f37e7aecc4Karl Rosaen    /**
15871c5fa0f31009502c539c65de99010b63cb617aacSatish Sampath     * Column name for suggestions cursor. <i>Optional.</i>  This column is used to specify the
15881c5fa0f31009502c539c65de99010b63cb617aacSatish Sampath     * cursor item's background color if it needs a non-default background color. A non-zero value
15891c5fa0f31009502c539c65de99010b63cb617aacSatish Sampath     * indicates a valid background color to override the default.
15901c5fa0f31009502c539c65de99010b63cb617aacSatish Sampath     *
1591590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen     * @hide For internal use, not part of the public API.
15921c5fa0f31009502c539c65de99010b63cb617aacSatish Sampath     */
15931c5fa0f31009502c539c65de99010b63cb617aacSatish Sampath    public final static String SUGGEST_COLUMN_BACKGROUND_COLOR = "suggest_background_color";
1594ce0959df5ca49cf8f726adddb65978da83e42544Mike LeBeau
1595ce0959df5ca49cf8f726adddb65978da83e42544Mike LeBeau    /**
1596ce0959df5ca49cf8f726adddb65978da83e42544Mike LeBeau     * Column name for suggestions cursor. <i>Optional.</i> This column is used to specify
1597ce0959df5ca49cf8f726adddb65978da83e42544Mike LeBeau     * that a spinner should be shown in lieu of an icon2 while the shortcut of this suggestion
1598ce0959df5ca49cf8f726adddb65978da83e42544Mike LeBeau     * is being refreshed.
1599ce0959df5ca49cf8f726adddb65978da83e42544Mike LeBeau     */
1600ce0959df5ca49cf8f726adddb65978da83e42544Mike LeBeau    public final static String SUGGEST_COLUMN_SPINNER_WHILE_REFRESHING =
1601ce0959df5ca49cf8f726adddb65978da83e42544Mike LeBeau            "suggest_spinner_while_refreshing";
16021c5fa0f31009502c539c65de99010b63cb617aacSatish Sampath
16031c5fa0f31009502c539c65de99010b63cb617aacSatish Sampath    /**
1604b2a5011578d4a64df2f39bdeeedfe9f37e7aecc4Karl Rosaen     * Column value for suggestion column {@link #SUGGEST_COLUMN_SHORTCUT_ID} when a suggestion
1605b2a5011578d4a64df2f39bdeeedfe9f37e7aecc4Karl Rosaen     * should not be stored as a shortcut in global search.
1606b2a5011578d4a64df2f39bdeeedfe9f37e7aecc4Karl Rosaen     */
1607b2a5011578d4a64df2f39bdeeedfe9f37e7aecc4Karl Rosaen    public final static String SUGGEST_NEVER_MAKE_SHORTCUT = "_-1";
1608b2a5011578d4a64df2f39bdeeedfe9f37e7aecc4Karl Rosaen
1609b2a5011578d4a64df2f39bdeeedfe9f37e7aecc4Karl Rosaen    /**
16103fc7c67de192a5baee2b4510fdb464b0fec72dcaBjorn Bringert     * Query parameter added to suggestion queries to limit the number of suggestions returned.
161186917dbb9554e3e05be4ca8845a409b730120022Bjorn Bringert     * This limit is only advisory and suggestion providers may chose to ignore it.
16123fc7c67de192a5baee2b4510fdb464b0fec72dcaBjorn Bringert     */
16133fc7c67de192a5baee2b4510fdb464b0fec72dcaBjorn Bringert    public final static String SUGGEST_PARAMETER_LIMIT = "limit";
16143fc7c67de192a5baee2b4510fdb464b0fec72dcaBjorn Bringert
16153fc7c67de192a5baee2b4510fdb464b0fec72dcaBjorn Bringert    /**
161632d580c360da0a0f15e7a080f4ebd0b7b514fe4cBjorn Bringert     * Intent action for opening the search source selection activity.
161732d580c360da0a0f15e7a080f4ebd0b7b514fe4cBjorn Bringert     * The intent may include these extra values:
161832d580c360da0a0f15e7a080f4ebd0b7b514fe4cBjorn Bringert     * {@link #QUERY},
161932d580c360da0a0f15e7a080f4ebd0b7b514fe4cBjorn Bringert     * {@link #APP_DATA}.
162032d580c360da0a0f15e7a080f4ebd0b7b514fe4cBjorn Bringert     */
162132d580c360da0a0f15e7a080f4ebd0b7b514fe4cBjorn Bringert    public static final String INTENT_ACTION_SELECT_SEARCH_SOURCE
162232d580c360da0a0f15e7a080f4ebd0b7b514fe4cBjorn Bringert            = "android.intent.action.SELECT_SEARCH_SOURCE";
162332d580c360da0a0f15e7a080f4ebd0b7b514fe4cBjorn Bringert
162432d580c360da0a0f15e7a080f4ebd0b7b514fe4cBjorn Bringert    /**
1625875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen     * If a suggestion has this value in {@link #SUGGEST_COLUMN_INTENT_ACTION},
1626875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen     * the search dialog will switch to a different suggestion source when the
1627875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen     * suggestion is clicked.
1628875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen     *
1629875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen     * {@link #SUGGEST_COLUMN_INTENT_DATA} must contain
1630875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen     * the flattened {@link ComponentName} of the activity which is to be searched.
1631875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen     *
1632875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen     * TODO: Should {@link #SUGGEST_COLUMN_INTENT_DATA} instead contain a URI in the format
1633875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen     * used by {@link android.provider.Applications}?
1634875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen     *
1635875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen     * TODO: This intent should be protected by the same permission that we use
1636875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen     * for replacing the global search provider.
1637875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen     *
1638875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen     * The query text field will be set to the value of {@link #SUGGEST_COLUMN_QUERY}.
1639875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen     *
1640875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen     * @hide Pending API council approval.
1641875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen     */
1642875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen    public final static String INTENT_ACTION_CHANGE_SEARCH_SOURCE
1643875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen            = "android.search.action.CHANGE_SEARCH_SOURCE";
1644a058f02b591d971a829cb1e28d48a992e46ad85eKarl Rosaen
1645875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen    /**
164674708bbdf8d6f172b08343bdc578a20aa4b39148Bjorn Bringert     * Intent action for finding the global search activity.
164774708bbdf8d6f172b08343bdc578a20aa4b39148Bjorn Bringert     * The global search provider should handle this intent.
164874708bbdf8d6f172b08343bdc578a20aa4b39148Bjorn Bringert     *
164974708bbdf8d6f172b08343bdc578a20aa4b39148Bjorn Bringert     * @hide Pending API council approval.
165074708bbdf8d6f172b08343bdc578a20aa4b39148Bjorn Bringert     */
165174708bbdf8d6f172b08343bdc578a20aa4b39148Bjorn Bringert    public final static String INTENT_ACTION_GLOBAL_SEARCH
165274708bbdf8d6f172b08343bdc578a20aa4b39148Bjorn Bringert            = "android.search.action.GLOBAL_SEARCH";
165374708bbdf8d6f172b08343bdc578a20aa4b39148Bjorn Bringert
165474708bbdf8d6f172b08343bdc578a20aa4b39148Bjorn Bringert    /**
1655875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen     * Intent action for starting the global search settings activity.
1656875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen     * The global search provider should handle this intent.
1657875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen     *
1658875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen     * @hide Pending API council approval.
1659875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen     */
1660875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen    public final static String INTENT_ACTION_SEARCH_SETTINGS
1661875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen            = "android.search.action.SEARCH_SETTINGS";
16623a27803b29dc739685e1e2465a0ca697e4b60d14Mike LeBeau
16633a27803b29dc739685e1e2465a0ca697e4b60d14Mike LeBeau    /**
16643a27803b29dc739685e1e2465a0ca697e4b60d14Mike LeBeau     * Intent action for starting a web search provider's settings activity.
16653a27803b29dc739685e1e2465a0ca697e4b60d14Mike LeBeau     * Web search providers should handle this intent if they have provider-specific
16663a27803b29dc739685e1e2465a0ca697e4b60d14Mike LeBeau     * settings to implement.
16673a27803b29dc739685e1e2465a0ca697e4b60d14Mike LeBeau     */
16683a27803b29dc739685e1e2465a0ca697e4b60d14Mike LeBeau    public final static String INTENT_ACTION_WEB_SEARCH_SETTINGS
16693a27803b29dc739685e1e2465a0ca697e4b60d14Mike LeBeau            = "android.search.action.WEB_SEARCH_SETTINGS";
1670a058f02b591d971a829cb1e28d48a992e46ad85eKarl Rosaen
1671a058f02b591d971a829cb1e28d48a992e46ad85eKarl Rosaen    /**
1672f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath     * Intent action broadcasted to inform that the searchables list or default have changed.
1673f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath     * Components should handle this intent if they cache any searchable data and wish to stay
1674f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath     * up to date on changes.
1675f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath     */
1676f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath    public final static String INTENT_ACTION_SEARCHABLES_CHANGED
1677f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath            = "android.search.action.SEARCHABLES_CHANGED";
1678d4fb7a0d90b16e360b7a7b64cb7a6fd94f084c27Mike LeBeau
1679d4fb7a0d90b16e360b7a7b64cb7a6fd94f084c27Mike LeBeau    /**
1680d4fb7a0d90b16e360b7a7b64cb7a6fd94f084c27Mike LeBeau     * Intent action broadcasted to inform that the search settings have changed in some way.
1681590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen     * Either searchables have been enabled or disabled, or a different web search provider
1682590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen     * has been chosen.
1683d4fb7a0d90b16e360b7a7b64cb7a6fd94f084c27Mike LeBeau     */
1684d4fb7a0d90b16e360b7a7b64cb7a6fd94f084c27Mike LeBeau    public final static String INTENT_ACTION_SEARCH_SETTINGS_CHANGED
1685d4fb7a0d90b16e360b7a7b64cb7a6fd94f084c27Mike LeBeau            = "android.search.action.SETTINGS_CHANGED";
1686f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath
1687f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath    /**
1688a058f02b591d971a829cb1e28d48a992e46ad85eKarl Rosaen     * If a suggestion has this value in {@link #SUGGEST_COLUMN_INTENT_ACTION},
1689a058f02b591d971a829cb1e28d48a992e46ad85eKarl Rosaen     * the search dialog will take no action.
1690a058f02b591d971a829cb1e28d48a992e46ad85eKarl Rosaen     *
1691590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen     * @hide
1692a058f02b591d971a829cb1e28d48a992e46ad85eKarl Rosaen     */
1693a058f02b591d971a829cb1e28d48a992e46ad85eKarl Rosaen    public final static String INTENT_ACTION_NONE = "android.search.action.ZILCH";
1694875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen
1695875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen    /**
1696875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen     * Reference to the shared system search service.
1697875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen     */
16988d1538237847baf381787b881141f8c0478bef5bBjorn Bringert    private static ISearchManager mService;
16999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final Context mContext;
17018d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert
1702d2d6014f715f12f6263f61ba3eeb6f8cba6d0fa6krosaen    /**
1703d2d6014f715f12f6263f61ba3eeb6f8cba6d0fa6krosaen     * compact representation of the activity associated with this search manager so
1704d2d6014f715f12f6263f61ba3eeb6f8cba6d0fa6krosaen     * we can say who we are when starting search.  the search managerservice, in turn,
1705d2d6014f715f12f6263f61ba3eeb6f8cba6d0fa6krosaen     * uses this to properly handle the back stack.
1706d2d6014f715f12f6263f61ba3eeb6f8cba6d0fa6krosaen     */
1707b06ea706530e6d19eb2a1a9a7ae6c5dd77d80af0Dianne Hackborn    private int mIdent;
1708d2d6014f715f12f6263f61ba3eeb6f8cba6d0fa6krosaen
1709d2d6014f715f12f6263f61ba3eeb6f8cba6d0fa6krosaen    /**
1710d2d6014f715f12f6263f61ba3eeb6f8cba6d0fa6krosaen     * The package associated with this seach manager.
1711d2d6014f715f12f6263f61ba3eeb6f8cba6d0fa6krosaen     */
1712d2d6014f715f12f6263f61ba3eeb6f8cba6d0fa6krosaen    private String mAssociatedPackage;
1713b06ea706530e6d19eb2a1a9a7ae6c5dd77d80af0Dianne Hackborn
17148d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert    // package private since they are used by the inner class SearchManagerCallback
17158d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert    /* package */ final Handler mHandler;
17168d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert    /* package */ OnDismissListener mDismissListener = null;
17178d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert    /* package */ OnCancelListener mCancelListener = null;
17188d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert
17198d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert    private final SearchManagerCallback mSearchManagerCallback = new SearchManagerCallback();
17209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /*package*/ SearchManager(Context context, Handler handler)  {
17229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext = context;
17239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mHandler = handler;
17248d1538237847baf381787b881141f8c0478bef5bBjorn Bringert        mService = ISearchManager.Stub.asInterface(
17258d1538237847baf381787b881141f8c0478bef5bBjorn Bringert                ServiceManager.getService(Context.SEARCH_SERVICE));
17269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1727ec0a12cf199659a749ff1fe7b788626eddc095ebKarl Rosaen
1728ec0a12cf199659a749ff1fe7b788626eddc095ebKarl Rosaen    /*package*/ boolean hasIdent() {
1729ec0a12cf199659a749ff1fe7b788626eddc095ebKarl Rosaen        return mIdent != 0;
1730ec0a12cf199659a749ff1fe7b788626eddc095ebKarl Rosaen    }
17319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1732d2d6014f715f12f6263f61ba3eeb6f8cba6d0fa6krosaen    /*package*/ void setIdent(int ident, ComponentName component) {
1733b06ea706530e6d19eb2a1a9a7ae6c5dd77d80af0Dianne Hackborn        if (mIdent != 0) {
1734b06ea706530e6d19eb2a1a9a7ae6c5dd77d80af0Dianne Hackborn            throw new IllegalStateException("mIdent already set");
1735b06ea706530e6d19eb2a1a9a7ae6c5dd77d80af0Dianne Hackborn        }
1736d2d6014f715f12f6263f61ba3eeb6f8cba6d0fa6krosaen        if (component == null) {
1737d2d6014f715f12f6263f61ba3eeb6f8cba6d0fa6krosaen            throw new IllegalArgumentException("component must be non-null");
1738d2d6014f715f12f6263f61ba3eeb6f8cba6d0fa6krosaen        }
1739b06ea706530e6d19eb2a1a9a7ae6c5dd77d80af0Dianne Hackborn        mIdent = ident;
1740d2d6014f715f12f6263f61ba3eeb6f8cba6d0fa6krosaen        mAssociatedPackage = component.getPackageName();
1741b06ea706530e6d19eb2a1a9a7ae6c5dd77d80af0Dianne Hackborn    }
1742b06ea706530e6d19eb2a1a9a7ae6c5dd77d80af0Dianne Hackborn
17439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
17449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Launch search UI.
17459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
17469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>The search manager will open a search widget in an overlapping
17479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * window, and the underlying activity may be obscured.  The search
17489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * entry state will remain in effect until one of the following events:
17499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <ul>
17509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <li>The user completes the search.  In most cases this will launch
17519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * a search intent.</li>
17529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <li>The user uses the back, home, or other keys to exit the search.</li>
17539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <li>The application calls the {@link #stopSearch}
17549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * method, which will hide the search window and return focus to the
17559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * activity from which it was launched.</li>
17569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
17579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>Most applications will <i>not</i> use this interface to invoke search.
17589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * The primary method for invoking search is to call
17599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link android.app.Activity#onSearchRequested Activity.onSearchRequested()} or
17609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link android.app.Activity#startSearch Activity.startSearch()}.
17619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
17629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param initialQuery A search string can be pre-entered here, but this
17639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * is typically null or empty.
17649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param selectInitialQuery If true, the intial query will be preselected, which means that
17659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * any further typing will replace it.  This is useful for cases where an entire pre-formed
17669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * query is being inserted.  If false, the selection point will be placed at the end of the
17679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * inserted query.  This is useful when the inserted query is text that the user entered,
17689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * and the user would expect to be able to keep typing.  <i>This parameter is only meaningful
17699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * if initialQuery is a non-empty string.</i>
17709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param launchActivity The ComponentName of the activity that has launched this search.
17719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param appSearchData An application can insert application-specific
17729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * context here, in order to improve quality or specificity of its own
17739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * searches.  This data will be returned with SEARCH intent(s).  Null if
17749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * no extra data is required.
17759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param globalSearch If false, this will only launch the search that has been specifically
17769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * defined by the application (which is usually defined as a local search).  If no default
1777cfa419b754332e12f8cd45244c2f3bee9d6a74bbMike LeBeau     * search is defined in the current application or activity, global search will be launched.
17789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * If true, this will always launch a platform-global (e.g. web-based) search instead.
17799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
17809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see android.app.Activity#onSearchRequested
17819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #stopSearch
17829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
17839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void startSearch(String initialQuery,
17849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            boolean selectInitialQuery,
17859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            ComponentName launchActivity,
17869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            Bundle appSearchData,
17879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            boolean globalSearch) {
1788b06ea706530e6d19eb2a1a9a7ae6c5dd77d80af0Dianne Hackborn        if (mIdent == 0) throw new IllegalArgumentException(
1789b06ea706530e6d19eb2a1a9a7ae6c5dd77d80af0Dianne Hackborn                "Called from outside of an Activity context");
17903c50ef6f665ab22cdb50c76bb31283e6bac47fc6Bjorn Bringert
17913c50ef6f665ab22cdb50c76bb31283e6bac47fc6Bjorn Bringert        if (globalSearch) {
17923c50ef6f665ab22cdb50c76bb31283e6bac47fc6Bjorn Bringert            startGlobalSearch(initialQuery, selectInitialQuery, appSearchData);
17933c50ef6f665ab22cdb50c76bb31283e6bac47fc6Bjorn Bringert            return;
17943c50ef6f665ab22cdb50c76bb31283e6bac47fc6Bjorn Bringert        }
17953c50ef6f665ab22cdb50c76bb31283e6bac47fc6Bjorn Bringert
17963c50ef6f665ab22cdb50c76bb31283e6bac47fc6Bjorn Bringert        if (!mAssociatedPackage.equals(launchActivity.getPackageName())) {
1797d2d6014f715f12f6263f61ba3eeb6f8cba6d0fa6krosaen            Log.w(TAG, "invoking app search on a different package " +
1798d2d6014f715f12f6263f61ba3eeb6f8cba6d0fa6krosaen                    "not associated with this search manager");
1799d2d6014f715f12f6263f61ba3eeb6f8cba6d0fa6krosaen        }
18008d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert        try {
18018d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert            // activate the search manager and start it up!
18028d1538237847baf381787b881141f8c0478bef5bBjorn Bringert            mService.startSearch(initialQuery, selectInitialQuery, launchActivity, appSearchData,
1803b06ea706530e6d19eb2a1a9a7ae6c5dd77d80af0Dianne Hackborn                    globalSearch, mSearchManagerCallback, mIdent);
18048d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert        } catch (RemoteException ex) {
1805d2d6014f715f12f6263f61ba3eeb6f8cba6d0fa6krosaen            Log.e(TAG, "startSearch() failed.", ex);
1806d2d6014f715f12f6263f61ba3eeb6f8cba6d0fa6krosaen        }
1807d2d6014f715f12f6263f61ba3eeb6f8cba6d0fa6krosaen    }
1808d2d6014f715f12f6263f61ba3eeb6f8cba6d0fa6krosaen
1809d2d6014f715f12f6263f61ba3eeb6f8cba6d0fa6krosaen    /**
18103c50ef6f665ab22cdb50c76bb31283e6bac47fc6Bjorn Bringert     * Starts the global search activity.
18113c50ef6f665ab22cdb50c76bb31283e6bac47fc6Bjorn Bringert     */
18123c50ef6f665ab22cdb50c76bb31283e6bac47fc6Bjorn Bringert    private void startGlobalSearch(String initialQuery, boolean selectInitialQuery,
18133c50ef6f665ab22cdb50c76bb31283e6bac47fc6Bjorn Bringert            Bundle appSearchData) {
18143c50ef6f665ab22cdb50c76bb31283e6bac47fc6Bjorn Bringert        ComponentName globalSearchActivity = getGlobalSearchActivity();
18153c50ef6f665ab22cdb50c76bb31283e6bac47fc6Bjorn Bringert        if (globalSearchActivity == null) {
18163c50ef6f665ab22cdb50c76bb31283e6bac47fc6Bjorn Bringert            Log.w(TAG, "No global search activity found.");
18173c50ef6f665ab22cdb50c76bb31283e6bac47fc6Bjorn Bringert            return;
18183c50ef6f665ab22cdb50c76bb31283e6bac47fc6Bjorn Bringert        }
18193c50ef6f665ab22cdb50c76bb31283e6bac47fc6Bjorn Bringert        Intent intent = new Intent(Intent.ACTION_GLOBAL_SEARCH);
18203c50ef6f665ab22cdb50c76bb31283e6bac47fc6Bjorn Bringert        intent.setComponent(globalSearchActivity);
18213c50ef6f665ab22cdb50c76bb31283e6bac47fc6Bjorn Bringert        // TODO: Always pass name of calling package as an extra?
18223c50ef6f665ab22cdb50c76bb31283e6bac47fc6Bjorn Bringert        if (appSearchData != null) {
18233c50ef6f665ab22cdb50c76bb31283e6bac47fc6Bjorn Bringert            intent.putExtra(APP_DATA, appSearchData);
18243c50ef6f665ab22cdb50c76bb31283e6bac47fc6Bjorn Bringert        }
18253c50ef6f665ab22cdb50c76bb31283e6bac47fc6Bjorn Bringert        if (!TextUtils.isEmpty(initialQuery)) {
18263c50ef6f665ab22cdb50c76bb31283e6bac47fc6Bjorn Bringert            intent.putExtra(INITIAL_QUERY, initialQuery);
18273c50ef6f665ab22cdb50c76bb31283e6bac47fc6Bjorn Bringert        }
18283c50ef6f665ab22cdb50c76bb31283e6bac47fc6Bjorn Bringert        if (selectInitialQuery) {
18293c50ef6f665ab22cdb50c76bb31283e6bac47fc6Bjorn Bringert            intent.putExtra(SELECT_INITIAL_QUERY, selectInitialQuery);
18303c50ef6f665ab22cdb50c76bb31283e6bac47fc6Bjorn Bringert        }
18313c50ef6f665ab22cdb50c76bb31283e6bac47fc6Bjorn Bringert        try {
18323c50ef6f665ab22cdb50c76bb31283e6bac47fc6Bjorn Bringert            if (DBG) Log.d(TAG, "Starting global search: " + intent.toUri(0));
18333c50ef6f665ab22cdb50c76bb31283e6bac47fc6Bjorn Bringert            mContext.startActivity(intent);
18343c50ef6f665ab22cdb50c76bb31283e6bac47fc6Bjorn Bringert        } catch (ActivityNotFoundException ex) {
18353c50ef6f665ab22cdb50c76bb31283e6bac47fc6Bjorn Bringert            Log.e(TAG, "Global search activity not found: " + globalSearchActivity);
18363c50ef6f665ab22cdb50c76bb31283e6bac47fc6Bjorn Bringert        }
18373c50ef6f665ab22cdb50c76bb31283e6bac47fc6Bjorn Bringert    }
18383c50ef6f665ab22cdb50c76bb31283e6bac47fc6Bjorn Bringert
18393c50ef6f665ab22cdb50c76bb31283e6bac47fc6Bjorn Bringert    /**
18403c50ef6f665ab22cdb50c76bb31283e6bac47fc6Bjorn Bringert     * Gets the name of the global search activity.
18413c50ef6f665ab22cdb50c76bb31283e6bac47fc6Bjorn Bringert     *
18423c50ef6f665ab22cdb50c76bb31283e6bac47fc6Bjorn Bringert     * This is currently implemented by returning the first activity that handles
18433c50ef6f665ab22cdb50c76bb31283e6bac47fc6Bjorn Bringert     * the GLOBAL_SEARCH intent and has the GLOBAL_SEARCH permission. If we allow
18443c50ef6f665ab22cdb50c76bb31283e6bac47fc6Bjorn Bringert     * more than one global search acitivity to be installed, this code must be changed.
18453c50ef6f665ab22cdb50c76bb31283e6bac47fc6Bjorn Bringert     *
18463c50ef6f665ab22cdb50c76bb31283e6bac47fc6Bjorn Bringert     * TODO: Doing this every time we start global search is inefficient. Will fix that once
18473c50ef6f665ab22cdb50c76bb31283e6bac47fc6Bjorn Bringert     * we have settled on the right mechanism for finding the global search activity.
18483c50ef6f665ab22cdb50c76bb31283e6bac47fc6Bjorn Bringert     */
18493c50ef6f665ab22cdb50c76bb31283e6bac47fc6Bjorn Bringert    private ComponentName getGlobalSearchActivity() {
18503c50ef6f665ab22cdb50c76bb31283e6bac47fc6Bjorn Bringert        Intent intent = new Intent(Intent.ACTION_GLOBAL_SEARCH);
18513c50ef6f665ab22cdb50c76bb31283e6bac47fc6Bjorn Bringert        PackageManager pm = mContext.getPackageManager();
18523c50ef6f665ab22cdb50c76bb31283e6bac47fc6Bjorn Bringert        List<ResolveInfo> activities =
18533c50ef6f665ab22cdb50c76bb31283e6bac47fc6Bjorn Bringert                pm.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
18543c50ef6f665ab22cdb50c76bb31283e6bac47fc6Bjorn Bringert        int count = activities.size();
18553c50ef6f665ab22cdb50c76bb31283e6bac47fc6Bjorn Bringert        for (int i = 0; i < count; i++) {
18563c50ef6f665ab22cdb50c76bb31283e6bac47fc6Bjorn Bringert            ActivityInfo ai = activities.get(i).activityInfo;
18573c50ef6f665ab22cdb50c76bb31283e6bac47fc6Bjorn Bringert            if (pm.checkPermission(Manifest.permission.GLOBAL_SEARCH,
18583c50ef6f665ab22cdb50c76bb31283e6bac47fc6Bjorn Bringert                    ai.packageName) == PackageManager.PERMISSION_GRANTED) {
18593c50ef6f665ab22cdb50c76bb31283e6bac47fc6Bjorn Bringert                return new ComponentName(ai.packageName, ai.name);
18603c50ef6f665ab22cdb50c76bb31283e6bac47fc6Bjorn Bringert            } else {
18613c50ef6f665ab22cdb50c76bb31283e6bac47fc6Bjorn Bringert                Log.w(TAG, "Package " + ai.packageName + " wants to handle GLOBAL_SEARCH, "
18623c50ef6f665ab22cdb50c76bb31283e6bac47fc6Bjorn Bringert                        + "but does not have the GLOBAL_SEARCH permission.");
18633c50ef6f665ab22cdb50c76bb31283e6bac47fc6Bjorn Bringert            }
18643c50ef6f665ab22cdb50c76bb31283e6bac47fc6Bjorn Bringert        }
18653c50ef6f665ab22cdb50c76bb31283e6bac47fc6Bjorn Bringert        return null;
18663c50ef6f665ab22cdb50c76bb31283e6bac47fc6Bjorn Bringert    }
18673c50ef6f665ab22cdb50c76bb31283e6bac47fc6Bjorn Bringert
18683c50ef6f665ab22cdb50c76bb31283e6bac47fc6Bjorn Bringert    /**
1869d2d6014f715f12f6263f61ba3eeb6f8cba6d0fa6krosaen     * Similar to {@link #startSearch} but actually fires off the search query after invoking
1870d2d6014f715f12f6263f61ba3eeb6f8cba6d0fa6krosaen     * the search dialog.  Made available for testing purposes.
1871d2d6014f715f12f6263f61ba3eeb6f8cba6d0fa6krosaen     *
1872d2d6014f715f12f6263f61ba3eeb6f8cba6d0fa6krosaen     * @param query The query to trigger.  If empty, request will be ignored.
1873d2d6014f715f12f6263f61ba3eeb6f8cba6d0fa6krosaen     * @param launchActivity The ComponentName of the activity that has launched this search.
1874d2d6014f715f12f6263f61ba3eeb6f8cba6d0fa6krosaen     * @param appSearchData An application can insert application-specific
1875d2d6014f715f12f6263f61ba3eeb6f8cba6d0fa6krosaen     * context here, in order to improve quality or specificity of its own
1876d2d6014f715f12f6263f61ba3eeb6f8cba6d0fa6krosaen     * searches.  This data will be returned with SEARCH intent(s).  Null if
1877d2d6014f715f12f6263f61ba3eeb6f8cba6d0fa6krosaen     * no extra data is required.
1878d2d6014f715f12f6263f61ba3eeb6f8cba6d0fa6krosaen     *
1879d2d6014f715f12f6263f61ba3eeb6f8cba6d0fa6krosaen     * @see #startSearch
1880d2d6014f715f12f6263f61ba3eeb6f8cba6d0fa6krosaen     */
1881d2d6014f715f12f6263f61ba3eeb6f8cba6d0fa6krosaen    public void triggerSearch(String query,
1882d2d6014f715f12f6263f61ba3eeb6f8cba6d0fa6krosaen                              ComponentName launchActivity,
1883b782a2f4f0a3072f2677f6f10fb255c77468ae66Bjorn Bringert                              Bundle appSearchData) {
1884d2d6014f715f12f6263f61ba3eeb6f8cba6d0fa6krosaen        if (mIdent == 0) throw new IllegalArgumentException(
1885d2d6014f715f12f6263f61ba3eeb6f8cba6d0fa6krosaen                "Called from outside of an Activity context");
1886d2d6014f715f12f6263f61ba3eeb6f8cba6d0fa6krosaen        if (!mAssociatedPackage.equals(launchActivity.getPackageName())) {
1887d2d6014f715f12f6263f61ba3eeb6f8cba6d0fa6krosaen            throw new IllegalArgumentException("invoking app search on a different package " +
1888d2d6014f715f12f6263f61ba3eeb6f8cba6d0fa6krosaen                    "not associated with this search manager");
1889d2d6014f715f12f6263f61ba3eeb6f8cba6d0fa6krosaen        }
1890d2d6014f715f12f6263f61ba3eeb6f8cba6d0fa6krosaen        if (query == null || TextUtils.getTrimmedLength(query) == 0) {
1891d2d6014f715f12f6263f61ba3eeb6f8cba6d0fa6krosaen            Log.w(TAG, "triggerSearch called with empty query, ignoring.");
1892d2d6014f715f12f6263f61ba3eeb6f8cba6d0fa6krosaen            return;
1893d2d6014f715f12f6263f61ba3eeb6f8cba6d0fa6krosaen        }
1894d2d6014f715f12f6263f61ba3eeb6f8cba6d0fa6krosaen        try {
1895d2d6014f715f12f6263f61ba3eeb6f8cba6d0fa6krosaen            mService.triggerSearch(query, launchActivity, appSearchData, mSearchManagerCallback,
1896b782a2f4f0a3072f2677f6f10fb255c77468ae66Bjorn Bringert                    mIdent);
1897d2d6014f715f12f6263f61ba3eeb6f8cba6d0fa6krosaen        } catch (RemoteException ex) {
1898d2d6014f715f12f6263f61ba3eeb6f8cba6d0fa6krosaen            Log.e(TAG, "triggerSearch() failed.", ex);
18999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
19009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
19019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
19039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Terminate search UI.
19049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
19059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>Typically the user will terminate the search UI by launching a
19069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * search or by canceling.  This function allows the underlying application
19079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * or activity to cancel the search prematurely (for any reason).
19089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
19099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>This function can be safely called at any time (even if no search is active.)
19109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
19119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #startSearch
19129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
19138d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert    public void stopSearch() {
1914ea52d29bc46c306f3607d121aa1ad84f0e9eb473Karl Rosaen        if (DBG) debug("stopSearch()");
19158d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert        try {
19168d1538237847baf381787b881141f8c0478bef5bBjorn Bringert            mService.stopSearch();
19178d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert        } catch (RemoteException ex) {
19189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
19199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
19209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
19229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Determine if the Search UI is currently displayed.
19239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
19249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * This is provided primarily for application test purposes.
19259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
19269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return Returns true if the search UI is currently displayed.
19279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
19289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @hide
19299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
19308d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert    public boolean isVisible() {
1931ea52d29bc46c306f3607d121aa1ad84f0e9eb473Karl Rosaen        if (DBG) debug("isVisible()");
1932ea52d29bc46c306f3607d121aa1ad84f0e9eb473Karl Rosaen        try {
1933ea52d29bc46c306f3607d121aa1ad84f0e9eb473Karl Rosaen            return mService.isVisible();
1934ea52d29bc46c306f3607d121aa1ad84f0e9eb473Karl Rosaen        } catch (RemoteException e) {
1935ea52d29bc46c306f3607d121aa1ad84f0e9eb473Karl Rosaen            Log.e(TAG, "isVisible() failed: " + e);
1936ea52d29bc46c306f3607d121aa1ad84f0e9eb473Karl Rosaen            return false;
1937ea52d29bc46c306f3607d121aa1ad84f0e9eb473Karl Rosaen        }
19389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
19398d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert
19409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1941a058f02b591d971a829cb1e28d48a992e46ad85eKarl Rosaen     * See {@link SearchManager#setOnDismissListener} for configuring your activity to monitor
1942a058f02b591d971a829cb1e28d48a992e46ad85eKarl Rosaen     * search UI state.
19439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
19449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public interface OnDismissListener {
19459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
1946a058f02b591d971a829cb1e28d48a992e46ad85eKarl Rosaen         * This method will be called when the search UI is dismissed. To make use of it, you must
1947a058f02b591d971a829cb1e28d48a992e46ad85eKarl Rosaen         * implement this method in your activity, and call
1948a058f02b591d971a829cb1e28d48a992e46ad85eKarl Rosaen         * {@link SearchManager#setOnDismissListener} to register it.
19499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
19509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void onDismiss();
19519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
19529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1954a058f02b591d971a829cb1e28d48a992e46ad85eKarl Rosaen     * See {@link SearchManager#setOnCancelListener} for configuring your activity to monitor
1955a058f02b591d971a829cb1e28d48a992e46ad85eKarl Rosaen     * search UI state.
19569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
19579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public interface OnCancelListener {
19589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
19599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * This method will be called when the search UI is canceled. To make use if it, you must
1960a058f02b591d971a829cb1e28d48a992e46ad85eKarl Rosaen         * implement this method in your activity, and call
1961a058f02b591d971a829cb1e28d48a992e46ad85eKarl Rosaen         * {@link SearchManager#setOnCancelListener} to register it.
19629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
19639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void onCancel();
19649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
19659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
19679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Set or clear the callback that will be invoked whenever the search UI is dismissed.
19689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
19699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param listener The {@link OnDismissListener} to use, or null.
19709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
19719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setOnDismissListener(final OnDismissListener listener) {
19729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mDismissListener = listener;
19739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
19749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
19769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Set or clear the callback that will be invoked whenever the search UI is canceled.
19779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
19789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param listener The {@link OnCancelListener} to use, or null.
19799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
19808d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert    public void setOnCancelListener(OnCancelListener listener) {
19819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mCancelListener = listener;
19829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
19838d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert
19848d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert    private class SearchManagerCallback extends ISearchManagerCallback.Stub {
19858d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert
19868d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert        private final Runnable mFireOnDismiss = new Runnable() {
19878d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert            public void run() {
19888d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert                if (DBG) debug("mFireOnDismiss");
19898d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert                if (mDismissListener != null) {
19908d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert                    mDismissListener.onDismiss();
19918d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert                }
19928d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert            }
19938d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert        };
19948d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert
19958d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert        private final Runnable mFireOnCancel = new Runnable() {
19968d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert            public void run() {
19978d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert                if (DBG) debug("mFireOnCancel");
19988d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert                if (mCancelListener != null) {
19998d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert                    mCancelListener.onCancel();
20008d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert                }
20019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
20028d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert        };
20038d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert
20048d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert        public void onDismiss() {
20058d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert            if (DBG) debug("onDismiss()");
20068d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert            mHandler.post(mFireOnDismiss);
20078d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert        }
20088d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert
20098d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert        public void onCancel() {
20108d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert            if (DBG) debug("onCancel()");
20118d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert            mHandler.post(mFireOnCancel);
20129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
20138d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert
20148d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert    }
20158d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert
20160e01ea41b215941128a4ea8dee454e6b35a4e798Bjorn Bringert    /**
20170e01ea41b215941128a4ea8dee454e6b35a4e798Bjorn Bringert     * @deprecated This method is an obsolete internal implementation detail. Do not use.
20180e01ea41b215941128a4ea8dee454e6b35a4e798Bjorn Bringert     */
20194a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn    @Deprecated
20208d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert    public void onCancel(DialogInterface dialog) {
20218d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert        throw new UnsupportedOperationException();
20228d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert    }
20230e01ea41b215941128a4ea8dee454e6b35a4e798Bjorn Bringert
20240e01ea41b215941128a4ea8dee454e6b35a4e798Bjorn Bringert    /**
20250e01ea41b215941128a4ea8dee454e6b35a4e798Bjorn Bringert     * @deprecated This method is an obsolete internal implementation detail. Do not use.
20260e01ea41b215941128a4ea8dee454e6b35a4e798Bjorn Bringert     */
20274a51c20ce607c74914f90fd897f04080121ac13bDianne Hackborn    @Deprecated
20288d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert    public void onDismiss(DialogInterface dialog) {
20298d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert        throw new UnsupportedOperationException();
20309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
20319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
20329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2033875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen     * Gets information about a searchable activity. This method is static so that it can
2034875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen     * be used from non-Activity contexts.
2035875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen     *
2036875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen     * @param componentName The activity to get searchable information for.
2037875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen     * @param globalSearch If <code>false</code>, return information about the given activity.
2038875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen     *        If <code>true</code>, return information about the global search activity.
2039875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen     * @return Searchable information, or <code>null</code> if the activity is not searchable.
2040875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen     *
2041875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen     * @hide because SearchableInfo is not part of the API.
2042875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen     */
20438d1538237847baf381787b881141f8c0478bef5bBjorn Bringert    public SearchableInfo getSearchableInfo(ComponentName componentName,
2044875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen            boolean globalSearch) {
2045875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen        try {
20468d1538237847baf381787b881141f8c0478bef5bBjorn Bringert            return mService.getSearchableInfo(componentName, globalSearch);
20478d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert        } catch (RemoteException ex) {
20488d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert            Log.e(TAG, "getSearchableInfo() failed: " + ex);
2049875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen            return null;
2050875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen        }
2051875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen    }
2052875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen
2053875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen    /**
2054875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen     * Checks whether the given searchable is the default searchable.
2055875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen     *
2056875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen     * @hide because SearchableInfo is not part of the API.
2057875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen     */
20588d1538237847baf381787b881141f8c0478bef5bBjorn Bringert    public boolean isDefaultSearchable(SearchableInfo searchable) {
20598d1538237847baf381787b881141f8c0478bef5bBjorn Bringert        SearchableInfo defaultSearchable = getSearchableInfo(null, true);
2060875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen        return defaultSearchable != null
2061a92041306e4d73baa10fb711fb905b9590f06b26Bjorn Bringert                && defaultSearchable.getSearchActivity().equals(searchable.getSearchActivity());
2062875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen    }
20638d1538237847baf381787b881141f8c0478bef5bBjorn Bringert
2064875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen    /**
206597325db8565ad503b86d9a0f602b2d001b5cee13Bjorn Bringert     * Gets a cursor with search suggestions.
206697325db8565ad503b86d9a0f602b2d001b5cee13Bjorn Bringert     *
206797325db8565ad503b86d9a0f602b2d001b5cee13Bjorn Bringert     * @param searchable Information about how to get the suggestions.
206897325db8565ad503b86d9a0f602b2d001b5cee13Bjorn Bringert     * @param query The search text entered (so far).
206997325db8565ad503b86d9a0f602b2d001b5cee13Bjorn Bringert     * @return a cursor with suggestions, or <code>null</null> the suggestion query failed.
207097325db8565ad503b86d9a0f602b2d001b5cee13Bjorn Bringert     *
207197325db8565ad503b86d9a0f602b2d001b5cee13Bjorn Bringert     * @hide because SearchableInfo is not part of the API.
207297325db8565ad503b86d9a0f602b2d001b5cee13Bjorn Bringert     */
207397325db8565ad503b86d9a0f602b2d001b5cee13Bjorn Bringert    public Cursor getSuggestions(SearchableInfo searchable, String query) {
20743fc7c67de192a5baee2b4510fdb464b0fec72dcaBjorn Bringert        return getSuggestions(searchable, query, -1);
20753fc7c67de192a5baee2b4510fdb464b0fec72dcaBjorn Bringert    }
20763fc7c67de192a5baee2b4510fdb464b0fec72dcaBjorn Bringert
20773fc7c67de192a5baee2b4510fdb464b0fec72dcaBjorn Bringert    /**
20783fc7c67de192a5baee2b4510fdb464b0fec72dcaBjorn Bringert     * Gets a cursor with search suggestions.
20793fc7c67de192a5baee2b4510fdb464b0fec72dcaBjorn Bringert     *
20803fc7c67de192a5baee2b4510fdb464b0fec72dcaBjorn Bringert     * @param searchable Information about how to get the suggestions.
20813fc7c67de192a5baee2b4510fdb464b0fec72dcaBjorn Bringert     * @param query The search text entered (so far).
20823fc7c67de192a5baee2b4510fdb464b0fec72dcaBjorn Bringert     * @param limit The query limit to pass to the suggestion provider. This is advisory,
20833fc7c67de192a5baee2b4510fdb464b0fec72dcaBjorn Bringert     *        the returned cursor may contain more rows. Pass {@code -1} for no limit.
20843fc7c67de192a5baee2b4510fdb464b0fec72dcaBjorn Bringert     * @return a cursor with suggestions, or <code>null</null> the suggestion query failed.
20853fc7c67de192a5baee2b4510fdb464b0fec72dcaBjorn Bringert     *
20863fc7c67de192a5baee2b4510fdb464b0fec72dcaBjorn Bringert     * @hide because SearchableInfo is not part of the API.
20873fc7c67de192a5baee2b4510fdb464b0fec72dcaBjorn Bringert     */
20883fc7c67de192a5baee2b4510fdb464b0fec72dcaBjorn Bringert    public Cursor getSuggestions(SearchableInfo searchable, String query, int limit) {
2089875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen        if (searchable == null) {
2090875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen            return null;
2091875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen        }
2092875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen
2093875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen        String authority = searchable.getSuggestAuthority();
2094875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen        if (authority == null) {
2095875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen            return null;
2096875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen        }
2097875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen
2098875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen        Uri.Builder uriBuilder = new Uri.Builder()
2099875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen                .scheme(ContentResolver.SCHEME_CONTENT)
21003fc7c67de192a5baee2b4510fdb464b0fec72dcaBjorn Bringert                .authority(authority)
21013fc7c67de192a5baee2b4510fdb464b0fec72dcaBjorn Bringert                .query("")  // TODO: Remove, workaround for a bug in Uri.writeToParcel()
21023fc7c67de192a5baee2b4510fdb464b0fec72dcaBjorn Bringert                .fragment("");  // TODO: Remove, workaround for a bug in Uri.writeToParcel()
2103875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen
2104875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen        // if content path provided, insert it now
2105875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen        final String contentPath = searchable.getSuggestPath();
2106875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen        if (contentPath != null) {
2107875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen            uriBuilder.appendEncodedPath(contentPath);
2108875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen        }
2109875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen
21103fc7c67de192a5baee2b4510fdb464b0fec72dcaBjorn Bringert        // append standard suggestion query path
2111875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen        uriBuilder.appendPath(SearchManager.SUGGEST_URI_PATH_QUERY);
2112875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen
2113875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen        // get the query selection, may be null
2114875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen        String selection = searchable.getSuggestSelection();
2115875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen        // inject query, either as selection args or inline
2116875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen        String[] selArgs = null;
2117875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen        if (selection != null) {    // use selection if provided
2118875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen            selArgs = new String[] { query };
2119875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen        } else {                    // no selection, use REST pattern
2120875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen            uriBuilder.appendPath(query);
2121875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen        }
2122875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen
21233fc7c67de192a5baee2b4510fdb464b0fec72dcaBjorn Bringert        if (limit > 0) {
21243fc7c67de192a5baee2b4510fdb464b0fec72dcaBjorn Bringert            uriBuilder.appendQueryParameter(SUGGEST_PARAMETER_LIMIT, String.valueOf(limit));
21253fc7c67de192a5baee2b4510fdb464b0fec72dcaBjorn Bringert        }
21263fc7c67de192a5baee2b4510fdb464b0fec72dcaBjorn Bringert
21273fc7c67de192a5baee2b4510fdb464b0fec72dcaBjorn Bringert        Uri uri = uriBuilder.build();
2128875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen
2129875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen        // finally, make the query
21308d1538237847baf381787b881141f8c0478bef5bBjorn Bringert        return mContext.getContentResolver().query(uri, null, selection, selArgs, null);
2131875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen    }
2132875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen
21336d72e029cb6e5a9cf26aa3314c3dca83614fc91bBjorn Bringert    /**
21346d72e029cb6e5a9cf26aa3314c3dca83614fc91bBjorn Bringert     * Returns a list of the searchable activities that can be included in global search.
21356d72e029cb6e5a9cf26aa3314c3dca83614fc91bBjorn Bringert     *
21366d72e029cb6e5a9cf26aa3314c3dca83614fc91bBjorn Bringert     * @return a list containing searchable information for all searchable activities
213713107bb186d72bc80dc5609b20c71b7e77a9784dBjorn Bringert     *         that have the <code>android:includeInGlobalSearch</code> attribute set
213813107bb186d72bc80dc5609b20c71b7e77a9784dBjorn Bringert     *         in their searchable meta-data.
21396d72e029cb6e5a9cf26aa3314c3dca83614fc91bBjorn Bringert     */
21408d1538237847baf381787b881141f8c0478bef5bBjorn Bringert    public List<SearchableInfo> getSearchablesInGlobalSearch() {
21416d72e029cb6e5a9cf26aa3314c3dca83614fc91bBjorn Bringert        try {
21428d1538237847baf381787b881141f8c0478bef5bBjorn Bringert            return mService.getSearchablesInGlobalSearch();
21436d72e029cb6e5a9cf26aa3314c3dca83614fc91bBjorn Bringert        } catch (RemoteException e) {
21448d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert            Log.e(TAG, "getSearchablesInGlobalSearch() failed: " + e);
21456d72e029cb6e5a9cf26aa3314c3dca83614fc91bBjorn Bringert            return null;
21466d72e029cb6e5a9cf26aa3314c3dca83614fc91bBjorn Bringert        }
21476d72e029cb6e5a9cf26aa3314c3dca83614fc91bBjorn Bringert    }
2148f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath
2149f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath    /**
2150f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath     * Returns a list of the searchable activities that handle web searches.
2151f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath     *
21528d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert     * @return a list of all searchable activities that handle
21538d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert     *         {@link android.content.Intent#ACTION_WEB_SEARCH}.
2154f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath     *
2155f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath     * @hide because SearchableInfo is not part of the API.
2156f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath     */
21578d1538237847baf381787b881141f8c0478bef5bBjorn Bringert    public List<SearchableInfo> getSearchablesForWebSearch() {
2158f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath        try {
21598d1538237847baf381787b881141f8c0478bef5bBjorn Bringert            return mService.getSearchablesForWebSearch();
2160f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath        } catch (RemoteException e) {
21618d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert            Log.e(TAG, "getSearchablesForWebSearch() failed: " + e);
2162f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath            return null;
2163f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath        }
2164f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath    }
2165f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath
2166f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath    /**
2167f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath     * Returns the default searchable activity for web searches.
2168f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath     *
2169f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath     * @return searchable information for the activity handling web searches by default.
2170f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath     *
2171f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath     * @hide because SearchableInfo is not part of the API.
2172f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath     */
21738d1538237847baf381787b881141f8c0478bef5bBjorn Bringert    public SearchableInfo getDefaultSearchableForWebSearch() {
2174f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath        try {
21758d1538237847baf381787b881141f8c0478bef5bBjorn Bringert            return mService.getDefaultSearchableForWebSearch();
2176f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath        } catch (RemoteException e) {
21778d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert            Log.e(TAG, "getDefaultSearchableForWebSearch() failed: " + e);
2178f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath            return null;
2179f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath        }
2180f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath    }
2181f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath
2182f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath    /**
2183f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath     * Sets the default searchable activity for web searches.
2184f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath     *
2185f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath     * @param component Name of the component to set as default activity for web searches.
2186f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath     *
2187f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath     * @hide
2188f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath     */
21898d1538237847baf381787b881141f8c0478bef5bBjorn Bringert    public void setDefaultWebSearch(ComponentName component) {
2190f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath        try {
21918d1538237847baf381787b881141f8c0478bef5bBjorn Bringert            mService.setDefaultWebSearch(component);
2192f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath        } catch (RemoteException e) {
21938d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert            Log.e(TAG, "setDefaultWebSearch() failed: " + e);
2194f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath        }
2195f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath    }
21968d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert
21978d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert    private static void debug(String msg) {
21988d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert        Thread thread = Thread.currentThread();
21998d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert        Log.d(TAG, msg + " (" + thread.getName() + "-" + thread.getId() + ")");
22008d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringert    }
2201d27b10837525f341eee7d46013e2177b0bad3c60Scott Main}