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