search-dialog.jd revision ec80d7f311b1a0899bb4caf5b380b07027e902d1
1page.title=Using the Android Search Dialog
2parent.title=Search
3parent.link=index.html
4@jd:body
5
6<div id="qv-wrapper">
7<div id="qv">
8<h2>In this document</h2>
9<ol>
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>
13  <ol>
14    <li><a href="#DeclaringSearchableActivity">Declaring a searchable Activity</a></li>
15    <li><a href="#PerformingSearch">Performing a search</a></li>
16  </ol>
17</li>
18<li><a href="#InvokingTheSearchDialog">Invoking the Search Dialog</a>
19  <ol>
20    <li><a href="#LifeCycle">The impact of the search dialog on your Activity life-cycle</a></li>
21  </ol>
22</li>
23<li><a href="#SearchContextData">Passing Search Context Data</a></li>
24<li><a href="#VoiceSearch">Adding Voice Search</a></li>
25</ol>
26
27<h2>Key classes</h2>
28<ol>
29<li>{@link android.app.SearchManager}</li>
30</ol>
31
32<h2>Related samples</h2>
33<ol>
34<li><a href="{@docRoot}resources/samples/SearchableDictionary/index.html">Searchable
35Dictionary</a></li>
36</ol>
37
38<h2>Downloads</h2>
39<ol>
40<li><a href="{@docRoot}shareables/search_icons.zip">search_icons.zip</a></li>
41</ol>
42
43<h2>See also</h2>
44<ol>
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>
48</ol>
49
50</div>
51</div>
52
53<p>When you want to implement search in your application, the last thing you should have to worry
54about is where to put the search box. When you implement search with the Android search framework,
55you don't have to. When the user invokes search, a search dialog appears at the top of the screen
56with your application icon to the left of the search box. When the user executes the search, your
57application receives the query so it can search your application's data. An example of the search
58dialog is shown in figure 1.</p>
59
60<p>This guide shows you how to set up your application to provide search in the search
61dialog. When you use the search dialog, you provide a standardized search
62experience and can add features such as voice search and search suggestions.</p>
63
64
65<h2 id="TheBasics">The Basics</h2>
66
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>
70</div>
71
72<p>The Android search framework manages the search dialog for your application. You never need
73to draw it or worry about where it is, and your Activity is not interrupted when the search dialog
74appears. The Search Manager ({@link android.app.SearchManager}) is the component that does this work
75for you. It manages the life of the search dialog and sends your application the user's search
76query.</p>
77
78<p>When the user executes a search, the Search Manager creates an {@link android.content.Intent} to
79pass the search query to the Activity that you've declared to handle searches. Basically, all you
80need is an Activity that receives the search Intent, performs the search, and presents the results.
81Specifically, you need the following:</p>
82
83<dl>
84  <dt>A searchable configuration</dt>
85  <dd>An XML file that configures the search dialog and includes settings for features such as voice
86search, 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
89displays 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
92is not guaranteed on all devices, so provide another means by which the user can invoke a search,
93such as a search button in the Options Menu or elsewhere in the Activity UI.</dd>
94</dl>
95
96
97
98<h2 id="SearchableConfiguration">Creating a Searchable Configuration</h2>
99
100<p>The searchable configuration is an XML file that defines several settings for the search
101dialog in your application. This file is traditionally named {@code searchable.xml} and must be
102saved in the {@code res/xml/} project directory.</p>
103
104<p>The file must consist of the {@code &lt;searchable&gt;} element as the root node and specify one
105or more attributes that configure your search dialog. For example:</p>
106
107<pre>
108&lt;?xml version="1.0" encoding="utf-8"?>
109&lt;searchable xmlns:android="http://schemas.android.com/apk/res/android"
110    android:label="@string/app_label"
111    android:hint="@string/search_hint" >
112&lt;/searchable>
113</pre>
114
115<p>The {@code android:label} attribute is the only required attribute and points to a string
116resource, which should be the same as the application name. This label isn't actually visible to the
117user until you enable suggestions for Quick Search Box, at which point, this label is visible in the
118list of Searchable items in the system Settings.</p>
119
120<p>Though it's not required, we recommend that you always include the {@code android:hint}
121attribute, which provides a hint string in the search dialog's text box before the user
122enters their query. The hint is important because it provides important clues to users about what
123they can search.</p>
124
125<p class="note"><strong>Tip:</strong> For consistency among other
126Android applications, you should format the string for {@code android:hint} as "Search
127<em>&lt;content-or-product&gt;</em>". For example, "Search songs and artists" or "Search
128YouTube".</p>
129
130<p>The {@code &lt;searchable&gt;} element accepts several other attributes. Most attributes apply
131only when configuring features such as search suggestions and voice search.</p>
132
133<p>For more details about the searchable configuration file, see the <a
134href="{@docRoot}guide/topics/search/searchable-config.html">Searchable Configuration</a>
135reference.</p>
136
137
138
139<h2 id="SearchableActivity">Creating a Searchable Activity</h2>
140
141<p>When the user executes a search from the search dialog, the Search Manager takes the query
142and sends it to your searchable {@link android.app.Activity} in the {@link
143android.content.Intent#ACTION_SEARCH} {@link android.content.Intent}. Your searchable Activity
144then searches your data using the query and presents the results to the user.</p>
145
146<p>In order for the Search Manager to know where to deliver the search query, you must declare your
147searchable Activity in the Android manifest file.</p>
148
149
150<h3 id="DeclaringSearchableActivity">Declaring a searchable Activity</h3>
151
152<p>If you don't have one already, create an {@link android.app.Activity} that performs
153searches and present search results. To set up this Activity as your searchable Activity:</p>
154<ol>
155  <li>Declare the Activity to accept the {@link android.content.Intent#ACTION_SEARCH} {@link
156android.content.Intent}, in an <a
157href="{@docRoot}guide/topics/manifest/intent-filter-element.html">{@code &lt;intent-filter&gt;}</a>
158element.</li>
159  <li>Apply the searchable configuration, in a <a
160href="{@docRoot}guide/topics/manifest/meta-data-element.html">{@code &lt;meta-data&gt;}</a>
161element.</li>
162</ol>
163
164<p>For example:</p>
165
166<pre>
167&lt;application ... >
168    &lt;activity android:name=".MySearchableActivity" >
169        &lt;intent-filter>
170            &lt;action android:name="android.intent.action.SEARCH" />
171        &lt;/intent-filter>
172        &lt;meta-data android:name="android.app.searchable"
173                   android:resource="@xml/searchable"/>
174    &lt;/activity>
175    ...
176&lt;/application>
177</pre>
178
179<p>The {@code &lt;meta-data&gt;} element must include the {@code android:name} attribute with a
180value of {@code "android.app.searchable"} and the {@code android:resource} attribute with a
181reference to the searchable configuration file (in this example, it
182refers to the {@code res/xml/searchable.xml} file).</p>
183
184<p class="note"><strong>Note:</strong> The {@code &lt;intent-filter&gt;} does not need a <a
185href="{@docRoot}guide/topics/manifest/category-element.html">{@code &lt;category&gt;}</a> with the
186{@code DEFAULT} value, because the Search Manager delivers the {@link
187android.content.Intent#ACTION_SEARCH} Intent explicitly to your searchable Activity by name.</p>
188
189<p>The search dialog is not, by default, available from every Activity of your
190application. Rather, the search dialog is presented to users only when they
191invoke search from a searchable context of your application. A searchable context is any Activity
192for which you have
193declared searchable meta-data in the manifest file. For example, the searchable Activity itself
194(declared in the manifest snippet above) is
195a searchable context because it includes meta-data that defines the
196searchable configuration. Any other Activity in your application is not a searchable context, by
197default, and thus, does not reveal the search dialog. However, you probably do want the search
198dialog available from your other activities (and to launch the searchable Activity when the user
199executes a search). You can do exactly that.</p>
200
201<p>If you want all of your activities to provide the search dialog, add another {@code
202&lt;meta-data&gt;} element inside the {@code
203&lt;application&gt;} element. Use this element to declare the existing searchable Activity as the
204default searchable Activity. For example:</p>
205
206<pre>
207&lt;application ... >
208    &lt;activity android:name=".MySearchableActivity" >
209        &lt;intent-filter>
210            &lt;action android:name="android.intent.action.SEARCH" />
211        &lt;/intent-filter>
212        &lt;meta-data android:name="android.app.searchable"
213                   android:resource="@xml/searchable"/>
214    &lt;/activity>
215    &lt;activity android:name=".AnotherActivity" ... >
216    &lt;/activity>
217    &lt;!-- declare the default searchable Activity for the whole app --&gt;
218    <b>&lt;meta-data android:name="android.app.default_searchable"
219               android:value=".MySearchableActivity" /&gt;</b>
220    ...
221&lt;/application>
222</pre>
223
224<p>The {@code &lt;meta-data&gt;} element with the {@code android:name} attribute value of
225{@code "android.app.default_searchable"} specifies a default searchable Activity for the context in
226which it is placed (which, in this case, is the entire application). The searchable Activity to
227use is specified with the {@code android:value} attribute. All other activities in the
228application, such as {@code AnotherActivity}, are now considered a searchable context and can invoke
229the search dialog. When a search is executed, {@code MySearchableActivity} is launched to handle
230the search query.</p>
231
232<p>You can also control which activities provide search at a more granular level.
233To specify only an individual Activity as a searchable context, place the {@code
234&lt;meta-data&gt;} with the {@code
235"android.app.default_searchable"} name inside the respective {@code &lt;activity&gt;}
236element (rather than inside the {@code &lt;application&gt;} element). While uncommon, you
237can also create more than one searchable Activity and provide each one in different contexts of your
238application, either by declaring a different searchable Activity in each {@code &lt;activity&gt;}
239element, or by declaring a default searchable Activity for the entire application and then
240overriding it with a {@code &lt;meta-data&gt;} element inside certain activities. (You might do
241this if you want to search different sets of data that cannot be handled by the same
242searchable Activity, depending on the currently open Activity.)</p>
243
244
245<h3 id="PerformingSearch">Performing a search</h3>
246
247<p>Once you have declared your searchable Activity, performing a search for the user involves
248three steps:</p>
249<ol>
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>
253</ol>
254
255<p>Traditionally, your search results should be presented in a {@link android.widget.ListView}, so
256you might want your searchable Activity to extend {@link android.app.ListActivity}, which
257provides easy access to {@link android.widget.ListView} APIs. (See the <a
258href="{@docRoot}resources/tutorials/views/hello-listview.html">List View Tutorial</a> for a simple
259{@link android.app.ListActivity} sample.)</p>
260
261
262<h4 id="ReceivingTheQuery">Receiving the query</h4>
263
264<p>When a user executes a search from the search dialog, the Search Manager sends the {@link
265android.content.Intent#ACTION_SEARCH} {@link android.content.Intent} to your searchable Activity.
266This Intent carries the search query in the
267{@link android.app.SearchManager#QUERY QUERY} string extra. You must check for
268this Intent when the Activity starts and extract the string. For example, here's how you can get the
269query when your Activity starts:</p>
270
271<pre>
272&#64;Override
273public void onCreate(Bundle savedInstanceState) {
274    super.onCreate(savedInstanceState);
275    setContentView(R.layout.search);
276
277    Intent intent = getIntent();
278
279    if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
280      String query = intent.getStringExtra(SearchManager.QUERY);
281      doMySearch(query);
282    }
283}
284</pre>
285
286<p>The {@link android.app.SearchManager#QUERY QUERY} string is always included with
287the {@link android.content.Intent#ACTION_SEARCH} Intent. In this example, the query is
288retrieved and passed to a local {@code doMySearch()} method where the actual search operation
289is done.</p>
290
291
292<h4 id="SearchingYourData">Searching your data</h4>
293
294<p>The process of storing and searching your data is unique to your application.
295You can store and search your data in many ways, but this guide does not show you how to store your
296data and search it. Storing and searching your data is something you should carefully consider in
297terms of your needs and your data. However, here are some tips you might be able to apply:</p>
298
299  <ul>
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
302produce results significantly faster. See <a href="http://sqlite.org/fts3.html">sqlite.org</a>
303for information about FTS3 and the {@link android.database.sqlite.SQLiteDatabase} class for
304information about SQLite on Android. Also look at the <a
305href="{@docRoot}resources/samples/SearchableDictionary/index.html">Searchable Dictionary</a> sample
306application 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
308inhibited by the user's data connection. You might want to display a spinning progress wheel until
309your search returns. See {@link android.net} for a reference of network APIs and <a
310href="{@docRoot}guide/topics/ui/dialogs.html#ProgressDialog">Creating a Progress Dialog</a> to see
311how you can display a progress wheel.</li>
312  </ul>
313
314
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
319android.view.View} objects. When the Adapter
320is applied to a {@link android.widget.ListView}, the Views are injected as individual items of the
321list. {@link
322android.widget.Adapter} is simply an interface, so implementations such as {@link
323android.widget.CursorAdapter} (for binding data from a {@link android.database.Cursor}) are needed.
324If 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
326original version of the Searchable Dictionary, which creates a custom BaseAdapter.</p>
327</div>
328</div>
329
330<p>Regardless of where your data lives and how you search it, we recommend that you return search
331results to your searchable Activity with an {@link android.widget.Adapter}. This way, you can easily
332present all the search results in a {@link android.widget.ListView}. If your data comes from a
333SQLite database query, then you can apply your results to a {@link android.widget.ListView}
334using a {@link android.widget.CursorAdapter}. If your data comes in some other type of format, then
335you can create an extension of the {@link android.widget.BaseAdapter}.</p>
336
337<h4 id="PresentingTheResults">Presenting the results</h4>
338
339<p>Presenting your search results is mostly a UI detail that is not handled by the search APIs.
340However, one option is to create your searchable Activity to extend {@link
341android.app.ListActivity} and call {@link
342android.app.ListActivity#setListAdapter(ListAdapter)}, passing it an {@link
343android.widget.Adapter} that is bound to your data. This injects all the
344results into the Activity {@link android.widget.ListView}.</p>
345
346<p>For more help presenting your results, see the {@link android.app.ListActivity}
347documentation.</p>
348
349<p>Also see the <a
350href="{@docRoot}resources/samples/SearchableDictionary/index.html">Searchable Dictionary</a> sample
351for 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>
353
354
355
356<h2 id="InvokingTheSearchDialog">Invoking the Search Dialog</h2>
357
358<p>Once you have a searchable Activity, invoking the search dialog is easy. Many Android
359devices provide a dedicated SEARCH key, which reveals the search dialog when the user presses it
360from a searchable context of your application. However, you should not assume that a SEARCH
361key is available on the user's device and should always provide a search button in your UI that
362invokes search.</p>
363
364<p>To invoke search from your Activity, call {@link android.app.Activity#onSearchRequested()}.</p>
365
366<p>For instance, you should provide a menu item in your <a
367href="{@docRoot}guide/topics/ui/menus.html#options-menu">Options Menu</a> or a button in your UI to
368invoke search with this method. The <a
369href="{@docRoot}shareables/search_icons.zip">search_icons.zip</a> file includes icons for
370medium and high density screens, which you can use for your search menu item or button (low density
371screens automatically scale-down the hdpi image by one half). </p>
372
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
375android.view.MenuItem#setAlphabeticShortcut(char)}, then SearchManager.MENU_KEY is the recommended
376key character, representing the default search key.</p>
377-->
378
379<p>You can also enable "type-to-search" functionality, which reveals the search dialog when the
380user starts typing on the keyboard and the keystrokes are inserted into the search dialog. You can
381enable type-to-search in your Activity by calling
382{@link android.app.Activity#setDefaultKeyMode(int) setDefaultKeyMode}({@link
383android.app.Activity#DEFAULT_KEYS_SEARCH_LOCAL}) during your Activity's
384{@link android.app.Activity#onCreate(Bundle) onCreate()} method.</p>
385
386
387<h3 id="LifeCycle">The impact of the search dialog on your Activity lifecycle</h3>
388
389<p>The search dialog is a {@link android.app.Dialog} that floats at the top of the
390screen. It does not cause any change in the Activity stack, so when the search dialog appears, no
391lifecycle methods for the currently open Activity (such as {@link
392android.app.Activity#onPause()}) are called. Your Activity just loses input focus as it is given to
393the search dialog.
394</p>
395
396<p>If you want to be notified when search is invoked, override the {@link
397android.app.Activity#onSearchRequested()} method. When the system calls this method, you can do any
398work you want to when your Activity looses input focus to the search dialog (such as pause
399animations). 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
401example:</p>
402
403<pre>
404&#64;Override
405public boolean onSearchRequested() {
406    pauseSomeStuff();
407    return super.onSearchRequested();
408}
409</pre>
410
411<p>If the user cancels search by pressing the BACK key, the Activity in which search was
412invoked re-gains input focus. You can register to be notified when the search dialog is
413closed with {@link android.app.SearchManager#setOnDismissListener(SearchManager.OnDismissListener)
414setOnDismissListener()}
415and/or {@link android.app.SearchManager#setOnCancelListener(SearchManager.OnCancelListener)
416setOnCancelListener()}. You
417should need to register only the {@link android.app.SearchManager.OnDismissListener
418OnDismissListener}, because it is called every time the search dialog closes. The {@link
419android.app.SearchManager.OnCancelListener OnCancelListener} only pertains to events in which the
420user explicitly exited the search dialog, so it is not called when a search is executed (in which
421case, the search dialog naturally disappears).</p>
422
423<p>If the current Activity is not the searchable Activity, then the normal Activity lifecycle
424events are triggered once the user executes a search (the current Activity receives {@link
425android.app.Activity#onPause()} and so forth, as
426described in <a href="{@docRoot}guide/topics/fundamentals.html#lcycles">Application
427Fundamentals</a>). If, however, the current Activity is the searchable Activity, then one of two
428things happens:</p>
429
430<ol type="a">
431  <li>By default, the searchable Activity receives the {@link
432android.content.Intent#ACTION_SEARCH} Intent with a call to {@link
433android.app.Activity#onCreate(Bundle) onCreate()} and a new instance of the
434Activity is brought to the top of the Activity stack. There are now two instances of your
435searchable Activity in the Activity stack (so pressing the BACK key goes back to the previous
436instance of the searchable Activity, rather than exiting the searchable Activity).</li>
437  <li>If you set {@code android:launchMode} to "singleTop", then the
438searchable Activity receives the {@link android.content.Intent#ACTION_SEARCH} Intent with a call
439to {@link android.app.Activity#onNewIntent(Intent)}, passing the new {@link
440android.content.Intent#ACTION_SEARCH} Intent here. For example, here's how you might handle
441this case, in which the searchable Activity's launch mode is "singleTop":
442<pre>
443&#64;Override
444public void onCreate(Bundle savedInstanceState) {
445    super.onCreate(savedInstanceState);
446    setContentView(R.layout.search);
447    handleIntent(getIntent());
448}
449
450&#64;Override
451protected void onNewIntent(Intent intent) {
452    setIntent(intent);
453    handleIntent(intent);
454}
455
456private void handleIntent(Intent intent) {
457    if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
458      String query = intent.getStringExtra(SearchManager.QUERY);
459      doMySearch(query);
460    }
461}
462</pre>
463
464<p>Compared to the example code in the section about <a href="#PerfomingSearch">Performing a
465Search</a>, all the code to handle the
466search Intent is now in the {@code handleIntent()} method, so that both {@link
467android.app.Activity#onCreate(Bundle)
468onCreate()} and {@link android.app.Activity#onNewIntent(Intent) onNewIntent()} can execute it.</p>
469
470<p>When the system calls {@link android.app.Activity#onNewIntent(Intent)}, the Activity has
471not been restarted, so the {@link android.app.Activity#getIntent()} method
472returns the same Intent that was received with {@link
473android.app.Activity#onCreate(Bundle) onCreate()}. This is why you should call {@link
474android.app.Activity#setIntent(Intent)} inside {@link
475android.app.Activity#onNewIntent(Intent)} (so that the Intent saved by the Activity is updated in
476case you call {@link android.app.Activity#getIntent()} in the future).</p>
477
478</li>
479</ol>
480
481<p>The second scenario using "singleTop" launch mode is usually ideal, because chances are good that
482once a search is done, the user will perform additional searches and it's a bad experience if your
483application creates multiple instances of the searchable Activity. So, we recommend that you set
484your searchable Activity to "singleTop" launch mode in the application
485manifest. For example:</p>
486
487<pre>
488&lt;activity android:name=".MySearchableActivity"
489          <b>android:launchMode="singleTop"</b> >
490    &lt;intent-filter>
491        &lt;action android:name="android.intent.action.SEARCH" />
492    &lt;/intent-filter>
493    &lt;meta-data android:name="android.app.searchable"
494                      android:resource="@xml/searchable"/>
495  &lt;/activity>
496</pre>
497
498
499
500<h2 id="SearchContextData">Passing Search Context Data</h2>
501
502<p>To refine your search criteria from the current Activity instead of depending only on the user's
503search query, you can provide additional data in the Intent that the Search Manager sends to your
504searchable Activity. In a simple case, you can make your refinements inside the searchable
505Activity, for every search made, but if your
506search criteria varies from one searchable context to another, then you can pass whatever data
507is necessary to refine your search in the {@link android.app.SearchManager#APP_DATA} {@link
508android.os.Bundle}, which is included in the {@link android.content.Intent#ACTION_SEARCH}
509Intent.</p>
510
511<p>To pass this kind of data to your searchable Activity, override  {@link
512android.app.Activity#onSearchRequested()} method for the Activity in which search can be invoked.
513For example:</p>
514
515<pre>
516&#64;Override
517public boolean onSearchRequested() {
518     Bundle appData = new Bundle();
519     appData.putBoolean(MySearchableActivity.JARGON, true);
520     startSearch(null, false, appData, false);
521     return true;
522 }
523</pre>
524
525<p>Returning "true" indicates that you have successfully handled this callback event. Then in your
526searchable Activity, you can extract the data placed inside {@code appdata} from the {@link
527android.app.SearchManager#APP_DATA} {@link android.os.Bundle} to refine the search. For example:</p>
528
529<pre>
530Bundle appData = getIntent().getBundleExtra(SearchManager.APP_DATA);
531if (appData != null) {
532    boolean jargon = appData.getBoolean(MySearchableActivity.JARGON);
533}
534</pre>
535
536<p class="caution"><strong>Caution:</strong> Never call the {@link
537android.app.Activity#startSearch(String,boolean,Bundle,boolean) startSearch()} method from outside
538the {@link android.app.Activity#onSearchRequested()} callback method. To invoke the search dialog
539in your Activity, always call {@link android.app.Activity#onSearchRequested()}. Otherwise, {@link
540android.app.Activity#onSearchRequested()} is not called and customizations (such as the addition of
541{@code appData} in the above example) are missed.</p>
542
543
544<h2 id="VoiceSearch">Adding Voice Search</h2>
545
546<p>You can add voice search functionality to your search dialog by adding the {@code
547android:voiceSearchMode} attribute to your searchable configuration. This adds a voice search
548button in the search dialog that launches a voice prompt. When the user
549has finished speaking, the transcribed search query is sent to your searchable
550Activity.</p>
551
552<p>For example:</p>
553
554<pre>
555&lt;?xml version="1.0" encoding="utf-8"?>
556&lt;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> >
560&lt;/searchable>
561</pre>
562
563<p>The value {@code showVoiceSearchButton} is required to enable voice
564search, while the second value, {@code launchRecognizer}, specifies that the voice search button
565should launch a recognizer that returns the transcribed text to the searchable Activity.</p>
566
567<p>You can provide additional attributes to specify the voice search behavior, such
568as the language to be expected and the maximum number of results to return. See the <a
569href="searchable-config.html">Searchable Configuration</a> reference for more information about the
570available attributes.</p>
571
572<p class="note"><strong>Note:</strong> Carefully consider whether voice search is appropriate for
573your application. All searches performed with the voice search button are immediately sent to
574your searchable Activity without a chance for the user to review the transcribed query. Sufficiently
575test the voice recognition and ensure that it understands the types of queries that
576the user might submit inside your application.</p>
577