1page.title=Providing Audio Playback for Auto
2page.tags="auto", "car", "automotive", "audio"
3page.article=true
4
5page.metaDescription=Learn how to extend your audio apps for use in Android Auto devices.
6page.image=auto/images/assets/icons/media_app_playback.png
7
8@jd:body
9
10<div id="tb-wrapper">
11<div id="tb">
12  <h2>Dependencies and Prerequisites</h2>
13  <ul>
14    <li>Android 5.0 (API level 21) or higher</li>
15  </ul>
16
17    <h2>This class teaches you how to</h2>
18
19    <ol>
20      <li><a href="#overview">Provide Audio Services</a></li>
21      <li><a href="#config_manifest">Configure Your Manifest</a></li>
22      <li><a href="#isconnected">Determine if Your App is Connected</a></li>
23      <li><a href="#alarm">Handle Alarms</a></li>
24      <li><a href="#mediaadv">Handle Media Advertisements</a></li>
25      <li><a href="#implement_browser">Build a Browser Service</a></li>
26      <li><a href="#implement_callback">Implement Play Controls</a></li>
27      <li><a href="#support_voice">Support Voice Actions</a></li>
28    </ol>
29
30    <h2>Related Samples</h2>
31
32    <ul>
33      <li><a href="{@docRoot}samples/MediaBrowserService/index.html">
34        MediaBrowserService</a></li>
35      <li><a href="//github.com/googlesamples/android-UniversalMusicPlayer"
36        class="external-link">Universal Media Player</a></li>
37    </ul>
38
39    <h2>See Also</h2>
40
41    <ul>
42      <li>
43        <a href="{@docRoot}shareables/auto/AndroidAuto-audio-apps.pdf">
44              User Experience Guidelines: Audio Apps</a>
45      </li>
46      <li><a href="{@docRoot}training/managing-audio/index.html">Managing Audio
47        Playback</a></li>
48      <li><a href="{@docRoot}guide/topics/media/exoplayer.html">ExoPlayer</a>
49      </li>
50    </ul>
51
52</div>
53</div>
54
55<a class="notice-developers-video wide"
56href="https://www.youtube.com/watch?v=Q96Sw6v4ULg">
57<div>
58    <h3>Video</h3>
59    <p>Devbytes: Android Auto Audio</p>
60</div>
61</a>
62
63<p>
64  Drivers want to access their music and other audio content on the road. Audio books, podcasts,
65  sports commentary, and recorded talks can make a long trip educational, inspirational, and
66  enjoyable. The Android framework allows you to extend your audio app so users can listen to their
67  favorite tunes and audio content using a simple, yet customizable user interface.
68</p>
69
70<p>
71  Apps running on mobile devices with Android 5.0 or higher can provide audio services for
72  dashboard systems running Android Auto. By configuring your app with a few settings and
73  implementing a service for accessing music tracks, you can enable Auto devices to discover your
74  app and provide a browse and playback interface for your app's audio content.
75</p>
76
77<p>
78  This class assumes that you have built an app that plays audio through an Android device's
79  integrated speakers or connected headphones. It describes how to extend your app to allow Auto
80  devices to browse your content listings and play it through a car stereo system.
81</p>
82
83
84<h2 id="overview">Provide Audio Services</h2>
85
86<p>
87  Audio apps do not directly control a car dashboard device that runs Android Auto. When the user
88  connects an Android mobile device into a dashboard system, Android Auto discovers your app through
89  manifest entries that indicate what audio services your app can provide. The dashboard system
90  displays a launcher icon for your app as a music provider and the user can choose to use your
91  app's services. If the user launches your app, the Auto device queries your app to see what
92  content is available, displays your content items to the user, and sends requests to your app to
93  control playback with actions such as play, pause, or skip track.
94</p>
95
96<p>To enable your app to provide audio content for Auto devices, you need to:
97</p>
98
99<ul>
100  <li>Configure your app manifest to do the following:</li>
101    <ul>
102      <li>Declare that your app can provide audio content for Auto devices.</li>
103      <li>Define a service that provides a browsable list of your audio tracks.</li>
104    </ul>
105  </li>
106  <li>Build a service that provides audio track listing information extending
107    {@link android.service.media.MediaBrowserService}.</li>
108  <li>Register a {@link android.media.session.MediaSession} object and implement the
109    {@link android.media.session.MediaSession.Callback} object to enable playback controls.</li>
110</ul>
111
112
113<h2 id="config_manifest">Configure Your Manifest</h2>
114
115<p>
116  When a user plugs an Android mobile device into a dashboard device running Auto, the system
117  requests a list of installed apps that include <a href=
118  "{@docRoot}guide/topics/manifest/manifest-intro.html">app manifest</a> entries to indicate they
119  support services for Auto devices and how to access them. This section describes how to configure
120  your app manifest to indicate your app supports audio services for Auto devices, and allow
121  dashboard system to connect with your app.
122</p>
123
124
125<h3 id="manifest-car-app">Declare Auto audio support</h3>
126
127<p>
128  You indicate that your app supports cars capabilities using the following manifest entry:
129</p>
130
131<pre>
132&lt;application&gt;
133    ...
134    &lt;meta-data android:name="com.google.android.gms.car.application"
135        android:resource="&#64;xml/automotive_app_desc"/&gt;
136    ...
137&lt;application&gt;
138</pre>
139
140<p>
141  This manifest entry refers to a secondary XML file, where you declare what Auto capabilities your
142  app supports. For an app that supports audio for cars, add an XML file to the {@code res/xml/}
143  resources directory as {@code automotive_app_desc.xml}, with the following content:
144</p>
145
146<pre>
147&lt;automotiveApp&gt;
148    &lt;uses name="media"/&gt;
149&lt;/automotiveApp&gt;
150</pre>
151
152<p>
153  For more information about declaring capabilities for Auto devices, see <a href=
154  "{@docRoot}training/auto/start/index.html#auto-metadata">Getting Started with Auto</a>.
155</p>
156
157
158<h3 id="manifest-service">Declare your media browser service</h3>
159
160<p>
161  Auto devices expect to connect to a service in order to browse audio track
162  listings. You declare this service in your manifest to allow the dashboard system to discover
163  this service and connect to your app.
164</p>
165
166<p>The following code example shows how to declare this listing browser service in your manifest:</p>
167
168<pre>
169&lt;application&gt;
170    ...
171    &lt;service android:name="<em>.MyMediaBrowserService</em>"
172                android:exported="true"&gt;
173        &lt;intent-filter&gt;
174            <strong>&lt;action android:name=</strong>
175                <strong>"android.media.browse.MediaBrowserService"/&gt;</strong>
176        &lt;/intent-filter&gt;
177    &lt;/service&gt;
178    ...
179&lt;application&gt;
180</pre>
181
182<p>
183  The service your app provides for browsing audio tracks must extend the
184  {@link android.service.media.MediaBrowserService}. The implementation of this service is discussed
185  in the <a href="#implement_browser">Build a Browser Service</a> section.
186</p>
187
188<p class="note">
189  <strong>Note:</strong> Other clients can also contact your app's browser service aside from Auto
190  devices. These media clients might be other apps on a user's mobile device, or they might be other
191  remote clients.
192</p>
193
194<h3 id="manifest-icon">Specify a notification icon</h3>
195
196<p>
197  The Auto user interface shows notifications about your audio app to the user during the course
198  of operation. For example, if the user has a navigation app running, and one song finishes
199  and a new song starts, the Auto device shows the user a notification to indicate the change with
200  an icon from your app. You can specify an icon that is used to represent your app for these
201  notifications using the following manifest declaration:
202</p>
203
204<pre>
205&lt;application&gt;
206    ...
207    &lt;meta-data android:name="com.google.android.gms.car.notification.SmallIcon"
208        android:resource="&#64;drawable/ic_notification" /&gt;
209    ...
210&lt;application&gt;
211</pre>
212
213<p class="note"><strong>Note:</strong> The icon you provide should have transparency enabled, so the
214icon's background gets filled in with the app's primary color.</p>
215
216<h2 id="isconnected">Determine if Your App is Connected</h2>
217<p>
218It is possible to determine if your app is selected as the current media app.</p>
219<p>
220Android Auto broadcasts an intent with <code>com.google.android.gms.car.media.STATUS</code>
221action when a user connects or disconnects from a media app. The broadcast intent is
222scoped to the package name of the media app selected. You can register a broadcast receiver in your
223app, preferably in your <a href="{@docRoot}reference/android/service/media/MediaBrowserService.html">
224MediaBrowserService</a> implementation and listen for this intent
225and adjust advertisements, metadata, and UI buttons in your app to operate safely in a vehicle.</p>
226
227<p>The broadcasted intent has a String extra <code>media_connection_status</code>, that
228contains either <code>media_connected</code> or <code>media_disconnected</code> string that represents
229 the current connection status. </p>
230
231<pre>
232IntentFilter filter = new IntentFilter("com.google.android.gms.car.media.STATUS");
233BroadcastReceiver receiver = new BroadcastReceiver() {
234    ...
235    public void onReceive(Context context, Intent intent) {
236        String status = intent.getStringExtra("media_connection_status");
237        boolean isConnectedToCar = "media_connected".equals(status);
238        // adjust settings based on the connection status
239    }
240};
241registerReceiver(receiver, filter);
242</pre>
243
244<h2 id="alarm">Handle Alarms</h2>
245<p>
246To prevent user distraction, Android Auto media apps must not start playing audio
247 through the car speakers unless a user consciously starts playback (such as
248 when the user presses play in your app). Even a user-scheduled alarm from the
249 media app must not start playing music through the car speakers.
250 If your media app has an alarm feature, the app should determine if the phone
251 is in
252<a href="{@docRoot}reference/android/content/res/Configuration.html#UI_MODE_TYPE_CAR">car mode</a>
253before playing any audio. Your app can do this by calling
254<a href="{@docRoot}reference/android/app/UiModeManager.html">UiModeManager.getCurrentModeType()</a>,
255 which checks whether the device is running in car mode.
256</p>
257
258<p>
259If the device is in car mode, media apps that support alarms must do one of the
260following things:
261
262<ul>
263<li>Disable the alarm.</li>
264<li>Play the alarm over
265<a href="{@docRoot}reference/android/media/AudioManager.html#STREAM_ALARM">STREAM_ALARM</a>,
266 and provide a UI on the phone screen to disable the alarm.</li>
267</ul>
268
269The following code snippet checks whether an app is running in car mode:
270<pre>
271 public static boolean isCarUiMode(Context c) {
272      UiModeManager uiModeManager = (UiModeManager) c.getSystemService(Context.UI_MODE_SERVICE);
273      if (uiModeManager.getCurrentModeType() == Configuration.UI_MODE_TYPE_CAR) {
274            LogHelper.d(TAG, "Running in Car mode");
275            return true;
276      } else {
277          LogHelper.d(TAG, "Running on a non-Car mode");
278          return false;
279        }
280  }
281</pre>
282
283<h2 id="mediaadv">Handle Media Advertisements</h2>
284<p>By default, Android Auto displays a notification when
285the media metadata changes during an audio playback session. When a media
286app switches from playing music to running an advertisement, it is distracting
287(and unnecessary) to display a notification to the user. To prevent Android Auto
288from displaying a notification in this case, you must set the media metadata
289key {@code android.media.metadata.ADVERTISEMENT} to 1, as shown in the code
290snippet below:
291
292<pre>
293
294&#64;Override
295public static final String EXTRA_METADATA_ADVERTISEMENT =
296            "android.media.metadata.ADVERTISEMENT";
297
298public void onPlayFromMediaId(String mediaId, Bundle extras) {
299    MediaMetadata.Builder builder = new MediaMetadata.Builder();
300    // ...
301    if (isAd(mediaId)) {
302        builder.putLong(EXTRA_METADATA_ADVERTISEMENT, 1);
303    }
304    // ...
305    mediaSession.setMetadata(builder.build());
306}
307
308</pre>
309
310<h2 id="implement_browser">Build a Browser Service</h2>
311
312<p>Auto devices interact with your app by contacting its implementation of a
313  {@link android.service.media.MediaBrowserService}, which
314you declare in your app manifest. This service allows Auto devices to find out what content your app
315provides. Connected Auto devices can also query your app's media browser service to contact the
316{@link android.media.session.MediaSession} provided by your app, which handles content playback
317commands.</p>
318
319<p>You create a media browser service by extending the
320{@link android.service.media.MediaBrowserService} class.
321Connected Auto devices can contact your service to do the following:</p>
322
323<ul>
324  <li>Browse your app's content hierarchy, in order to present a menu to the
325    user</li>
326  <li>Get the token for your app's {@link android.media.session.MediaSession}
327    object, in order to control audio playback</li>
328</ul>
329
330
331<h3 id="browser_workflow">Media browser service workflow</h3>
332
333<ol>
334
335<li>When your app's audio services are requested by a user through a connected Auto device, the
336dashboard system contacts your app's media browser service.
337In your implementation of the {@link android.service.media.MediaBrowserService#onCreate()
338onCreate()} method, you must create and register a {@link
339android.media.session.MediaSession} object and its callback object.</li>
340
341<li>The Auto device calls the browser service's {@link
342android.service.media.MediaBrowserService#onGetRoot onGetRoot()} method to get the top node of
343your content hierarchy. The node retrieved by this call is not used as a menu item, it is only used
344to retrieve its child nodes, which are subsequently displayed as the top menu items.
345</li>
346
347<li>Auto invokes the {@link android.service.media.MediaBrowserService#onLoadChildren
348onLoadChildren()} method to get the children of the root node, and uses this information to
349present a menu to the user.</li>
350
351<li>If the user selects a submenu, Auto invokes
352{@link android.service.media.MediaBrowserService#onLoadChildren
353onLoadChildren()} again to retrieve the child nodes of the selected menu item.</li>
354
355<li>If the user begins playback, Auto invokes the appropriate media session
356callback method to perform that action. For more information, see the section about how to
357<a href="#implement_callback">Implement Playback Controls</a>. </li>
358
359</ol>
360
361
362<h3 id="build_hierarchy">Building your content hierarchy</h3>
363
364<p>Auto devices acting as audio clients call your app's {@link
365android.service.media.MediaBrowserService} to find out what content you have
366available. You need to implement two methods in your browser service to support
367this: {@link android.service.media.MediaBrowserService#onGetRoot
368onGetRoot()} and {@link
369android.service.media.MediaBrowserService#onLoadChildren
370onLoadChildren()}.</p>
371
372<p>Each node in your content hierarchy is represented by a  {@link
373android.media.browse.MediaBrowser.MediaItem} object. Each of these objects is
374identified by a unique ID string. The client treats these ID strings as
375opaque tokens. When a client wants to browse to a submenu, or play a content
376item, it passes the ID token. Your app is responsible for associating the ID
377token with the appropriate menu node or content item.</p>
378
379<p class="note"><strong>Note:</strong> You should consider providing different content
380hierarchies depending on what client is making the query. In particular, Auto
381applications have strict limits on how large a menu they can display. This is
382intended to minimize distracting the driver, and to make it easy for the driver
383to operate the app via voice commands. For more information on the Auto user
384experience restrictions, see the <a href="{@docRoot}shareables/auto/AndroidAuto-audio-apps.pdf">
385Auto Audio Apps</a> guidelines.</p>
386
387<p>Your implementation of {@link android.service.media.MediaBrowserService#onGetRoot
388onGetRoot()} returns information about the root node of the menu
389hierarchy. This root node is the parent of the top items of your browse hierarchy.
390The method is passed information about the calling client. You can use this
391information to decide if the client should have access to your content at all.
392For example, if you want to limit your app's content to a list of approved
393clients, you can compare the passed {@code clientPackageName} to your whitelist
394and verify the certificate used to sign the caller's APK.
395If the caller can't be verified to be an approved package, return null to deny access to
396your content. For an example of an app that validates that the caller is an
397approved app, see the
398<a href="https://github.com/googlesamples/android-UniversalMusicPlayer/blob/master/mobile/src/main/java/com/example/android/uamp/PackageValidator.java"
399class="external-link"><code>PackageValidator</code></a> class in the
400<a href="https://github.com/googlesamples/android-UniversalMusicPlayer"
401class="external-link">Universal Android Music Player</a> sample app.
402</p>
403
404<p>A typical implementation of {@link
405android.service.media.MediaBrowserService#onGetRoot onGetRoot()} might
406look like this:</p>
407
408<pre>
409&#64;Override
410public BrowserRoot onGetRoot(String clientPackageName, int clientUid,
411    Bundle rootHints) {
412
413    // Verify that the specified package is allowed to access your
414    // content! You'll need to write your own logic to do this.
415    if (!isValid(clientPackageName, clientUid)) {
416        // If the request comes from an untrusted package, return null.
417        // No further calls will be made to other media browsing methods.
418
419        return null;
420    }
421
422    return new BrowserRoot(MY_MEDIA_ROOT_ID, null);
423}
424</pre>
425
426<p>
427  The Auto device client builds the top-level menu by calling {@link
428  android.service.media.MediaBrowserService#onLoadChildren onLoadChildren()}
429  with the root node object and getting its children. The client builds
430  submenus by calling the same method with other child nodes. The following
431  example code shows a simple implementation of {@link
432  android.service.media.MediaBrowserService#onLoadChildren onLoadChildren()} method:
433</p>
434
435<pre>
436&#64;Override
437public void onLoadChildren(final String parentMediaId,
438    final Result&lt;List&lt;MediaItem&gt;&gt; result) {
439
440    // Assume for example that the music catalog is already loaded/cached.
441
442    List&lt;MediaItem&gt; mediaItems = new ArrayList&lt;&gt;();
443
444    // Check if this is the root menu:
445    if (MY_MEDIA_ROOT_ID.equals(parentMediaId)) {
446
447        // build the MediaItem objects for the top level,
448        // and put them in the mediaItems list
449    } else {
450
451        // examine the passed parentMediaId to see which submenu we're at,
452        // and put the children of that menu in the mediaItems list
453    }
454    result.sendResult(mediaItems);
455}
456</pre>
457
458<p>
459  For examples of how to implement {@link
460  android.service.media.MediaBrowserService#onLoadChildren onLoadChildren()},
461  see the <a href="{@docRoot}samples/MediaBrowserService/index.html">
462  MediaBrowserService</a> and
463  <a href="https://github.com/googlesamples/android-UniversalMusicPlayer"
464  class="external-link">Universal Android Music Player</a> sample apps.
465</p>
466
467<h2 id="implement_callback">Enable Playback Control</h2>
468
469<p>
470  Auto devices use {@link android.media.session.MediaSession} objects to pass playback control
471  commands to an app that is providing audio services. Your audio app must create an instance of
472  this object to pass to the dashboard device and implement callback methods to enable remote
473  control of audio playback.
474</p>
475
476<h3 id="registering_mediasession">Register a media session</h3>
477
478<p>An Auto device using your app as audio service needs to obtain a {@link
479android.media.session.MediaSession} object from your app. The Auto device uses the session object
480to send playback commands requested by the Auto user back to your app.</p>
481
482<p>When you initialize your browser service, you register that session object with your {@link
483android.service.media.MediaBrowserService} by calling the {@link
484android.service.media.MediaBrowserService#setSessionToken setSessionToken()} method. This step
485allows clients such as an Auto device to retrieve that object by calling your browser service's
486{@link android.service.media.MediaBrowserService#getSessionToken getSessionToken()} method.</p>
487
488<p>In your browser service's {@link
489android.service.media.MediaBrowserService#onCreate() onCreate()} method,
490create a {@link android.media.session.MediaSession}. You can then query
491the {@link android.media.session.MediaSession} to get its token, and register
492the token with your browser service:</p>
493
494<pre>
495public void onCreate() {
496    super.onCreate();
497
498    ...
499    // Start a new MediaSession
500    MediaSession mSession = new MediaSession(this, "session tag");
501    setSessionToken(mSession.getSessionToken());
502
503    // Set a callback object to handle play control requests, which
504    // implements MediaSession.Callback
505    mSession.setCallback(new MyMediaSessionCallback());
506
507    ...
508</pre>
509
510<p>
511  When you create the media session object, you set a callback object that is used to handle
512  playback control requests. You create this callback object by providing an implementation of the
513  {@link android.media.session.MediaSession.Callback} class for your app. The next section
514  discusses how to implement this object.
515</p>
516
517
518<h3 id="playback-commands">Implement play commands</h3>
519
520<p>When an Auto device requests playback of an audio track from your app, it uses the
521{@link android.media.session.MediaSession.Callback} class from your app's
522{@link android.media.session.MediaSession} object, which it obtained from your app's
523media browse service. When an Auto user wants to play content or control content playback,
524such as pausing play or skipping to the next track, Auto invokes one
525of the callback object's methods.</p>
526
527<p>To handle content playback, your app must extend the abstract {@link
528android.media.session.MediaSession.Callback} class and implement the methods
529that your app supports. The most important callback methods are as follows:</p>
530
531<dl>
532
533<dt>{@link android.media.session.MediaSession.Callback#onPlay onPlay()}</dt>
534<dd>Invoked if the user chooses play without choosing a specific item. Your
535app should play its default content. If playback was paused with
536{@link android.media.session.MediaSession.Callback#onPause onPause()}, your
537app should resume playback.</dd>
538
539<p class="note">
540  <strong>Note:</strong> Google Play requires your app not to play music immediately when it
541  launches. For more information on this and other requirements, see
542<a href="{@docRoot}distribute/essentials/quality/auto.html">Auto App Quality</a>.
543</p>
544
545<dt>{@link android.media.session.MediaSession.Callback#onPlayFromMediaId
546onPlayFromMediaId()}</dt>
547<dd>Invoked when the user chooses to play a specific item. The method is passed
548the item's media ID, which you assigned to the item in the content
549hierarchy.</dd>
550
551<dt>{@link android.media.session.MediaSession.Callback#onPlayFromSearch
552onPlayFromSearch()}</dt>
553<dd>Invoked when the user chooses to play from a search query. The app should
554make an appropriate choice based on the passed search string.</dd>
555
556<dt>{@link android.media.session.MediaSession.Callback#onPause onPause()}</dt>
557<dd>Pause playback.</dd>
558
559<dt>{@link android.media.session.MediaSession.Callback#onSkipToNext
560onSkipToNext()}</dt>
561<dd>Skip to the next item.</dd>
562
563<dt>{@link android.media.session.MediaSession.Callback#onSkipToPrevious
564onSkipToPrevious()}</dt>
565<dd>Skip to the previous item.</dd>
566
567<dt>{@link android.media.session.MediaSession.Callback#onStop onStop()}</dt>
568<dd>Stop playback.</dd>
569
570</dl>
571
572<p>Your app should override these methods to provide any desired functionality.
573In some cases you might not implement a method if it is not supported by your app.
574For example, if your app plays a live stream (such as a sports
575broadcast), the skip to next function might not make sense. In that case, you
576could simply use the default implementation of
577{@link android.media.session.MediaSession.Callback#onSkipToNext
578onSkipToNext()}.</p>
579
580<p>When your app receives a request to play content, it should play audio the same way it
581would in a non-Auto situation (as if the user was listening through a device speaker
582or connected headphones). The audio content is automatically sent to the dashboard system
583to be played over the car's speakers.</p>
584
585<p>For more information about playing audio content, see
586<a href="{@docRoot}guide/topics/media/mediaplayer.html">Media Playback</a>,
587<a href="{@docRoot}training/managing-audio/index.html">Managing Audio Playback</a>, and
588<a href="{@docRoot}guide/topics/media/exoplayer.html">ExoPlayer</a>.</p>
589
590<a class="notice-developers-video wide"
591href="https://www.youtube.com/watch?v=xc2HZSwPcwM">
592<div>
593    <h3>Video</h3>
594    <p>Devbytes: Android Auto Voice Actions</p>
595</div>
596</a>
597<h2 id="support_voice">Support Voice Actions</h2>
598
599<p>To reduce driver distractions, you can add voice actions in your audio playback app. With voice
600action support, users can launch your app and play audio by providing voice input on Auto screens.
601If your audio playback app is already active and the user says
602<i>“Play a song”</i>, the system starts playing music without requiring the user to look at or touch
603the screen.</p>
604
605<h3 id="enable_playback">Enable your app to handle audio playback requests</h3>
606
607<p>Enable your audio app to launch with a voice command such as <i>"Play [search query] on
608[your app name]"</i> by adding the following entry in your manifest:</p>
609
610<pre>
611&lt;activity>
612    &lt;intent-filter>
613        &lt;action android:name=
614             "android.media.action.MEDIA_PLAY_FROM_SEARCH" />
615        &lt;category android:name=
616             "android.intent.category.DEFAULT" />
617    &lt;/intent-filter>
618&lt;/activity>
619</pre>
620
621<p>When the user says <i>“Play music on [your app name]”</i> on an Auto screen, Auto
622attempts to launch your app and play audio by calling your app’s
623<a href="{@docRoot}reference/android/media/session/MediaSession.Callback.html#onPlayFromSearch(java.lang.String, android.os.Bundle)"><code>MediaSession.Callback.onPlayFromSearch()</code></a>
624method. If the user has not specified criteria such as a track name or music genre, the
625<a href="{@docRoot}reference/android/media/session/MediaSession.Callback.html#onPlayFromSearch(java.lang.String, android.os.Bundle)"><code>MediaSession.Callback.onPlayFromSearch()</code></a>
626method receives an empty query parameter. Your app should respond by immediately playing audio, such
627as a song from a random queue or the most recent playlist.
628</p>
629
630<h3 id="parse_voice">Parse the voice query to build the playback queue</h3>
631
632<p>When a user searches for a specific criteria, such as <i>“Play jazz on [your app name]”</i>
633or <i>“Listen to [song title]”</i>, the
634<a href="{@docRoot}reference/android/media/session/MediaSession.Callback.html#onPlayFromSearch(java.lang.String, android.os.Bundle)"><code>onPlayFromSearch()</code></a>
635callback method receives the voice search results in the query parameter and an extras bundle. For
636more information on how to handle search queries to play audio content, see
637<a href="https://developer.android.com/guide/components/intents-common.html#PlaySearch">Play music
638based on a search query</a>.
639</p>
640
641<p>To parse the voice search query to play back audio content in your app, follow these steps:</p>
642
643<ol>
644  <li>Use the extras bundle and search query string returned from the voice search to filter
645  results.</li>
646  <li>Build the audio content queue based on these results.</li>
647  <li>Play the audio content.</li>
648</ol>
649
650<p>The
651<a href="{@docRoot}reference/android/media/session/MediaSession.Callback.html#onPlayFromSearch(java.lang.String, android.os.Bundle)"><code>onPlayFromSearch()</code></a>
652method takes an extras parameter with more detailed information from the voice search.
653These extras help you find the audio content in your app for playback. If the search results are
654unable to provide this data, you can implement logic to parse the raw search query and play the
655appropriate tracks based on the query.
656</p>
657
658<p>The following extras are supported in Android Auto:</p>
659
660<ul>
661  <li><a href="{@docRoot}reference/android/provider/MediaStore.html#EXTRA_MEDIA_ALBUM"><code>android.intent.extra.album</code></a></li>
662  <li><a href="{@docRoot}reference/android/provider/MediaStore.html#EXTRA_MEDIA_ARTIST"><code>android.intent.extra.artist</code></a></li>
663  <li><a href="{@docRoot}reference/android/provider/MediaStore.html#EXTRA_MEDIA_GENRE"><code>android.intent.extra.genre</code></a></li>
664  <li><a href="{@docRoot}reference/android/provider/MediaStore.html#EXTRA_MEDIA_PLAYLIST"><code>android.intent.extra.playlist</code></a></li>
665  <li><a href="{@docRoot}reference/android/provider/MediaStore.html#EXTRA_MEDIA_TITLE"><code>android.intent.extra.title</code></a></li>
666</ul>
667
668<p>The following snippet shows how to override the
669<a href="{@docRoot}reference/android/media/session/MediaSession.Callback.html#onPlayFromSearch(java.lang.String, android.os.Bundle)"><code>onPlayFromSearch()</code></a>
670method in your
671<a href="{@docRoot}reference/android/media/session/MediaSession.Callback.html"><code>MediaSession.Callback</code></a>
672implementation to handle the search query and extras for playing audio content in your app:
673</p>
674
675<pre>
676&#64;Override
677public void onPlayFromSearch(String query, Bundle extras) {
678    if (TextUtils.isEmpty(query)) {
679        // The user provided generic string e.g. 'Play music'
680        // Build appropriate playlist queue
681    } else {
682        // Build a queue based on songs that match "query" or "extras" param
683        String mediaFocus = extras.getString(MediaStore.EXTRA_MEDIA_FOCUS);
684        if (TextUtils.equals(mediaFocus,
685                MediaStore.Audio.Artists.ENTRY_CONTENT_TYPE)) {
686            isArtistFocus = true;
687            artist = extras.getString(MediaStore.EXTRA_MEDIA_ARTIST);
688        } else if (TextUtils.equals(mediaFocus,
689                MediaStore.Audio.Albums.ENTRY_CONTENT_TYPE)) {
690            isAlbumFocus = true;
691            album = extras.getString(MediaStore.EXTRA_MEDIA_ALBUM);
692        }
693
694        // Implement additional "extras" param filtering
695    }
696
697    // Implement your logic to retrieve the queue
698    if (isArtistFocus) {
699        result = searchMusicByArtist(artist);
700    } else if (isAlbumFocus) {
701        result = searchMusicByAlbum(album);
702    }
703
704    if (result == null) {
705        // No focus found, search by query for song title
706        result = searchMusicBySongTitle(query);
707    }
708
709    if (result != null && !result.isEmpty()) {
710        // Immediately start playing from the beginning of the search results
711        // Implement your logic to start playing music
712        playMusic(result);
713    } else {
714        // Handle no queue found. Stop playing if the app
715        // is currently playing a song
716    }
717}
718</pre>
719
720<p class="note">
721  <strong>Note:</strong> To minimize driver distractions, immediately initiate audio content
722  playback in the
723  <a href="{@docRoot}reference/android/media/session/MediaSession.Callback.html#onPlayFromSearch(java.lang.String, android.os.Bundle)"><code>onPlayFromSearch()</code></a>
724  method when you have generated the audio content queue based on the user's request.
725</p>
726
727<p>For a more detailed example on how to implement voice search to play audio content in your app,
728see the
729<a href="//github.com/googlesamples/android-UniversalMusicPlayer/">Universal Media Player</a>
730sample.
731</p>
732
733<h3 id="implement_playback_controls">Implement playback control actions</h3>
734
735<p>To provide a hands-free experience while users drive and listen to audio content in Android Auto,
736your app should allow users to control audio content playback with voice actions. When users speak
737commands such as <i>“Next song”</i>, <i>“Pause music”</i>, or <i>“Resume music”</i>, the system
738triggers the corresponding callback method where you implement the playback control action.
739</p>
740
741<p>To provide voice-enabled playback controls, first enable the hardware controls by setting these
742flags in your app’s
743<a href="{@docRoot}reference/android/media/session/MediaSession.html"><code>MediaSession</code></a>
744object:
745</p>
746
747<pre>
748mSession.setFlags(MediaSession.FLAG_HANDLES_MEDIA_BUTTONS |
749    MediaSession.FLAG_HANDLES_TRANSPORT_CONTROLS);
750</pre>
751
752<p>Then, implement the callback methods with the playback controls that you support in your app.
753Here’s a list of voice-enabled playback controls supported by Android Auto:
754</p>
755
756<table>
757  <tr>
758    <th>Example phrase</th>
759    <th>Callback method</th>
760  </tr>
761  <tr>
762    <td><i>"Next song"</i></td>
763    <td><a href="{@docRoot}reference/android/media/session/MediaSession.Callback.html#onSkipToNext()"><code>onSkipToNext()</code></a></td>
764  </tr>
765  <tr>
766    <td><i>"Previous song"</i></td>
767    <td><a href="{@docRoot}reference/android/media/session/MediaSession.Callback.html#onSkipToPrevious()"><code>onSkipToPrevious()</code></a></td>
768  </tr>
769  <tr>
770    <td><i>"Pause music"</i></td>
771    <td><a href="{@docRoot}reference/android/media/session/MediaSession.Callback.html#onPause()"><code>onPause()</code></a></td>
772  </tr>
773  <tr>
774    <td><i>"Stop music"</i></td>
775    <td><a href="{@docRoot}reference/android/media/session/MediaSession.Callback.html#onStop()"><code>onStop()</code></a></td>
776  </tr>
777  <tr>
778    <td><i>"Resume music"</i></td>
779    <td><a href="{@docRoot}reference/android/media/session/MediaSession.Callback.html#onPlay()"><code>onPlay()</code></a></td>
780  </tr>
781</table>
782
783<p>For a more detailed example on how to implement voice-enabled playback actions in your app, see
784the
785<a href="//github.com/googlesamples/android-UniversalMusicPlayer/">Universal Media Player</a>
786sample.
787</p>
788