page.title=Using the Android Search Dialog
parent.title=Search
parent.link=index.html
@jd:body

<div id="qv-wrapper">
<div id="qv">
<h2>Key classes</h2>
<ol>
<li>{@link android.app.SearchManager}</li>
</ol>
<h2>In this document</h2>
<ol>
<li><a href="#TheBasics">The Basics</a></li>
<li><a href="#SearchableConfiguration">Creating a Searchable Configuration</a></li>
<li><a href="#SearchableActivity">Creating a Searchable Activity</a>
  <ol>
    <li><a href="#DeclaringSearchableActivity">Declaring a searchable Activity</a></li>
    <li><a href="#PerformingSearch">Performing a search</a></li>
  </ol>
</li>
<li><a href="#InvokingTheSearchDialog">Invoking the Search Dialog</a>
  <ol>
    <li><a href="#LifeCycle">The impact of the search dialog on your Activity life-cycle</a></li>
  </ol>
</li>
<li><a href="#SearchContextData">Passing Search Context Data</a></li>
<li><a href="#VoiceSearch">Adding Voice Search</a></li>
</ol>
<h2>See also</h2>
<ol>
<li><a href="adding-recent-query-suggestions.html">Adding Recent Query Suggestions</a></li>
<li><a href="adding-custom-suggestions.html">Adding Custom Suggestions</a></li>
<li><a href="searchable-config.html">Searchable Configuration</a></li>
<li><a href="{@docRoot}resources/samples/SearchableDictionary/index.html">Searchable
Dictionary App</a></li>
</ol>
</div>
</div>

<p>When you want to provide search in your application, the last thing you should have to worry
about is where to put your search box. By using the Android search framework, your application will
reveal a custom search dialog whenever the user requests it. At the
press of a dedicated search key or an API call from your application, the search dialog will
appear at the top of the screen and will automatically show your application icon. An example is
shown in the screenshot below.</p>

<p>This guide will teach you how to set up your application to provide search in a custom search
dialog. In doing so, you will provide a standardized search experience and be able to add
features like voice search and search suggestions.</p>


<h2 id="TheBasics">The Basics</h2>

<img src="{@docRoot}images/search/search-ui.png" alt="" height="417"
style="float:right;clear:right;" />

<p>The Android search framework will manage the search dialog on your behalf; you never need
to draw it or worry about where it is, and your current Activity will not be
interrupted. The {@link android.app.SearchManager} is the component that does this work for
you (hereafter, referred to as "the Search Manager"). It manages the life of the Android search
dialog and will send your application the search query when executed by the user.</p>

<p>When the user executes a search, the Search Manager will use a specially-formed Intent to pass
the search query to the Activity that you've declared to handle searches. Essentially, all you
need is an Activity that receives this Intent, performs the search, and presents the results.
Specifically, what you need is the following:</p>

<dl>
  <dt>A searchable configuration</dt>
  <dd>This is an XML file that configures the search dialog and includes settings for
features such as the hint text shown in text box and settings voice search and search
suggestion.</dd>
  <dt>A searchable Activity</dt>
  <dd>This is the {@link android.app.Activity} that receives the search query then
searches your data and displays the search results.</dd>
  <dt>A mechanism by which the user can invoke search</dt>
  <dd>By default, the device search key (if available) will invoke the search dialog once
you've configured a searchable Activity. However, you should always provide another means by
which the user can invoke a search, such as with a search button in the Options Menu or elsewhere in
the Activity UI, because not all devices provide a dedicated search key.</dd>
</dl>


<h2 id="SearchableConfiguration">Creating a Searchable Configuration</h2>

<p>The searchable configuration is an XML file that defines several settings for the Android search
dialog in your application. This file is traditionally named {@code searchable.xml} and must be
saved in the {@code res/xml/} project directory.</p>

<p>The file must consist of the {@code &lt;searchable&gt;} element as the root node and specify one
or more attributes that configure your search dialog. For example:</p>

<pre>
&lt;?xml version="1.0" encoding="utf-8"?>
&lt;searchable xmlns:android="http://schemas.android.com/apk/res/android"
    android:label="@string/app_label" >
&lt;/searchable>
</pre>

<p>This is the minimum configuration required in order to provide the search dialog. The {@code
android:label} attribute is the only required attribute and points to a string resource, which
should normally be the same as the application. (Although it's required, this
label isn't actually shown to the user until you enable suggestions for Quick Search Box.)</p>

<p>There are several other attributes accepted by the {@code &lt;searchable&gt;} element. Most of
which apply only when configuring features such as search suggestions and voice
search. However, we recommend that you always include the {@code android:hint} attribute, which
specifies a string resource for the text to display in the search dialog's text box before the user
enters their query&mdash;it provides important clues to the user about what they can search. </p>

<p class="note"><strong>Tip:</strong> For consistency among other
Android applications, you should format the string for {@code android:hint} as "Search
<em>&lt;content-or-product&gt;</em>". For example, "Search songs and artists" or "Search
YouTube".</p>

<p>Next, you'll hook this configuration into your application.</p>


<h2 id="SearchableActivity">Creating a Searchable Activity</h2>

<p>When the user executes a search from the search dialog, the Search Manager will send
your searchable {@link android.app.Activity} the search query with the {@link
android.content.Intent#ACTION_SEARCH} {@link android.content.Intent}. Your searchable Activity will
then search your data and present the results.</p>


<h3 id="DeclaringSearchableActivity">Declaring a searchable Activity</h3>

<p>If you don't have one already, create an {@link android.app.Activity} that will be used to
perform searches, then declare it to
accept the {@link android.content.Intent#ACTION_SEARCH} {@link android.content.Intent} and apply the
searchable configuration. To do so, you need to add an {@code
&lt;intent-filter&gt;} element and a {@code &lt;meta-data&gt;} element to the
appropriate {@code &lt;activity&gt;} element in your manifest file. For example:</p>

<pre>
&lt;application ... >
    &lt;activity android:name=".MySearchableActivity" >
        &lt;intent-filter>
            &lt;action android:name="android.intent.action.SEARCH" />
        &lt;/intent-filter>
        &lt;meta-data android:name="android.app.searchable"
                   android:resource="@xml/searchable"/>
    &lt;/activity>
    ...
&lt;/application>
</pre>

<p>The {@code android:name} attribute in the {@code &lt;meta-data&gt;} element must be defined with
{@code "android.app.searchable"} and the {@code android:resource} attribute value must be a
reference to the searchable configuration file saved in {@code res/xml} (in this example, it
refers to the {@code res/xml/searchable.xml} file).</p>

<p class="note">If you're wondering why the {@code
&lt;intent-filter&gt;} does not include a {@code &lt;category&gt;} with the {@code DEFAULT}
value, it's because the Intent that is delivered to this Activity when a search is executed will
explicitly define this Activity as the component for the Intent (which the Search Manager knows
from the searcahble meta-data declared for the Activity).</p>

<p>Be aware that the search dialog will not be available from within every
Activity of your application, by default. Rather, the search dialog will be presented to
users only when they
invoke search from a searchable context of your application. A searchable context is any Activity
for which you have
declared searchable meta-data in the manifest file. For example, the searchable Activity itself
(declared in the manifest snippet above) is
a searchable context because it contains searchable meta-data that defines the
searchable configuration. Any other Activity in your application is not a searchable context, by
default, and thus, will not reveal the search dialog. You probably do want the
search dialog to be available from every Activity in your application, so this can be easily
fixed.</p>

<p>If you want all of your activities to provide the search dialog, add another {@code
&lt;meta-data&gt;} element inside the {@code
&lt;application&gt;} element. Use this element to declare the existing searchable Activity as the
default searchable Activity. For example:</p>

<pre>
&lt;application ... >
    &lt;activity android:name=".MySearchableActivity" >
        &lt;intent-filter>
            &lt;action android:name="android.intent.action.SEARCH" />
        &lt;/intent-filter>
        &lt;meta-data android:name="android.app.searchable"
                   android:resource="@xml/searchable"/>
    &lt;/activity>
    &lt;activity android:name=".AnotherActivity" ... >
    &lt;/activity>
    &lt;!-- this one declares the searchable Activity for the whole app --&gt;
    &lt;meta-data android:name="android.app.default_searchable"
               android:value=".MySearchableActivity" />
    ...
&lt;/application>
</pre>

<p>The {@code &lt;meta-data&gt;} element with the {@code android:name} attribute value of
{@code "android.app.default_searchable"} specifies a default searchable Activity for the context in
which it is placed (which, in this case, is the entire application). The searchable Activity to
use is specified with the {@code android:value} attribute. All other activities in the
application, such as {@code AnotherActivity}, are now considered a searchable context and can invoke
the search dialog. When a search is executed, {@code MySearchableActivity} will
be launched to handle the search query.</p>

<p>Notice that this allows you to control which activities provide search at a more granular level.
To specify only an individual Activity as a searchable context, simply place the {@code
&lt;meta-data&gt;} with the {@code
"android.app.default_searchable"} name inside the respective {@code &lt;activity&gt;}
element (rather than inside the {@code &lt;application&gt;}). And, while it is uncommon, you can
even create more than one searchable Activity and provide each one in different contexts of your
application, either by declaring a different searchable Activity in each {@code &lt;activity&gt;}
element, or declaring a default searchable Activity for the entire application and then overriding
it with a different {@code &lt;meta-data&gt;} element inside certain activities.</p>


<h3 id="PerformingSearch">Performing a search</h3>

<p>Once your Activity is declared searchable, performing the actual search involves three steps:
receiving the query, searching your data, and presenting the results.</p>

<p>Traditionally, your search results should be presented in a {@link android.widget.ListView}
(assuming that our results are text-based), so
you may want your searchable Activity to extend {@link android.app.ListActivity}, which 
provides easy access to {@link android.widget.ListView} APIs. (See the <a
href="{@docRoot}resources/tutorials/views/hello-listview.html">List View Tutorial</a> for a simple
{@link android.app.ListActivity} sample.)</p>


<h4 id="ReceivingTheQuery">Receiving the query</h4>

<p>When a search is executed from the search dialog, your searchable Activity will be opened
with the {@link android.content.Intent#ACTION_SEARCH} {@link android.content.Intent}, which carries
the search query in the
{@link android.app.SearchManager#QUERY QUERY} extra. All you need to do is check for
this Intent and extract the string. For example, here's how you can get the query when your
Activity launches:</p>

<pre>
&#64;Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.search);

    Intent intent = getIntent();

    if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
      String query = intent.getStringExtra(SearchManager.QUERY);
      doMySearch(query);
    }
}
</pre>

<p>The {@link android.app.SearchManager#QUERY QUERY} string is always included with
the {@link android.content.Intent#ACTION_SEARCH} Intent. In this example, the query is
retrieved and passed to a local {@code doMySearch()} method where the actual search operation
is done.</p>


<h4 id="SearchingYourData">Searching your data</h4>

<p>The process of storing and searching your data is a process that's unique to your application.
There are many ways that you might do this and discussing all options is beyond the scope of
this document. This guide will not teach you how to store your data and search it; this
is something you must carefully consider in terms of your needs and your data. However, here are
some tips you may be able to apply:</p>

  <ul>
    <li>If your data is stored in a SQLite database on the device, performing a full-text search
(using FTS3, rather than a LIKE query) can provide a more robust search across text data and can
produce results many, many times faster. See <a href="http://sqlite.org/fts3.html">sqlite.org</a>
for information about FTS3 and the {@link android.database.sqlite.SQLiteDatabase} class for
information about SQLite on Android. Also look at the <a
href="{@docRoot}resources/samples/SearchableDictionary/index.html">Searchable Dictionary</a> sample
application to see a complete SQLite implementation that performs searches with FTS3.</li>
    <li>If your data is stored online, then the perceived search performance may be
inhibited by the user's data connection. You may want to display a spinning progress wheel until
your search returns. See {@link android.net} for a reference of network APIs and <a
href="{@docRoot}guide/topics/ui/dialogs.html#ProgressDialog">Creating a Progress Dialog</a> to see
how you can display a progress wheel.</li>
  </ul>


<div class="sidebox-wrapper">
<div class="sidebox">
<h2>About Adapters</h2>
<p>An Adapter will bind individual items from a set of data into individual {@link
android.view.View} objects. When the Adapter
is applied to a {@link android.widget.ListView}, the Views are injected as individual items of the
list. {@link
android.widget.Adapter} is simply an interface, so implementations such as {@link
android.widget.CursorAdapter} (for binding data from a {@link android.database.Cursor}) are needed.
If none of the existing implementations work for your data, then you should implement your own from
{@link android.widget.BaseAdapter}. Install the SDK Samples package for API Level 4 to see a
version of the Searchable Dictionary that creates a custom BaseAdapter.</p>
</div>
</div>

<p>Regardless of where your data lives and how you search it, we recommend that you return search
results to your searchable Activity with an {@link android.widget.Adapter}. This way, you can easily
present all the search results in a {@link android.widget.ListView}. If your data comes from a
SQLite database query, then you can easily apply your results to a {@link android.widget.ListView}
using a {@link android.widget.CursorAdapter}. If your data comes in some other type of format, then
you can create an extension of the {@link android.widget.BaseAdapter}.</p>

<h4 id="PresentingTheResults">Presenting the results</h4>

<p>Presenting your search results is mostly a UI detail and not something covered by the search
framework APIs. However, a simple solution is to create your searchable Activity to extend {@link
android.app.ListActivity} and then call {@link
android.app.ListActivity#setListAdapter(ListAdapter)}, passing it an {@link
android.widget.Adapter} that is bound to your data. This will automatically project all the
results into the Activity {@link android.widget.ListView}.</p>

<p>For more help presenting your results, see the {@link android.app.ListActivity}
documentation.</p>

<p>Also see the <a
href="{@docRoot}resources/samples/SearchableDictionary/index.html">Searchable Dictionary</a> sample
application for an a complete demonstration of how to search an SQLite database and use an
{@link android.widget.Adapter} to provide resuls in a {@link android.widget.ListView}.</p>


<h2 id="InvokingTheSearchDialog">Invoking the Search Dialog</h2>

<p>Once you have a searchable Activity in place, invoking the search dialog so the user can
submit a
query is easy. Many Android devices provide a dedicated search key and when it is pressed while the
user is within a searchable context of your application, the search dialog will be revealed.
However,
you should never assume that a search key is available on the user's device and should always
provide a search button in your UI that will invoke search.</p>

<p>To invoke search from your Activity, simply call {@link
android.app.Activity#onSearchRequested()}.</p>

<p>For example, you should provide a menu item in your <a
href="{@docRoot}guide/topics/ui/menus.html#options-menu">Options Menu</a> or a button in your UI to
invoke search with this method. For your convenience, this <a
href="{@docRoot}shareables/search_icons.zip">search_icons.zip</a> file includes icons for
medium and high density screens, which you can use for your menu item or button (low density
screens will automatically scale-down the hdpi image by one half). </p>

<!-- ... maybe this should go into the Creating Menus document ....
<p>If you chose to provide a shortcut key for the menu item,  using {@link
android.view.MenuItem#setAlphabeticShortcut(char)}, then SearchManager.MENU_KEY is the recommended
key character, representing the default search key.</p>
-->

<p>You can also enable "type-to-search" functionality in your Activity by calling {@link
android.app.Activity#setDefaultKeyMode(int) setDefaultKeyMode}({@link
android.app.Activity#DEFAULT_KEYS_SEARCH_LOCAL}). When this is enabled and the user begins typing on
the keyboard, search will automatically be
invoked and the keystrokes will be inserted in the search dialog. Be sure to enable this mode
during your Activity {@link android.app.Activity#onCreate(Bundle) onCreate()} method.</p>


<h3 id="LifeCycle">The impact of the search dialog on your Activity life-cycle</h3>

<p>The search dialog behaves like a {@link android.app.Dialog} that floats at the top of the
screen. It
does not cause any change in the Activity stack, so no life-cycle methods (such as {@link
android.app.Activity#onPause()}) will
be called. All that happens is your Activity loses input focus as it is given to the search dialog.
</p>

<p>If you want to be notified when search is invoked, simply override the {@link
android.app.Activity#onSearchRequested()} method. When this is called, you can do any work you may
want to do when your Activity looses input focus (such as pause animations). But unless you are
<a href="#SearchContextData">Passing Search Context Data</a> (discussed above), you should always
call the super class implementation. For example:</p>

<pre>
&#64;Override
public boolean onSearchRequested() {
    pauseSomeStuff();
    return super.onSearchRequested();
}
</pre>

<p>If the user cancels search by pressing the device Back key, the Activity in which search was
invoked will re-gain input focus. You can register to be notified when the search dialog is
closed with {@link android.app.SearchManager#setOnDismissListener(SearchManager.OnDismissListener)}
and/or {@link android.app.SearchManager#setOnCancelListener(SearchManager.OnCancelListener)}. You
should normally only need to register the {@link android.app.SearchManager.OnDismissListener
OnDismissListener}, because this is called every time that the search dialog is closed. The {@link
android.app.SearchManager.OnCancelListener OnCancelListener} only pertains to events in which the
user explicitly left the search dialog, so it is not called when a search is executed (in which
case, the search dialog naturally disappears).</p>

<p>If the current Activity is not the searchable Activity, then the normal Activity life-cycle
events will be triggered once the user executes a search (the current Activity will receive {@link
android.app.Activity#onPause()} and so forth, as
described in <a href="{@docRoot}guide/topics/fundamentals.html#lcycles">Application
Fundamentals</a>). If, however, the current Activity is the searchable Activity, then one of two
things will happen:</p>

<ul>
  <li>By default, the searchable Activity will receive the {@link
android.content.Intent#ACTION_SEARCH} Intent with a call to {@link
android.app.Activity#onCreate(Bundle) onCreate()} and a new instance of the
Activity will be brought to the top of the stack. You'll now have two instances of your searchable
Activity in the Activity stack (so pressing the Back key will go back to the previous instance of
the searchable Activity, rather than exiting the searchable Activity).</li>
  <li>On the other hand, if the Activity has set {@code android:launchMode} to "singleTop" then the
searchable Activity will receive the {@link android.content.Intent#ACTION_SEARCH} Intent with a call
to {@link android.app.Activity#onNewIntent(Intent)}, passing the new {@link
android.content.Intent#ACTION_SEARCH} Intent here. For example, here's how you might want to handle
this case:
<pre>
&#64;Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.search);
    handleIntent(getIntent());
}

&#64;Override
protected void onNewIntent(Intent intent) {
    setIntent(intent);
    handleIntent(intent);
}

private void handleIntent(Intent intent) {
    if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
      String query = intent.getStringExtra(SearchManager.QUERY);
      doMySearch(query);
    }
}
</pre>

<p>Compared to the example code in the section about <a href="#PerfomingSearch">Performing a
Search</a>, all the code to handle the
search Intent has been moved outside the {@link android.app.Activity#onCreate(Bundle)
onCreate()} method so it can also be executed from {@link android.app.Activity#onNewIntent(Intent)
onNewIntent()}.
It's important to note that when {@link android.app.Activity#onNewIntent(Intent)} is
called, the Activity has not been restarted, so the {@link android.app.Activity#getIntent()} method
will still return the Intent that was first received with {@link
android.app.Activity#onCreate(Bundle) onCreate()}. This is why {@link
android.app.Activity#setIntent(Intent)} is called inside {@link
android.app.Activity#onNewIntent(Intent)} (just in case you call {@link
android.app.Activity#getIntent()} at a later time).</p>

</li>
</ul>

<p>This second scenario is normally ideal, because the chances are good that once a search is
completed, the user will perform additional searches and it's a bad experience if your application
piles multiple instances of the searchable Activity on the stack. So we recommend that you set your
searchable Activity to "singleTop" launch mode in the application manifest. For example:</p>

<pre>
&lt;activity android:name=".MySearchableActivity"
              android:launchMode="singleTop" >
    &lt;intent-filter>
        &lt;action android:name="android.intent.action.SEARCH" />
    &lt;/intent-filter>
    &lt;meta-data android:name="android.app.searchable"
                      android:resource="@xml/searchable"/>
  &lt;/activity>
</pre>


<h2 id="SearchContextData">Passing Search Context Data</h2>

<p>In order to refine your search criteria, you may want to provide some additional
data to your searchable Activity when a search is executed. For instance, when you search your data,
you may want to filter results based on more than just the search query text. In a simple
case, you could just make your refinements inside the searchable Activity, for every search made.
If, however, your
search criteria may vary from one searchable context to another, then you can pass whatever data is
necessary to refine your search in the {@link android.app.SearchManager#APP_DATA} Bundle, which is
included in the {@link android.content.Intent#ACTION_SEARCH} Intent.</p>

<p>To pass this kind of data to your searchable Activity, you need to override  {@link
android.app.Activity#onSearchRequested()} method for the Activity in which search will be invoked.
For example:</p>

<pre>
&#64;Override
public boolean onSearchRequested() {
     Bundle appData = new Bundle();
     appData.putBoolean(MySearchableActivity.JARGON, true);
     startSearch(null, false, appData, false);
     return true;
 }
</pre>

<p>Returning "true" indicates that you have successfully handled this callback event. Then in your
searchable Activity, you can extract this data from the {@link
android.app.SearchManager#APP_DATA} {@link android.os.Bundle} to refine the search. For example:</p>

<pre>
 Bundle appData = getIntent().getBundleExtra(SearchManager.APP_DATA);
 if (appData != null) {
     boolean jargon = appData.getBoolean(MySearchableActivity.JARGON);
 }
</pre>

<p class="caution"><strong>Note:</strong> You should never call the {@link
android.app.Activity#startSearch(String,boolean,Bundle,boolean) startSearch()} method from outside
the {@link android.app.Activity#onSearchRequested()} callback method. When you want to invoke the
search dialog, always call {@link android.app.Activity#onSearchRequested()} so that custom
implementations (such as the addition of {@code appData}, in the above example) can be accounted
for.</p>


<h2 id="VoiceSearch">Adding Voice Search</h2>

<p>You can easily add voice search functionality to your search dialog by adding the {@code
android:voiceSearchMode} attribute to your searchable configuration. This will add a voice search
button in the search dialog that, when clicked, will launch a voice prompt. When the user
has finished speaking, the transcribed search query will be sent to your searchable
Activity.</p>

<p>To enable voice search for your activity, add the {@code android:voiceSearchMode}
attribute to your searchable configuration. For example:</p>

<pre>
&lt;?xml version="1.0" encoding="utf-8"?>
&lt;searchable xmlns:android="http://schemas.android.com/apk/res/android"
    android:label="@string/search_label"
    android:hint="@string/search_hint"
    android:voiceSearchMode="showVoiceSearchButton|launchRecognizer" >
&lt;/searchable>
</pre>

<p>The value {@code showVoiceSearchButton} is required to enable voice
search, while the second value, {@code launchRecognizer}, specifies that the voice search button
should launch a recognizer that returns the transcribed text to the searchable Activity. This is
how most applications should declare this attribute.</p>

<p>There are some additional attributes you can provide to specify the voice search behavior, such
as the language to be expected and the maximum number of results to return. See the <a
href="searchable-config.html">Searchable Configuration</a> for more information about the
available attributes.</p>

<p class="note"><strong>Note:</strong> Carefully consider whether voice search is appropriate for
your application. All searches performed with the voice search button will be immediately sent to
your searchable Activity without a chance for the user to review the transcribed query. Be sure to
sufficiently test the voice recognition and ensure that it understands the types of queries that
the user will submit inside your application.</p>
