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 <searchable>} element as the root node and specify one 105or more attributes that configure your search dialog. For example:</p> 106 107<pre> 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" > 112</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><content-or-product></em>". For example, "Search songs and artists" or "Search 128YouTube".</p> 129 130<p>The {@code <searchable>} 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 <intent-filter>}</a> 158element.</li> 159 <li>Apply the searchable configuration, in a <a 160href="{@docRoot}guide/topics/manifest/meta-data-element.html">{@code <meta-data>}</a> 161element.</li> 162</ol> 163 164<p>For example:</p> 165 166<pre> 167<application ... > 168 <activity android:name=".MySearchableActivity" > 169 <intent-filter> 170 <action android:name="android.intent.action.SEARCH" /> 171 </intent-filter> 172 <meta-data android:name="android.app.searchable" 173 android:resource="@xml/searchable"/> 174 </activity> 175 ... 176</application> 177</pre> 178 179<p>The {@code <meta-data>} 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 <intent-filter>} does not need a <a 185href="{@docRoot}guide/topics/manifest/category-element.html">{@code <category>}</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<meta-data>} element inside the {@code 203<application>} element. Use this element to declare the existing searchable Activity as the 204default searchable Activity. For example:</p> 205 206<pre> 207<application ... > 208 <activity android:name=".MySearchableActivity" > 209 <intent-filter> 210 <action android:name="android.intent.action.SEARCH" /> 211 </intent-filter> 212 <meta-data android:name="android.app.searchable" 213 android:resource="@xml/searchable"/> 214 </activity> 215 <activity android:name=".AnotherActivity" ... > 216 </activity> 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> 220 ... 221</application> 222</pre> 223 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 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<meta-data>} with the {@code 235"android.app.default_searchable"} name inside the respective {@code <activity>} 236element (rather than inside the {@code <application>} 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 <activity>} 239element, or by declaring a default searchable Activity for the entire application and then 240overriding it with a {@code <meta-data>} 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@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@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@Override 444public void onCreate(Bundle savedInstanceState) { 445 super.onCreate(savedInstanceState); 446 setContentView(R.layout.search); 447 handleIntent(getIntent()); 448} 449 450@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<activity android:name=".MySearchableActivity" 489 <b>android:launchMode="singleTop"</b> > 490 <intent-filter> 491 <action android:name="android.intent.action.SEARCH" /> 492 </intent-filter> 493 <meta-data android:name="android.app.searchable" 494 android:resource="@xml/searchable"/> 495 </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@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<?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> > 560</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