1 page.title=Using the Android Search Dialog
8 <h2>In this document</h2>
10 <li><a href="#TheBasics">The Basics</a></li>
11 <li><a href="#SearchableConfiguration">Creating a Searchable Configuration</a></li>
12 <li><a href="#SearchableActivity">Creating a Searchable Activity</a>
14 <li><a href="#DeclaringSearchableActivity">Declaring a searchable Activity</a></li>
15 <li><a href="#PerformingSearch">Performing a search</a></li>
18 <li><a href="#InvokingTheSearchDialog">Invoking the Search Dialog</a>
20 <li><a href="#LifeCycle">The impact of the search dialog on your Activity life-cycle</a></li>
23 <li><a href="#SearchContextData">Passing Search Context Data</a></li>
24 <li><a href="#VoiceSearch">Adding Voice Search</a></li>
29 <li>{@link android.app.SearchManager}</li>
32 <h2>Related samples</h2>
34 <li><a href="{@docRoot}resources/samples/SearchableDictionary/index.html">Searchable
40 <li><a href="{@docRoot}shareables/search_icons.zip">search_icons.zip</a></li>
45 <li><a href="adding-recent-query-suggestions.html">Adding Recent Query Suggestions</a></li>
46 <li><a href="adding-custom-suggestions.html">Adding Custom Suggestions</a></li>
47 <li><a href="searchable-config.html">Searchable Configuration</a></li>
53 <p>When you want to implement search in your application, the last thing you should have to worry
54 about is where to put the search box. When you implement search with the Android search framework,
55 you don't have to. When the user invokes search, a search dialog appears at the top of the screen
56 with your application icon to the left of the search box. When the user executes the search, your
57 application receives the query so it can search your application's data. An example of the search
58 dialog is shown in figure 1.</p>
60 <p>This guide shows you how to set up your application to provide search in the search
61 dialog. When you use the search dialog, you provide a standardized search
62 experience and can add features such as voice search and search suggestions.</p>
65 <h2 id="TheBasics">The Basics</h2>
67 <div class="figure" style="width:250px">
68 <img src="{@docRoot}images/search/search-ui.png" alt="" height="417" />
69 <p class="img-caption"><strong>Figure 1.</strong> Screenshot of an application's search dialog.</p>
72 <p>The Android search framework manages the search dialog for your application. You never need
73 to draw it or worry about where it is, and your Activity is not interrupted when the search dialog
74 appears. The Search Manager ({@link android.app.SearchManager}) is the component that does this work
75 for you. It manages the life of the search dialog and sends your application the user's search
78 <p>When the user executes a search, the Search Manager creates an {@link android.content.Intent} to
79 pass the search query to the Activity that you've declared to handle searches. Basically, all you
80 need is an Activity that receives the search Intent, performs the search, and presents the results.
81 Specifically, you need the following:</p>
84 <dt>A searchable configuration</dt>
85 <dd>An XML file that configures the search dialog and includes settings for features such as voice
86 search, search suggestion, and the hint text.</dd>
87 <dt>A searchable Activity</dt>
88 <dd>The {@link android.app.Activity} that receives the search query, then searches your data and
89 displays the search results.</dd>
90 <dt>A mechanism by which the user can invoke search</dt>
91 <dd>The device search key invokes the search dialog, by default. However, a dedicated search key
92 is not guaranteed on all devices, so provide another means by which the user can invoke a search,
93 such as a search button in the Options Menu or elsewhere in the Activity UI.</dd>
98 <h2 id="SearchableConfiguration">Creating a Searchable Configuration</h2>
100 <p>The searchable configuration is an XML file that defines several settings for the search
101 dialog in your application. This file is traditionally named {@code searchable.xml} and must be
102 saved in the {@code res/xml/} project directory.</p>
104 <p>The file must consist of the {@code <searchable>} element as the root node and specify one
105 or more attributes that configure your search dialog. For example:</p>
108 <?xml version="1.0" encoding="utf-8"?>
109 <searchable xmlns:android="http://schemas.android.com/apk/res/android"
110 android:label="@string/app_label"
111 android:hint="@string/search_hint" >
115 <p>The {@code android:label} attribute is the only required attribute and points to a string
116 resource, which should be the same as the application name. This label isn't actually visible to the
117 user until you enable suggestions for Quick Search Box, at which point, this label is visible in the
118 list of Searchable items in the system Settings.</p>
120 <p>Though it's not required, we recommend that you always include the {@code android:hint}
121 attribute, which provides a hint string in the search dialog's text box before the user
122 enters their query. The hint is important because it provides important clues to users about what
125 <p class="note"><strong>Tip:</strong> For consistency among other
126 Android applications, you should format the string for {@code android:hint} as "Search
127 <em><content-or-product></em>". For example, "Search songs and artists" or "Search
130 <p>The {@code <searchable>} element accepts several other attributes. Most attributes apply
131 only when configuring features such as search suggestions and voice search.</p>
133 <p>For more details about the searchable configuration file, see the <a
134 href="{@docRoot}guide/topics/search/searchable-config.html">Searchable Configuration</a>
139 <h2 id="SearchableActivity">Creating a Searchable Activity</h2>
141 <p>When the user executes a search from the search dialog, the Search Manager takes the query
142 and sends it to your searchable {@link android.app.Activity} in the {@link
143 android.content.Intent#ACTION_SEARCH} {@link android.content.Intent}. Your searchable Activity
144 then searches your data using the query and presents the results to the user.</p>
146 <p>In order for the Search Manager to know where to deliver the search query, you must declare your
147 searchable Activity in the Android manifest file.</p>
150 <h3 id="DeclaringSearchableActivity">Declaring a searchable Activity</h3>
152 <p>If you don't have one already, create an {@link android.app.Activity} that performs
153 searches and present search results. To set up this Activity as your searchable Activity:</p>
155 <li>Declare the Activity to accept the {@link android.content.Intent#ACTION_SEARCH} {@link
156 android.content.Intent}, in an <a
157 href="{@docRoot}guide/topics/manifest/intent-filter-element.html">{@code <intent-filter>}</a>
159 <li>Apply the searchable configuration, in a <a
160 href="{@docRoot}guide/topics/manifest/meta-data-element.html">{@code <meta-data>}</a>
167 <application ... >
168 <activity android:name=".MySearchableActivity" >
170 <action android:name="android.intent.action.SEARCH" />
172 <meta-data android:name="android.app.searchable"
173 android:resource="@xml/searchable"/>
179 <p>The {@code <meta-data>} element must include the {@code android:name} attribute with a
180 value of {@code "android.app.searchable"} and the {@code android:resource} attribute with a
181 reference to the searchable configuration file (in this example, it
182 refers to the {@code res/xml/searchable.xml} file).</p>
184 <p class="note"><strong>Note:</strong> The {@code <intent-filter>} does not need a <a
185 href="{@docRoot}guide/topics/manifest/category-element.html">{@code <category>}</a> with the
186 {@code DEFAULT} value, because the Search Manager delivers the {@link
187 android.content.Intent#ACTION_SEARCH} Intent explicitly to your searchable Activity by name.</p>
189 <p>The search dialog is not, by default, available from every Activity of your
190 application. Rather, the search dialog is presented to users only when they
191 invoke search from a searchable context of your application. A searchable context is any Activity
193 declared searchable meta-data in the manifest file. For example, the searchable Activity itself
194 (declared in the manifest snippet above) is
195 a searchable context because it includes meta-data that defines the
196 searchable configuration. Any other Activity in your application is not a searchable context, by
197 default, and thus, does not reveal the search dialog. However, you probably do want the search
198 dialog available from your other activities (and to launch the searchable Activity when the user
199 executes a search). You can do exactly that.</p>
201 <p>If you want all of your activities to provide the search dialog, add another {@code
202 <meta-data>} element inside the {@code
203 <application>} element. Use this element to declare the existing searchable Activity as the
204 default searchable Activity. For example:</p>
207 <application ... >
208 <activity android:name=".MySearchableActivity" >
210 <action android:name="android.intent.action.SEARCH" />
212 <meta-data android:name="android.app.searchable"
213 android:resource="@xml/searchable"/>
215 <activity android:name=".AnotherActivity" ... >
217 <!-- declare the default searchable Activity for the whole app -->
218 <b><meta-data android:name="android.app.default_searchable"
219 android:value=".MySearchableActivity" /></b>
224 <p>The {@code <meta-data>} element with the {@code android:name} attribute value of
225 {@code "android.app.default_searchable"} specifies a default searchable Activity for the context in
226 which it is placed (which, in this case, is the entire application). The searchable Activity to
227 use is specified with the {@code android:value} attribute. All other activities in the
228 application, such as {@code AnotherActivity}, are now considered a searchable context and can invoke
229 the search dialog. When a search is executed, {@code MySearchableActivity} is launched to handle
230 the search query.</p>
232 <p>You can also control which activities provide search at a more granular level.
233 To specify only an individual Activity as a searchable context, place the {@code
234 <meta-data>} with the {@code
235 "android.app.default_searchable"} name inside the respective {@code <activity>}
236 element (rather than inside the {@code <application>} element). While uncommon, you
237 can also create more than one searchable Activity and provide each one in different contexts of your
238 application, either by declaring a different searchable Activity in each {@code <activity>}
239 element, or by declaring a default searchable Activity for the entire application and then
240 overriding it with a {@code <meta-data>} element inside certain activities. (You might do
241 this if you want to search different sets of data that cannot be handled by the same
242 searchable Activity, depending on the currently open Activity.)</p>
245 <h3 id="PerformingSearch">Performing a search</h3>
247 <p>Once you have declared your searchable Activity, performing a search for the user involves
250 <li><a href="#ReceivingTheQuery">Receiving the query</a></li>
251 <li><a href="#SearchingYourData">Searching your data</a></li>
252 <li><a href="#PresentingTheResults">Presenting the results</a></li>
255 <p>Traditionally, your search results should be presented in a {@link android.widget.ListView}, so
256 you might want your searchable Activity to extend {@link android.app.ListActivity}, which
257 provides easy access to {@link android.widget.ListView} APIs. (See the <a
258 href="{@docRoot}resources/tutorials/views/hello-listview.html">List View Tutorial</a> for a simple
259 {@link android.app.ListActivity} sample.)</p>
262 <h4 id="ReceivingTheQuery">Receiving the query</h4>
264 <p>When a user executes a search from the search dialog, the Search Manager sends the {@link
265 android.content.Intent#ACTION_SEARCH} {@link android.content.Intent} to your searchable Activity.
266 This Intent carries the search query in the
267 {@link android.app.SearchManager#QUERY QUERY} string extra. You must check for
268 this Intent when the Activity starts and extract the string. For example, here's how you can get the
269 query when your Activity starts:</p>
273 public void onCreate(Bundle savedInstanceState) {
274 super.onCreate(savedInstanceState);
275 setContentView(R.layout.search);
277 Intent intent = getIntent();
279 if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
280 String query = intent.getStringExtra(SearchManager.QUERY);
286 <p>The {@link android.app.SearchManager#QUERY QUERY} string is always included with
287 the {@link android.content.Intent#ACTION_SEARCH} Intent. In this example, the query is
288 retrieved and passed to a local {@code doMySearch()} method where the actual search operation
292 <h4 id="SearchingYourData">Searching your data</h4>
294 <p>The process of storing and searching your data is unique to your application.
295 You can store and search your data in many ways, but this guide does not show you how to store your
296 data and search it. Storing and searching your data is something you should carefully consider in
297 terms of your needs and your data. However, here are some tips you might be able to apply:</p>
300 <li>If your data is stored in a SQLite database on the device, performing a full-text search
301 (using FTS3, rather than a LIKE query) can provide a more robust search across text data and can
302 produce results significantly faster. See <a href="http://sqlite.org/fts3.html">sqlite.org</a>
303 for information about FTS3 and the {@link android.database.sqlite.SQLiteDatabase} class for
304 information about SQLite on Android. Also look at the <a
305 href="{@docRoot}resources/samples/SearchableDictionary/index.html">Searchable Dictionary</a> sample
306 application to see a complete SQLite implementation that performs searches with FTS3.</li>
307 <li>If your data is stored online, then the perceived search performance might be
308 inhibited by the user's data connection. You might want to display a spinning progress wheel until
309 your search returns. See {@link android.net} for a reference of network APIs and <a
310 href="{@docRoot}guide/topics/ui/dialogs.html#ProgressDialog">Creating a Progress Dialog</a> to see
311 how you can display a progress wheel.</li>
315 <div class="sidebox-wrapper">
316 <div class="sidebox">
317 <h2>About Adapters</h2>
318 <p>An Adapter binds individual items from a set of data into individual {@link
319 android.view.View} objects. When the Adapter
320 is applied to a {@link android.widget.ListView}, the Views are injected as individual items of the
322 android.widget.Adapter} is simply an interface, so implementations such as {@link
323 android.widget.CursorAdapter} (for binding data from a {@link android.database.Cursor}) are needed.
324 If none of the existing implementations work for your data, then you should implement your own from
325 {@link android.widget.BaseAdapter}. Install the SDK Samples package for API Level 4 to see the
326 original version of the Searchable Dictionary, which creates a custom BaseAdapter.</p>
330 <p>Regardless of where your data lives and how you search it, we recommend that you return search
331 results to your searchable Activity with an {@link android.widget.Adapter}. This way, you can easily
332 present all the search results in a {@link android.widget.ListView}. If your data comes from a
333 SQLite database query, then you can apply your results to a {@link android.widget.ListView}
334 using a {@link android.widget.CursorAdapter}. If your data comes in some other type of format, then
335 you can create an extension of the {@link android.widget.BaseAdapter}.</p>
337 <h4 id="PresentingTheResults">Presenting the results</h4>
339 <p>Presenting your search results is mostly a UI detail that is not handled by the search APIs.
340 However, one option is to create your searchable Activity to extend {@link
341 android.app.ListActivity} and call {@link
342 android.app.ListActivity#setListAdapter(ListAdapter)}, passing it an {@link
343 android.widget.Adapter} that is bound to your data. This injects all the
344 results into the Activity {@link android.widget.ListView}.</p>
346 <p>For more help presenting your results, see the {@link android.app.ListActivity}
350 href="{@docRoot}resources/samples/SearchableDictionary/index.html">Searchable Dictionary</a> sample
351 for an a complete demonstration of how to search an SQLite database and use an
352 {@link android.widget.Adapter} to provide results in a {@link android.widget.ListView}.</p>
356 <h2 id="InvokingTheSearchDialog">Invoking the Search Dialog</h2>
358 <p>Once you have a searchable Activity, invoking the search dialog is easy. Many Android
359 devices provide a dedicated SEARCH key, which reveals the search dialog when the user presses it
360 from a searchable context of your application. However, you should not assume that a SEARCH
361 key is available on the user's device and should always provide a search button in your UI that
364 <p>To invoke search from your Activity, call {@link android.app.Activity#onSearchRequested()}.</p>
366 <p>For instance, you should provide a menu item in your <a
367 href="{@docRoot}guide/topics/ui/menus.html#options-menu">Options Menu</a> or a button in your UI to
368 invoke search with this method. The <a
369 href="{@docRoot}shareables/search_icons.zip">search_icons.zip</a> file includes icons for
370 medium and high density screens, which you can use for your search menu item or button (low density
371 screens automatically scale-down the hdpi image by one half). </p>
373 <!-- ... maybe this should go into the Creating Menus document ....
374 <p>If you chose to provide a shortcut key for the menu item, using {@link
375 android.view.MenuItem#setAlphabeticShortcut(char)}, then SearchManager.MENU_KEY is the recommended
376 key character, representing the default search key.</p>
379 <p>You can also enable "type-to-search" functionality, which reveals the search dialog when the
380 user starts typing on the keyboard and the keystrokes are inserted into the search dialog. You can
381 enable type-to-search in your Activity by calling
382 {@link android.app.Activity#setDefaultKeyMode(int) setDefaultKeyMode}({@link
383 android.app.Activity#DEFAULT_KEYS_SEARCH_LOCAL}) during your Activity's
384 {@link android.app.Activity#onCreate(Bundle) onCreate()} method.</p>
387 <h3 id="LifeCycle">The impact of the search dialog on your Activity lifecycle</h3>
389 <p>The search dialog is a {@link android.app.Dialog} that floats at the top of the
390 screen. It does not cause any change in the Activity stack, so when the search dialog appears, no
391 lifecycle methods for the currently open Activity (such as {@link
392 android.app.Activity#onPause()}) are called. Your Activity just loses input focus as it is given to
396 <p>If you want to be notified when search is invoked, override the {@link
397 android.app.Activity#onSearchRequested()} method. When the system calls this method, you can do any
398 work you want to when your Activity looses input focus to the search dialog (such as pause
399 animations). Unless you are <a href="#SearchContextData">passing search context data</a>
400 (discussed below), you should end the method by calling the super class implementation. For
405 public boolean onSearchRequested() {
407 return super.onSearchRequested();
411 <p>If the user cancels search by pressing the BACK key, the Activity in which search was
412 invoked re-gains input focus. You can register to be notified when the search dialog is
413 closed with {@link android.app.SearchManager#setOnDismissListener(SearchManager.OnDismissListener)
414 setOnDismissListener()}
415 and/or {@link android.app.SearchManager#setOnCancelListener(SearchManager.OnCancelListener)
416 setOnCancelListener()}. You
417 should need to register only the {@link android.app.SearchManager.OnDismissListener
418 OnDismissListener}, because it is called every time the search dialog closes. The {@link
419 android.app.SearchManager.OnCancelListener OnCancelListener} only pertains to events in which the
420 user explicitly exited the search dialog, so it is not called when a search is executed (in which
421 case, the search dialog naturally disappears).</p>
423 <p>If the current Activity is not the searchable Activity, then the normal Activity lifecycle
424 events are triggered once the user executes a search (the current Activity receives {@link
425 android.app.Activity#onPause()} and so forth, as
426 described in <a href="{@docRoot}guide/topics/fundamentals.html#lcycles">Application
427 Fundamentals</a>). If, however, the current Activity is the searchable Activity, then one of two
431 <li>By default, the searchable Activity receives the {@link
432 android.content.Intent#ACTION_SEARCH} Intent with a call to {@link
433 android.app.Activity#onCreate(Bundle) onCreate()} and a new instance of the
434 Activity is brought to the top of the Activity stack. There are now two instances of your
435 searchable Activity in the Activity stack (so pressing the BACK key goes back to the previous
436 instance of the searchable Activity, rather than exiting the searchable Activity).</li>
437 <li>If you set {@code android:launchMode} to "singleTop", then the
438 searchable Activity receives the {@link android.content.Intent#ACTION_SEARCH} Intent with a call
439 to {@link android.app.Activity#onNewIntent(Intent)}, passing the new {@link
440 android.content.Intent#ACTION_SEARCH} Intent here. For example, here's how you might handle
441 this case, in which the searchable Activity's launch mode is "singleTop":
444 public void onCreate(Bundle savedInstanceState) {
445 super.onCreate(savedInstanceState);
446 setContentView(R.layout.search);
447 handleIntent(getIntent());
451 protected void onNewIntent(Intent intent) {
453 handleIntent(intent);
456 private void handleIntent(Intent intent) {
457 if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
458 String query = intent.getStringExtra(SearchManager.QUERY);
464 <p>Compared to the example code in the section about <a href="#PerformingSearch">Performing a
465 Search</a>, all the code to handle the
466 search Intent is now in the {@code handleIntent()} method, so that both {@link
467 android.app.Activity#onCreate(Bundle)
468 onCreate()} and {@link android.app.Activity#onNewIntent(Intent) onNewIntent()} can execute it.</p>
470 <p>When the system calls {@link android.app.Activity#onNewIntent(Intent)}, the Activity has
471 not been restarted, so the {@link android.app.Activity#getIntent()} method
472 returns the same Intent that was received with {@link
473 android.app.Activity#onCreate(Bundle) onCreate()}. This is why you should call {@link
474 android.app.Activity#setIntent(Intent)} inside {@link
475 android.app.Activity#onNewIntent(Intent)} (so that the Intent saved by the Activity is updated in
476 case you call {@link android.app.Activity#getIntent()} in the future).</p>
481 <p>The second scenario using "singleTop" launch mode is usually ideal, because chances are good that
482 once a search is done, the user will perform additional searches and it's a bad experience if your
483 application creates multiple instances of the searchable Activity. So, we recommend that you set
484 your searchable Activity to "singleTop" launch mode in the application
485 manifest. For example:</p>
488 <activity android:name=".MySearchableActivity"
489 <b>android:launchMode="singleTop"</b> >
491 <action android:name="android.intent.action.SEARCH" />
493 <meta-data android:name="android.app.searchable"
494 android:resource="@xml/searchable"/>
500 <h2 id="SearchContextData">Passing Search Context Data</h2>
502 <p>To refine your search criteria from the current Activity instead of depending only on the user's
503 search query, you can provide additional data in the Intent that the Search Manager sends to your
504 searchable Activity. In a simple case, you can make your refinements inside the searchable
505 Activity, for every search made, but if your
506 search criteria varies from one searchable context to another, then you can pass whatever data
507 is necessary to refine your search in the {@link android.app.SearchManager#APP_DATA} {@link
508 android.os.Bundle}, which is included in the {@link android.content.Intent#ACTION_SEARCH}
511 <p>To pass this kind of data to your searchable Activity, override {@link
512 android.app.Activity#onSearchRequested()} method for the Activity in which search can be invoked.
517 public boolean onSearchRequested() {
518 Bundle appData = new Bundle();
519 appData.putBoolean(MySearchableActivity.JARGON, true);
520 startSearch(null, false, appData, false);
525 <p>Returning "true" indicates that you have successfully handled this callback event. Then in your
526 searchable Activity, you can extract the data placed inside {@code appdata} from the {@link
527 android.app.SearchManager#APP_DATA} {@link android.os.Bundle} to refine the search. For example:</p>
530 Bundle appData = getIntent().getBundleExtra(SearchManager.APP_DATA);
531 if (appData != null) {
532 boolean jargon = appData.getBoolean(MySearchableActivity.JARGON);
536 <p class="caution"><strong>Caution:</strong> Never call the {@link
537 android.app.Activity#startSearch(String,boolean,Bundle,boolean) startSearch()} method from outside
538 the {@link android.app.Activity#onSearchRequested()} callback method. To invoke the search dialog
539 in your Activity, always call {@link android.app.Activity#onSearchRequested()}. Otherwise, {@link
540 android.app.Activity#onSearchRequested()} is not called and customizations (such as the addition of
541 {@code appData} in the above example) are missed.</p>
544 <h2 id="VoiceSearch">Adding Voice Search</h2>
546 <p>You can add voice search functionality to your search dialog by adding the {@code
547 android:voiceSearchMode} attribute to your searchable configuration. This adds a voice search
548 button in the search dialog that launches a voice prompt. When the user
549 has finished speaking, the transcribed search query is sent to your searchable
555 <?xml version="1.0" encoding="utf-8"?>
556 <searchable xmlns:android="http://schemas.android.com/apk/res/android"
557 android:label="@string/search_label"
558 android:hint="@string/search_hint"
559 <b>android:voiceSearchMode="showVoiceSearchButton|launchRecognizer"</b> >
563 <p>The value {@code showVoiceSearchButton} is required to enable voice
564 search, while the second value, {@code launchRecognizer}, specifies that the voice search button
565 should launch a recognizer that returns the transcribed text to the searchable Activity.</p>
567 <p>You can provide additional attributes to specify the voice search behavior, such
568 as the language to be expected and the maximum number of results to return. See the <a
569 href="searchable-config.html">Searchable Configuration</a> reference for more information about the
570 available attributes.</p>
572 <p class="note"><strong>Note:</strong> Carefully consider whether voice search is appropriate for
573 your application. All searches performed with the voice search button are immediately sent to
574 your searchable Activity without a chance for the user to review the transcribed query. Sufficiently
575 test the voice recognition and ensure that it understands the types of queries that
576 the user might submit inside your application.</p>