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