1page.title=Creating a Search Interface 2page.tags=searchview 3@jd:body 4 5<div id="qv-wrapper"> 6<div id="qv"> 7 8 9<h2>In this document</h2> 10<ol> 11 <li><a href="#TheBasics">The Basics</a></li> 12 <li><a href="#SearchableConfiguration">Creating a Searchable Configuration</a></li> 13 <li><a href="#SearchableActivity">Creating a Searchable Activity</a> 14 <ol> 15 <li><a href="#DeclaringSearchableActivity">Declaring a searchable activity</a></li> 16 <li><a href="#PerformingSearch">Performing a search</a></li> 17 </ol> 18 </li> 19 <li><a href="#SearchDialog">Using the Search Dialog</a> 20 <ol> 21 <li><a href="#InvokingTheSearchDialog">Invoking the search dialog</a></li> 22 <li><a href="#LifeCycle">The impact of the search dialog on your activity lifecycle</a></li> 23 <li><a href="#SearchContextData">Passing search context data</a></li> 24 </ol> 25 </li> 26 <li><a href="#UsingSearchWidget">Using the Search Widget</a> 27 <ol> 28 <li><a href="#ConfiguringWidget">Configuring the search widget</a></li> 29 <li><a href="#WidgetFeatures">Other search widget features</a></li> 30 <li><a href="#UsingBoth">Using both the widget and the dialog</a></li> 31 </ol> 32 </li> 33 <li><a href="#VoiceSearch">Adding Voice Search</a></li> 34 <li><a href="#SearchSuggestions">Adding Search Suggestions</a></li> 35</ol> 36 37<h2>Key classes</h2> 38<ol> 39<li>{@link android.app.SearchManager}</li> 40<li>{@link android.widget.SearchView}</li> 41</ol> 42 43<h2>Related samples</h2> 44<ol> 45<li><a href="{@docRoot}resources/samples/SearchableDictionary/index.html">Searchable 46Dictionary</a></li> 47<li><a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/view/SearchViewActionBar.html">SearchView 48 in the Action Bar</a></li> 49<li><a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/view/SearchViewFilterMode.html">SearchView 50 filter mode</a></li> 51</ol> 52 53<h2>Downloads</h2> 54<ol> 55<li><a href="{@docRoot}design/downloads/index.html#action-bar-icon-pack">Action Bar 56Icon Pack</a></li> 57</ol> 58 59</div> 60</div> 61 62<p>When you're ready to add search functionality to your application, Android helps you implement 63the user interface with either a search dialog that appears at the top of the activity window or a 64search widget that you can insert in your layout. Both the search dialog and the widget can deliver 65the user's search query to a specific activity in your application. This way, the user can initiate 66a search from any activity where the search dialog or widget is available, and the system starts the 67appropriate activity to perform the search and present results.</p> 68 69<p>Other features available for the search dialog and widget include:</p> 70 71<ul> 72 <li>Voice search</li> 73 <li>Search suggestions based on recent queries</li> 74 <li>Search suggestions that match actual results in your application data</li> 75</ul> 76 77<p>This guide shows you how to set up your application to provide a search interface 78that's assisted by the Android system to deliver search queries, using either the 79search dialog or the search widget.</p> 80 81 82<h2 id="TheBasics">The Basics</h2> 83 84<div class="figure" style="width:250px"> 85<img src="{@docRoot}images/search/search-ui.png" alt="" height="417" /> 86<p class="img-caption"><strong>Figure 1.</strong> Screenshot of an application's search dialog.</p> 87</div> 88 89<p>Before you begin, you should decide whether you'll implement your search interface using the 90search dialog or the search widget. Both provide the same search features, but in slightly different 91ways:</p> 92 93<ul> 94 <li>The <strong>search dialog</strong> is a UI component that's controlled by the Android system. 95When activated by the user, the search dialog appears at the top of the activity, as shown in figure 961. 97 <p>The Android system controls all events in the search dialog. When the user 98submits a query, the system delivers the query to the activity that you specify to 99handle searches. The dialog can also provide search suggestions while the user types.</p></li> 100 101 <li>The <strong>search widget</strong> is an instance of {@link android.widget.SearchView} that 102you can place anywhere in your layout. By default, the search widget behaves like a standard {@link 103android.widget.EditText} widget and doesn't do anything, but you can configure it so that the 104Android system handles all input events, delivers queries to the appropriate activity, and provides 105search suggestions (just like the search dialog). 106 107<p class="note"><strong>Note:</strong> If you want, you can handle all user input into the 108search widget yourself, using various callback methods and listeners. This document, however, 109focuses on how to integrate the search widget with the system for an assisted search 110implementation. If you want to handle all user input yourself, read the reference documentation for 111{@link android.widget.SearchView} and its nested interfaces. </p></li> 112</ul> 113 114<p>When the user executes a search from the search dialog or a search widget, the system creates an 115{@link android.content.Intent} and stores the user query in it. The system then starts the activity 116that you've declared to handle searches (the "searchable activity") and delivers it the intent. To 117set up your application for this kind of assisted search, you need the following:</p> 118 119<ul> 120 <li>A searchable configuration 121 <p>An XML file that configures some settings for the search dialog or widget. It includes settings 122for features such as voice search, search suggestion, and hint text for the search box.</p></li> 123 <li>A searchable activity 124 <p>The {@link android.app.Activity} that receives the search query, searches your 125data, and displays the search results.</p></li> 126 <li>A search interface, provided by either: 127 <ul> 128 <li>The search dialog 129 <p>By default, the search dialog is hidden, but appears at the top of the screen when 130 you call {@link android.app.Activity#onSearchRequested()} (when the user presses your 131 Search button).</p> 132 </li> 133 <li>Or, a {@link android.widget.SearchView} widget 134 <p>Using the search widget allows you to put the search box anywhere in your activity. 135Instead of putting it in your activity layout, you should usually use 136{@link android.widget.SearchView} as an action view in the app bar.</p> 137 </li> 138 </ul> 139 </li> 140</ul> 141 142<p>The rest of this document shows you how to create the searchable configuration, searchable 143activity, and implement a search interface with either the search dialog or search widget.</p> 144 145 146<h2 id="SearchableConfiguration">Creating a Searchable Configuration</h2> 147 148<p>The first thing you need is an XML file called the searchable configuration. It configures 149certain UI aspects of the search dialog or widget and defines how features such as suggestions and 150voice search behave. This file is traditionally named {@code searchable.xml} and must be saved in 151the {@code res/xml/} project directory.</p> 152 153<p class="note"><strong>Note:</strong> The system uses this file to instantiate a {@link 154android.app.SearchableInfo} object, but you cannot create this object yourself at 155runtime—you must declare the searchable configuration in XML.</p> 156 157<p>The searchable configuration file must include the <a 158href="{@docRoot}guide/topics/search/searchable-config.html#searchable-element">{@code 159<searchable>}</a> element as the root node and specify one 160or more attributes. For example:</p> 161 162<pre> 163<?xml version="1.0" encoding="utf-8"?> 164<searchable xmlns:android="http://schemas.android.com/apk/res/android" 165 android:label="@string/app_label" 166 android:hint="@string/search_hint" > 167</searchable> 168</pre> 169 170<p>The {@code android:label} attribute is the only required attribute. It points to a string 171resource, which should be the application name. This label isn't actually visible to the 172user until you enable search suggestions for Quick Search Box. At that point, this label is visible 173in the list of Searchable items in the system Settings.</p> 174 175<p>Though it's not required, we recommend that you always include the {@code android:hint} 176attribute, which provides a hint string in the search box before users 177enters a query. The hint is important because it provides important clues to users about what 178they can search.</p> 179 180<p class="note"><strong>Tip:</strong> For consistency among other 181Android applications, you should format the string for {@code android:hint} as "Search 182<content-or-product>". For example, "Search songs and artists" or "Search 183YouTube".</p> 184 185<p>The <a 186href="{@docRoot}guide/topics/search/searchable-config.html#searchable-element">{@code 187<searchable>}</a> element accepts several other attributes. However, you don't need 188most attributes until you add features such as <a href="#SearchSuggestions">search suggestions</a> 189and <a href="#VoiceSearch">voice search</a>. For detailed information about the searchable 190configuration file, see the <a 191href="{@docRoot}guide/topics/search/searchable-config.html">Searchable Configuration</a> reference 192document.</p> 193 194 195 196<h2 id="SearchableActivity">Creating a Searchable Activity</h2> 197 198<p>A searchable activity is the {@link android.app.Activity} in your application that performs 199searches based on a query string and presents the search results.</p> 200 201<p>When the user executes a search in the search dialog or widget, the system starts your 202searchable activity and delivers it the search query in an {@link 203android.content.Intent} with the {@link android.content.Intent#ACTION_SEARCH} action. Your 204searchable activity retrieves the query from the intent's {@link android.app.SearchManager#QUERY 205QUERY} extra, then searches your data and presents the results.</p> 206 207<p>Because you may include the search dialog or widget in any other activity in your application, 208the system must know which activity is your searchable activity, so it can properly deliver the 209search query. So, you must first declare your searchable activity in the Android manifest file.</p> 210 211 212<h3 id="DeclaringSearchableActivity">Declaring a searchable activity</h3> 213 214<p>If you don't have one already, create an {@link android.app.Activity} that will perform 215searches and present results. You don't need to implement the search functionality yet—just 216create an activity that you can declare in the manifest. Inside the manifest's <a 217href="{@docRoot}guide/topics/manifest/activity-element.html">{@code <activity>}</a> 218element:</p> 219<ol> 220 <li>Declare the activity to accept the {@link android.content.Intent#ACTION_SEARCH} intent, in an 221<a href="{@docRoot}guide/topics/manifest/intent-filter-element.html">{@code 222<intent-filter>}</a> 223element.</li> 224 <li>Specify the searchable configuration to use, in a <a 225href="{@docRoot}guide/topics/manifest/meta-data-element.html">{@code <meta-data>}</a> 226element.</li> 227</ol> 228 229<p>For example:</p> 230 231<pre> 232<application ... > 233 <activity android:name=".SearchableActivity" > 234 <intent-filter> 235 <action android:name="android.intent.action.SEARCH" /> 236 </intent-filter> 237 <meta-data android:name="android.app.searchable" 238 android:resource="@xml/searchable"/> 239 </activity> 240 ... 241</application> 242</pre> 243 244<p>The {@code <meta-data>} element must include the {@code android:name} attribute with a 245value of {@code "android.app.searchable"} and the {@code android:resource} attribute with a 246reference to the searchable configuration file (in this example, it 247refers to the {@code res/xml/searchable.xml} file).</p> 248 249<p class="note"><strong>Note:</strong> The <a 250href="{@docRoot}guide/topics/manifest/intent-filter-element.html">{@code 251<intent-filter>}</a> does not need a <a 252href="{@docRoot}guide/topics/manifest/category-element.html">{@code <category>}</a> with the 253{@code DEFAULT} value (which you usually see in <a 254href="{@docRoot}guide/topics/manifest/activity-element.html">{@code <activity>}</a> elements), 255because the system delivers the {@link android.content.Intent#ACTION_SEARCH} intent explicitly to 256your searchable activity, using its component name.</p> 257 258 259 260<h3 id="PerformingSearch">Performing a search</h3> 261 262<p>Once you have declared your searchable activity in the manifest, performing a search in your 263searchable activity involves three steps:</p> 264 265<ol> 266 <li><a href="#ReceivingTheQuery">Receiving the query</a></li> 267 <li><a href="#SearchingYourData">Searching your data</a></li> 268 <li><a href="#PresentingTheResults">Presenting the results</a></li> 269</ol> 270 271<p>Traditionally, your search results should be presented in a {@link android.widget.ListView}, so 272you might want your searchable activity to extend {@link android.app.ListActivity}. It includes 273a default layout with a single {@link android.widget.ListView} and provides several 274convenience methods for working with the {@link android.widget.ListView}.</p> 275 276 277<h4 id="ReceivingTheQuery">Receiving the query</h4> 278 279<p>When a user executes a search from the search dialog or widget, the system starts your 280searchable activity and sends it a {@link android.content.Intent#ACTION_SEARCH} intent. This intent 281carries the search query in the 282{@link android.app.SearchManager#QUERY QUERY} string extra. You must check for 283this intent when the activity starts and extract the string. For example, here's how you can get the 284search query when your searchable activity starts:</p> 285 286<pre> 287@Override 288public void onCreate(Bundle savedInstanceState) { 289 super.onCreate(savedInstanceState); 290 setContentView(R.layout.search); 291 292 // Get the intent, verify the action and get the query 293 Intent intent = getIntent(); 294 if (Intent.ACTION_SEARCH.equals(intent.getAction())) { 295 String query = intent.getStringExtra(SearchManager.QUERY); 296 doMySearch(query); 297 } 298} 299</pre> 300 301<p>The {@link android.app.SearchManager#QUERY QUERY} string is always included with 302the {@link android.content.Intent#ACTION_SEARCH} intent. In this example, the query is 303retrieved and passed to a local {@code doMySearch()} method where the actual search operation 304is done.</p> 305 306 307<h4 id="SearchingYourData">Searching your data</h4> 308 309<p>The process of storing and searching your data is unique to your application. 310You can store and search your data in many ways, but this guide does not show you how to store your 311data and search it. Storing and searching your data is something you should carefully consider in 312terms of your needs and your data format. However, here are some tips you might be able to 313apply:</p> 314 315 <ul> 316 <li>If your data is stored in a SQLite database on the device, performing a full-text search 317(using FTS3, rather than a {@code LIKE} query) can provide a more robust search across text data and 318can produce results significantly faster. See <a href="http://sqlite.org/fts3.html">sqlite.org</a> 319for information about FTS3 and the {@link android.database.sqlite.SQLiteDatabase} class for 320information about SQLite on Android. Also look at the <a 321href="{@docRoot}resources/samples/SearchableDictionary/index.html">Searchable Dictionary</a> sample 322application to see a complete SQLite implementation that performs searches with FTS3.</li> 323 <li>If your data is stored online, then the perceived search performance might be 324inhibited by the user's data connection. You might want to display a spinning progress wheel until 325your search returns. See {@link android.net} for a reference of network APIs and <a 326href="{@docRoot}guide/topics/ui/dialogs.html#ProgressDialog">Creating a Progress Dialog</a> 327for information about how to display a progress wheel.</li> 328 </ul> 329 330 331<div class="sidebox-wrapper"> 332<div class="sidebox"> 333<h2>About Adapters</h2> 334<p>An {@link android.widget.Adapter} binds each item from a set of data into a 335{@link android.view.View} object. When the {@link android.widget.Adapter} 336is applied to a {@link android.widget.ListView}, each piece of data is inserted as an individual 337view into the list. {@link 338android.widget.Adapter} is just an interface, so implementations such as {@link 339android.widget.CursorAdapter} (for binding data from a {@link android.database.Cursor}) are needed. 340If none of the existing implementations work for your data, then you can implement your own from 341{@link android.widget.BaseAdapter}. Install the SDK Samples package for API Level 4 to see the 342original version of the Searchable Dictionary, which creates a custom adapter to read data from 343a file.</p> 344</div> 345</div> 346 347<p>Regardless of where your data lives and how you search it, we recommend that you return search 348results to your searchable activity with an {@link android.widget.Adapter}. This way, you can easily 349present all the search results in a {@link android.widget.ListView}. If your data comes from a 350SQLite database query, you can apply your results to a {@link android.widget.ListView} 351using a {@link android.widget.CursorAdapter}. If your data comes in some other type of format, then 352you can create an extension of {@link android.widget.BaseAdapter}.</p> 353 354 355<h4 id="PresentingTheResults">Presenting the results</h4> 356 357<p>As discussed above, the recommended UI for your search results is a {@link 358android.widget.ListView}, so you might want your searchable activity to extend {@link 359android.app.ListActivity}. You can then call {@link 360android.app.ListActivity#setListAdapter(ListAdapter) setListAdapter()}, passing it an {@link 361android.widget.Adapter} that is bound to your data. This injects all the 362search results into the activity {@link android.widget.ListView}.</p> 363 364<p>For more help presenting your results in a list, see the {@link android.app.ListActivity} 365documentation.</p> 366 367<p>Also see the <a 368href="{@docRoot}resources/samples/SearchableDictionary/index.html">Searchable Dictionary</a> sample 369for an a complete demonstration of how to search an SQLite database and use an 370{@link android.widget.Adapter} to provide results in a {@link android.widget.ListView}.</p> 371 372 373 374 375 376<h2 id="SearchDialog">Using the Search Dialog</h2> 377 378 379<p>The search dialog provides a floating search box at the top of the screen, with the application 380icon on the left. The search dialog can provide search suggestions as the user types and, when 381the user executes a search, the system sends the search query to a 382searchable activity that performs the search. However, if you are developing 383your application for devices running Android 3.0, you should consider using the search widget 384instead (see <a href="#UsingSearchWidget">Using the Search Widget</a> section).</p> 385 386<p>The search dialog is always hidden by default, until the user activates it. Your application 387can activate the search dialog by calling {@link 388android.app.Activity#onSearchRequested onSearchRequested()}. However, this method doesn't work 389until you enable the search dialog for the activity.</p> 390 391<p>To enable the search dialog, you must indicate to the system which searchable activity should 392receive search queries from the search dialog, in order to perform searches. For example, in the 393previous section about <a href="#SearchableActivity">Creating a Searchable Activity</a>, a 394searchable activity named {@code SearchableActivity} was created. If you want a separate activity, 395named {@code OtherActivity}, to show the search dialog and deliver searches to {@code 396SearchableActivity}, you must declare in the manifest that {@code SearchableActivity} is the 397searchable activity to use for the search dialog in {@code OtherActivity}.</p> 398 399<p>To declare the searchable activity for an activity's search dialog, 400add a <a href="{@docRoot}guide/topics/manifest/meta-data-element.html">{@code <meta-data>}</a> 401element inside the respective activity's <a 402href="{@docRoot}guide/topics/manifest/activity-element.html">{@code <activity>}</a> element. 403The <a href="{@docRoot}guide/topics/manifest/meta-data-element.html">{@code <meta-data>}</a> 404element must include the {@code android:value} attribute that specifies the searchable activity's 405class name and the {@code android:name} attribute with a value of {@code 406"android.app.default_searchable"}.</p> 407 408<p>For example, here is the declaration for 409both a searchable activity, {@code SearchableActivity}, and another activity, {@code 410OtherActivity}, which uses {@code SearchableActivity} to perform searches executed from its 411search dialog:</p> 412 413<pre> 414<application ... > 415 <!-- this is the searchable activity; it performs searches --> 416 <activity android:name=".SearchableActivity" > 417 <intent-filter> 418 <action android:name="android.intent.action.SEARCH" /> 419 </intent-filter> 420 <meta-data android:name="android.app.searchable" 421 android:resource="@xml/searchable"/> 422 </activity> 423 424 <!-- this activity enables the search dialog to initiate searches 425 in the SearchableActivity --> 426 <activity android:name=".OtherActivity" ... > 427 <!-- enable the search dialog to send searches to SearchableActivity --> 428 <b><meta-data android:name="android.app.default_searchable" 429 android:value=".SearchableActivity" /></b> 430 </activity> 431 ... 432</application> 433</pre> 434 435<p>Because the {@code OtherActivity} now includes a <a 436href="{@docRoot}guide/topics/manifest/meta-data-element.html">{@code <meta-data>}</a> 437element to declare which searchable activity to use for searches, the activity has enabled the 438search dialog. 439While the user is in this activity, the {@link 440android.app.Activity#onSearchRequested onSearchRequested()} method activates the search dialog. 441When the user executes the search, the system starts {@code SearchableActivity} and delivers it 442the {@link android.content.Intent#ACTION_SEARCH} intent.</p> 443 444<p class="note"><strong>Note:</strong> The searchable activity itself provides the search dialog 445by default, so you don't need to add this declaration to {@code SearchableActivity}.</p> 446 447<p>If you want every activity in your application to provide the search dialog, insert the above <a 448href="{@docRoot}guide/topics/manifest/meta-data-element.html">{@code <meta-data>}</a> 449element as a child of the <a 450href="{@docRoot}guide/topics/manifest/application-element.html">{@code <application>}</a> 451element, instead of each <a 452href="{@docRoot}guide/topics/manifest/activity-element.html">{@code <activity>}</a>. This 453way, every activity inherits the value, provides the search dialog, and delivers searches to 454the same searchable activity. (If you have multiple searchable activities, you can override the 455default searchable activity by placing a different <a 456href="{@docRoot}guide/topics/manifest/meta-data-element.html">{@code <meta-data>}</a> 457declaration inside individual activities.)</p> 458 459<p>With the search dialog now enabled for your activities, your application is ready to perform 460searches.</p> 461 462 463<h3 id="InvokingTheSearchDialog">Invoking the search dialog</h3> 464 465<p>Although some devices provide a dedicated Search button, the behavior of the button may vary 466between devices and many devices do not provide a Search button at all. So when using the search 467dialog, you <strong>must provide a search button in your UI</strong> that activates the search 468dialog by calling {@link android.app.Activity#onSearchRequested()}.</p> 469 470<p>For instance, you should add a Search button in your <a 471href="{@docRoot}guide/topics/ui/menus.html#options-menu">Options Menu</a> or UI 472layout that calls {@link android.app.Activity#onSearchRequested()}. For consistency with 473the Android system and other apps, you should label your button with the Android Search icon that's 474available from the <a href="{@docRoot}design/downloads/index.html#action-bar-icon-pack">Action Bar 475Icon Pack</a>.</p> 476 477<p class="note"><strong>Note:</strong> If your app uses an <a 478href="{@docRoot}training/appbar/index.html">app bar</a>, then you should not use 479the search dialog for your search interface. Instead, use the <a href="#UsingSearchWidget">search 480widget</a> as a collapsible view in the app bar.</p> 481 482<p>You can also enable "type-to-search" functionality, which activates the search dialog when the 483user starts typing on the keyboard—the keystrokes are inserted into the search dialog. You can 484enable type-to-search in your activity by calling 485{@link android.app.Activity#setDefaultKeyMode(int) setDefaultKeyMode}({@link 486android.app.Activity#DEFAULT_KEYS_SEARCH_LOCAL}) during your activity's 487{@link android.app.Activity#onCreate(Bundle) onCreate()} method.</p> 488 489 490<h3 id="LifeCycle">The impact of the search dialog on your activity lifecycle</h3> 491 492<p>The search dialog is a {@link android.app.Dialog} that floats at the top of the 493screen. It does not cause any change in the activity stack, so when the search dialog appears, no 494lifecycle methods (such as {@link android.app.Activity#onPause()}) are called. Your activity just 495loses input focus, as input focus is given to the search dialog. 496</p> 497 498<p>If you want to be notified when the search dialog is activated, override the {@link 499android.app.Activity#onSearchRequested()} method. When the system calls this method, it is an 500indication that your activity has lost input focus to the search dialog, so you can do any 501work appropriate for the event (such as pause 502a game). Unless you are <a 503href="#SearchContextData">passing search context data</a> 504(discussed below), you should end the method by calling the super class implementation. For 505example:</p> 506 507<pre> 508@Override 509public boolean onSearchRequested() { 510 pauseSomeStuff(); 511 return super.onSearchRequested(); 512} 513</pre> 514 515<p>If the user cancels search by pressing the <em>Back</em> button, the search dialog closes and the 516activity 517regains input focus. You can register to be notified when the search dialog is 518closed with {@link android.app.SearchManager#setOnDismissListener(SearchManager.OnDismissListener) 519setOnDismissListener()} 520and/or {@link android.app.SearchManager#setOnCancelListener(SearchManager.OnCancelListener) 521setOnCancelListener()}. You 522should need to register only the {@link android.app.SearchManager.OnDismissListener 523OnDismissListener}, because it is called every time the search dialog closes. The {@link 524android.app.SearchManager.OnCancelListener OnCancelListener} only pertains to events in which the 525user explicitly exited the search dialog, so it is not called when a search is executed (in which 526case, the search dialog naturally disappears).</p> 527 528<p>If the current activity is not the searchable activity, then the normal activity lifecycle 529events are triggered once the user executes a search (the current activity receives {@link 530android.app.Activity#onPause()} and so forth, as 531described in the <a 532href="{@docRoot}guide/components/activities.html#Lifecycle">Activities</a> 533document). If, however, the current activity is the searchable activity, then one of two 534things happens:</p> 535 536<ol type="a"> 537 <li>By default, the searchable activity receives the {@link 538android.content.Intent#ACTION_SEARCH} intent with a call to {@link 539android.app.Activity#onCreate(Bundle) onCreate()} and a new instance of the 540activity is brought to the top of the activity stack. There are now two instances of your 541searchable activity in the activity stack (so pressing the <em>Back</em> button goes back to the 542previous 543instance of the searchable activity, rather than exiting the searchable activity).</li> 544 <li>If you set {@code android:launchMode} to <code>"singleTop"</code>, then the 545searchable activity receives the {@link android.content.Intent#ACTION_SEARCH} intent with a call 546to {@link android.app.Activity#onNewIntent(Intent)}, passing the new {@link 547android.content.Intent#ACTION_SEARCH} intent here. For example, here's how you might handle 548this case, in which the searchable activity's launch mode is <code>"singleTop"</code>: 549<pre> 550@Override 551public void onCreate(Bundle savedInstanceState) { 552 super.onCreate(savedInstanceState); 553 setContentView(R.layout.search); 554 handleIntent(getIntent()); 555} 556 557@Override 558protected void onNewIntent(Intent intent) { 559 setIntent(intent); 560 handleIntent(intent); 561} 562 563private void handleIntent(Intent intent) { 564 if (Intent.ACTION_SEARCH.equals(intent.getAction())) { 565 String query = intent.getStringExtra(SearchManager.QUERY); 566 doMySearch(query); 567 } 568} 569</pre> 570 571<p>Compared to the example code in the section about <a href="#PerformingSearch">Performing a 572Search</a>, all the code to handle the 573search intent is now in the {@code handleIntent()} method, so that both {@link 574android.app.Activity#onCreate(Bundle) 575onCreate()} and {@link android.app.Activity#onNewIntent(Intent) onNewIntent()} can execute it.</p> 576 577<p>When the system calls {@link android.app.Activity#onNewIntent(Intent)}, the activity has 578not been restarted, so the {@link android.app.Activity#getIntent()} method 579returns the same intent that was received with {@link 580android.app.Activity#onCreate(Bundle) onCreate()}. This is why you should call {@link 581android.app.Activity#setIntent(Intent)} inside {@link 582android.app.Activity#onNewIntent(Intent)} (so that the intent saved by the activity is updated in 583case you call {@link android.app.Activity#getIntent()} in the future).</p> 584 585</li> 586</ol> 587 588<p>The second scenario using <code>"singleTop"</code> launch mode is usually ideal, because chances 589are good that once a search is done, the user will perform additional searches and it's a bad 590experience if your application creates multiple instances of the searchable activity. So, we 591recommend that you set your searchable activity to <code>"singleTop"</code> launch mode in the 592application manifest. For example:</p> 593 594<pre> 595<activity android:name=".SearchableActivity" 596 <b>android:launchMode="singleTop"</b> > 597 <intent-filter> 598 <action android:name="android.intent.action.SEARCH" /> 599 </intent-filter> 600 <meta-data android:name="android.app.searchable" 601 android:resource="@xml/searchable"/> 602 </activity> 603</pre> 604 605 606 607<h3 id="SearchContextData">Passing search context data</h3> 608 609<p>In some cases, you can make necessary refinements to the search query inside the searchable 610activity, for every search made. However, if you want to refine your search criteria based on the 611activity from which the user is performing a search, you can provide additional data in the intent 612that the system sends to your searchable activity. You can pass the additional data in the {@link 613android.app.SearchManager#APP_DATA} {@link android.os.Bundle}, which is included in the {@link 614android.content.Intent#ACTION_SEARCH} intent.</p> 615 616<p>To pass this kind of data to your searchable activity, override the {@link 617android.app.Activity#onSearchRequested()} method for the activity from which the user can perform a 618search, create a {@link android.os.Bundle} with the additional data, and call {@link 619android.app.Activity#startSearch startSearch()} to activate the search dialog. 620For example:</p> 621 622<pre> 623@Override 624public boolean onSearchRequested() { 625 Bundle appData = new Bundle(); 626 appData.putBoolean(SearchableActivity.JARGON, true); 627 startSearch(null, false, appData, false); 628 return true; 629 } 630</pre> 631 632<p>Returning "true" indicates that you have successfully handled this callback event and 633called {@link android.app.Activity#startSearch startSearch()} to activate 634the search dialog. Once the user submits a query, it's delivered to your 635searchable activity along with the data you've added. You can extract the extra data from the {@link 636android.app.SearchManager#APP_DATA} {@link android.os.Bundle} to refine the search. For example:</p> 637 638<pre> 639Bundle appData = getIntent().getBundleExtra(SearchManager.APP_DATA); 640if (appData != null) { 641 boolean jargon = appData.getBoolean(SearchableActivity.JARGON); 642} 643</pre> 644 645<p class="caution"><strong>Caution:</strong> Never call the {@link 646android.app.Activity#startSearch(String,boolean,Bundle,boolean) startSearch()} method from outside 647the {@link android.app.Activity#onSearchRequested()} callback method. To activate the search dialog 648in your activity, always call {@link android.app.Activity#onSearchRequested()}. Otherwise, {@link 649android.app.Activity#onSearchRequested()} is not called and customizations (such as the addition of 650{@code appData} in the above example) are missed.</p> 651 652 653 654<h2 id="UsingSearchWidget">Using the Search Widget</h2> 655 656<div class="figure" style="width:429px;margin:0"> 657 <img src="{@docRoot}images/ui/actionbar-actionview.png" alt="" /> 658 <p class="img-caption"><strong>Figure 2.</strong> The {@link 659android.widget.SearchView} widget as an "action view" in the Action Bar.</p> 660</div> 661 662<p>The {@link android.widget.SearchView} widget is available in Android 3.0 and higher. If 663you're developing your application for Android 3.0 and have decided to use the search widget, we 664recommend that you insert the search widget as an action view in the app bar, 665instead of using the search dialog (and instead of placing the search widget in your activity 666layout). For example, figure 2 shows the search widget in the app bar.</p> 667 668<p>The search widget provides the same functionality as the search dialog. It starts the appropriate 669activity when the user executes a search, and it can provide search suggestions and perform voice 670search. If it's not an option for you to put the search widget in the Action Bar, you can instead 671put the search widget somewhere in your activity layout.</p> 672 673<p class="note"><strong>Note:</strong> When you use the search widget as an action view, you 674still might need to support using the search dialog, for cases in which the search widget does 675not fit in the Action Bar. See the following section about <a href="#UsingBoth">Using both 676the widget and the dialog</a>.</p> 677 678<h3 id="ConfiguringWidget">Configuring the search widget</h3> 679 680<p>After you've created a <a href="#SearchableConfiguration">searchable configuration</a> and a <a 681href="#SearchableActivity">searchable activity</a>, as discussed above, you need to enable assisted 682search for each {@link android.widget.SearchView}. You can do so by calling {@link 683android.widget.SearchView#setSearchableInfo setSearchableInfo()} and passing it the {@link 684android.app.SearchableInfo} object that represents your searchable configuration.</p> 685 686<p>You can get a reference to the {@link android.app.SearchableInfo} by calling {@link 687android.app.SearchManager#getSearchableInfo getSearchableInfo()} on {@link 688android.app.SearchManager}.</p> 689 690<p>For example, if you're using a {@link android.widget.SearchView} as an action view in the 691<a href="{@docRoot}training/appbar/index.html">app bar</a>, you should enable the widget 692during the {@link android.app.Activity#onCreateOptionsMenu onCreateOptionsMenu()} callback:</p> 693 694<pre> 695@Override 696public boolean onCreateOptionsMenu(Menu menu) { 697 // Inflate the options menu from XML 698 MenuInflater inflater = getMenuInflater(); 699 inflater.inflate(R.menu.options_menu, menu); 700 701 // Get the SearchView and set the searchable configuration 702 SearchManager searchManager = (SearchManager) {@link android.app.Activity#getSystemService(java.lang.String) getSystemService()}(Context.SEARCH_SERVICE); 703 SearchView searchView = (SearchView) menu.findItem(R.id.menu_search).getActionView(); 704 // Assumes current activity is the searchable activity 705 searchView.setSearchableInfo(searchManager.getSearchableInfo({@link android.app.Activity#getComponentName()})); 706 searchView.setIconifiedByDefault(false); // Do not iconify the widget; expand it by default 707 708 return true; 709} 710</pre> 711 712<p>That's all you need. The search widget is now configured and the system will deliver search 713queries to your searchable activity. You can also enable <a href="#SearchSuggestions">search 714suggestions</a> for the search widget.</p> 715 716<p class="note"><strong>Note:</strong> If you want to handle all user input yourself, you can do so 717with some callback methods and event listeners. For more information, see the reference 718documentation for {@link android.widget.SearchView} and its nested interfaces for the 719appropriate event listeners.</p> 720 721<p>For more information about action views in the Action Bar, see 722<a href="{@docRoot}training/appbar/action-views.html">Action Views and Action Providers</a>.</p> 723 724 725<h3 id="WidgetFeatures">Other search widget features</h3> 726 727<p>The {@link android.widget.SearchView} widget allows for a few additional features you might 728want:</p> 729 730<dl> 731 <dt>A submit button</dt> 732 <dd>By default, there's no button to submit a search query, so the user must press the 733"Return" key on the keyboard to initiate a search. You can add a "submit" button by calling 734{@link android.widget.SearchView#setSubmitButtonEnabled setSubmitButtonEnabled(true)}.</dd> 735 <dt>Query refinement for search suggestions</dt> 736 <dd>When you've enabled search suggestions, you usually expect users to simply select a 737suggestion, but they might also want to refine the suggested search query. You can add a button 738alongside each suggestion that inserts the suggestion in the search box for refinement by the 739user, by calling {@link android.widget.SearchView#setQueryRefinementEnabled 740setQueryRefinementEnabled(true)}.</dd> 741 <dt>The ability to toggle the search box visibility</dt> 742 <dd>By default, the search widget is "iconified," meaning that it is represented only by a 743search icon (a magnifying glass), and expands to show the search box when the user touches it. 744As shown above, you can show the search box by default, by calling {@link 745android.widget.SearchView#setIconifiedByDefault setIconifiedByDefault(false)}. You can also 746toggle the search widget appearance by calling {@link android.widget.SearchView#setIconified 747setIconified()}.</dd> 748</dl> 749 750<p>There are several other APIs in the {@link android.widget.SearchView} class that allow you to 751customize the search widget. However, most of them are used only when you handle all 752user input yourself, instead of using the Android system to deliver search queries and display 753search suggestions.</p> 754 755 756<h3 id="UsingBoth">Using both the widget and the dialog</h3> 757 758<p>If you insert the search widget in the Action Bar as an <a 759href="{@docRoot}guide/topics/ui/actionbar.html#ActionView">action view</a>, and you enable it to 760appear in the Action Bar "if there is room" (by setting {@code 761android:showAsAction="ifRoom"}), then there is a chance that the search widget will not appear 762as an action view, but the menu item will appear in the overflow menu. For example, when your 763application runs on a smaller screen, there might not be enough room in the Action Bar to display 764the search widget along with other action items or navigation elements, so the menu item will 765instead appear in the overflow menu. When placed in the overflow menu, the item works like an 766ordinary menu item and does not display the action view (the search widget).</p> 767 768<p>To handle this situation, the menu item to which you've attached the search widget should 769activate the search dialog when the user selects it from the overflow menu. In order for it to do 770so, you must implement {@link android.app.Activity#onOptionsItemSelected onOptionsItemSelected()} to 771handle the "Search" menu item and open the search dialog by calling {@link 772android.app.Activity#onSearchRequested onSearchRequested()}.</p> 773 774<p>For more information about how items in the Action Bar work and how to handle this situation, see 775the <a href="{@docRoot}guide/topics/ui/actionbar.html">Action 776Bar</a> developer guide.</p> 777 778<p>Also see the <a 779href="{@docRoot}resources/samples/SearchableDictionary/src/com/example/android/searchabledict/SearchableDictionary.html" 780>Searchable Dictionary</a> for an example implementation using 781both the dialog and the widget.</p> 782 783 784 785<h2 id="VoiceSearch">Adding Voice Search</h2> 786 787<p>You can add voice search functionality to your search dialog or widget by adding the {@code 788android:voiceSearchMode} attribute to your searchable configuration. This adds a voice search 789button that launches a voice prompt. When the user 790has finished speaking, the transcribed search query is sent to your searchable 791activity.</p> 792 793<p>For example:</p> 794 795<pre> 796<?xml version="1.0" encoding="utf-8"?> 797<searchable xmlns:android="http://schemas.android.com/apk/res/android" 798 android:label="@string/search_label" 799 android:hint="@string/search_hint" 800 <b>android:voiceSearchMode="showVoiceSearchButton|launchRecognizer"</b> > 801</searchable> 802</pre> 803 804<p>The value {@code showVoiceSearchButton} is required to enable voice 805search, while the second value, {@code launchRecognizer}, specifies that the voice search button 806should launch a recognizer that returns the transcribed text to the searchable activity.</p> 807 808<p>You can provide additional attributes to specify the voice search behavior, such 809as the language to be expected and the maximum number of results to return. See the <a 810href="searchable-config.html">Searchable Configuration</a> reference for more information about the 811available attributes.</p> 812 813<p class="note"><strong>Note:</strong> Carefully consider whether voice search is appropriate for 814your application. All searches performed with the voice search button are immediately sent to 815your searchable activity without a chance for the user to review the transcribed query. Sufficiently 816test the voice recognition and ensure that it understands the types of queries that 817the user might submit inside your application.</p> 818 819 820 821<h2 id="SearchSuggestions">Adding Search Suggestions</h2> 822 823<div class="figure" style="width:250px;margin:0"> 824<img src="{@docRoot}images/search/search-suggest-custom.png" alt="" height="417" /> 825<p class="img-caption"><strong>Figure 3.</strong> Screenshot of a search dialog with custom 826search suggestions.</p> 827</div> 828 829<p>Both the search dialog and the search widget can provide search suggestions as the user 830types, with assistance from the Android system. The system manages the list of suggestions and 831handles the event when the user selects a suggestion.</p> 832 833<p>You can provide two kinds of search suggestions:</p> 834 835<dl> 836 <dt>Recent query search suggestions</dt> 837 <dd>These suggestions are simply words that the user previously used as search queries in 838your application. 839 <p>See <a href="adding-recent-query-suggestions.html">Adding Recent Query 840Suggestions</a>.</p></dd> 841 <dt>Custom search suggestions</dt> 842 <dd>These are search suggestions that you provide from your own data source, to help users 843immediately select the correct spelling or item they are searching for. Figure 3 shows an 844example of custom suggestions for a dictionary application—the user can select a suggestion 845to instantly go to the definition. 846 <p>See <a href="adding-custom-suggestions.html">Adding Custom 847Suggestions</a></p></dd> 848</dl> 849 850