1page.title=Providing Audio Playback for Auto
2page.tags="auto", "car", "automotive", "audio"
3page.article=true
4
5@jd:body
6
7<div id="tb-wrapper">
8<div id="tb">
9  <h2>Dependencies and Prerequisites</h2>
10  <ul>
11    <li>Android 5.0 (API level 21) or higher</li>
12  </ul>
13
14    <h2>This class teaches you how to</h2>
15
16    <ol>
17      <li><a href="#overview">Provide Audio Services</a></li>
18      <li><a href="#config_manifest">Configure Your Manifest</a></li>
19      <li><a href="#implement_browser">Build a Browser Service</a></li>
20      <li><a href="#implement_callback">Implement Play Controls</a></li>
21    </ol>
22
23    <h2>Related Samples</h2>
24
25    <ul>
26      <li><a href="{@docRoot}samples/MediaBrowserService/index.html">
27        MediaBrowserService</a></li>
28    </ul>
29
30    <h2>See Also</h2>
31
32    <ul>
33      <li>
34        <a href="{@docRoot}shareables/auto/AndroidAuto-media-apps.pdf">
35              User Experience Guidelines: Media Apps</a>
36      </li>
37      <li><a href="{@docRoot}training/managing-audio/index.html">Managing Audio
38        Playback</a></li>
39      <li><a href="{@docRoot}guide/topics/media/exoplayer.html">ExoPlayer</a>
40      </li>
41    </ul>
42
43</div>
44</div>
45
46<a class="notice-developers-video wide"
47href="https://www.youtube.com/watch?v=Q96Sw6v4ULg">
48<div>
49    <h3>Video</h3>
50    <p>Devbytes: Android Auto Audio</p>
51</div>
52</a>
53
54<p>
55  Drivers want to access their music and other audio content on the road. Audio books, podcasts,
56  sports commentary, and recorded talks can make a long trip educational, inspirational, and
57  enjoyable. The Android framework allows you to extend your audio app so users can listen to their
58  favorite tunes and audio content using a simpler, safer user interface.
59</p>
60
61<p>
62  Apps running on mobile devices with Android 5.0 or higher can provide audio services for
63  dashboard systems running Android Auto. By configuring your app with a few settings and
64  implementing a service for accessing music tracks, you can enable Auto devices to discover your
65  app and provide a browse and playback interface for your app's audio content.
66</p>
67
68<p>
69  This class assumes that you have built an app that plays audio through an Android device's
70  integrated speakers or connected headphones. It describes how to extend your app to allow Auto
71  devices to browse your content listings and play it through a car stereo system.
72</p>
73
74
75<h2 id="overview">Provide Audio Services</h2>
76
77<p>
78  Audio apps do not directly control a car dashboard device that runs Android Auto. When the user
79  connects an Android mobile device into a dashboard system, Android Auto discovers your app through
80  manifest entries that indicate what audio services your app can provide. The dashboard system
81  displays a launcher icon for your app as a music provider and the user can choose to use your
82  app's services. If the user launches your app, the Auto device queries your app to see what
83  content is available, displays your content items to the user, and sends requests to your app to
84  control playback with actions such as play, pause, or skip track.
85</p>
86
87<p>To enable your app to provide audio content for Auto devices, you need to:
88</p>
89
90<ul>
91  <li>Configure your app manifest to do the following:</li>
92    <ul>
93      <li>Declare that your app can provide audio content for Auto devices.</li>
94      <li>Define a service that provides a browsable list of your audio tracks.</li>
95    </ul>
96  </li>
97  <li>Build a service that provides audio track listing information extending
98    {@link android.service.media.MediaBrowserService}.</li>
99  <li>Register a {@link android.media.session.MediaSession} object and implement the
100    {@link android.media.session.MediaSession.Callback} object to enable playback controls.</li>
101</ul>
102
103
104<h2 id="config_manifest">Configure Your Manifest</h2>
105
106<p>
107  When a user plugs an Android mobile device into a dashboard device running Auto, the system
108  requests a list of installed apps that include <a href=
109  "{@docRoot}guide/topics/manifest/manifest-intro.html">app manifest</a> entries to indicate they
110  support services for Auto devices and how to access them. This section describes how to configure
111  your app manifest to indicate your app supports audio services for Auto devices, and allow
112  dashboard system to connect with your app.
113</p>
114
115
116<h3 id="manifest-car-app">Declare Auto audio support</h3>
117
118<p>
119  You indicate that your app supports cars capabilities using the following manifest entry:
120</p>
121
122<pre>
123&lt;application&gt;
124    ...
125    &lt;meta-data android:name="com.google.android.gms.car.application"
126        android:resource="&#64;xml/automotive_app_desc"/&gt;
127    ...
128&lt;application&gt;
129</pre>
130
131<p>
132  This manifest entry refers to a secondary XML file, where you declare what Auto capabilities your
133  app supports. For an app that supports audio for cars, add an XML file to the {@code res/xml/}
134  resources directory as {@code automotive_app_desc.xml}, with the following content:
135</p>
136
137<pre>
138&lt;automotiveApp&gt;
139    &lt;uses name="media"/&gt;
140&lt;/automotiveApp&gt;
141</pre>
142
143<p>
144  For more information about declaring capabilities for Auto devices, see <a href=
145  "{@docRoot}training/auto/start/index.html#auto-metadata">Getting Started with Auto</a>.
146</p>
147
148
149<h3 id="manifest-service">Declare your media browser service</h3>
150
151<p>
152  Auto devices expect to connect to a service in order to browse audio track
153  listings. You declare this service in your manifest to allow the dashboard system to discover
154  this service and connect to your app.
155</p>
156
157<p>The following code example shows how to declare this listing browser service in your manifest:</p>
158
159<pre>
160&lt;application&gt;
161    ...
162    &lt;service android:name="<em>.MyMediaBrowserService</em>"
163                android:exported="true"&gt;
164        &lt;intent-filter&gt;
165            <strong>&lt;action android:name=</strong>
166                <strong>"android.media.browse.MediaBrowserService"/&gt;</strong>
167        &lt;/intent-filter&gt;
168    &lt;/service&gt;
169    ...
170&lt;application&gt;
171</pre>
172
173<p>
174  The service your app provides for browsing audio tracks must extend the
175  {@link android.service.media.MediaBrowserService}. The implementation of this service is discussed
176  in the <a href="#implement_browser">Build a Browser Service</a> section.
177</p>
178
179<p class="note">
180  <strong>Note:</strong> Other clients can also contact your app's browser service aside from Auto
181  devices. These media clients might be other apps on a user's mobile device, or they might be other
182  remote clients.
183</p>
184
185<h3 id="manifest-icon">Specify a notification icon</h3>
186
187<p>
188  The Auto user interface shows notifications about your audio app to the user during the course
189  of operation. For example, if the user has a navigation app running, and one song finishes
190  and a new song starts, the Auto device shows the user a notification to indicate the change with
191  an icon from your app. You can specify an icon that is used to represent your app for these
192  notifications using the following manifest declaration:
193</p>
194
195<pre>
196&lt;application&gt;
197    ...
198    &lt;meta-data android:name="com.google.android.gms.car.notification.SmallIcon"
199        android:resource="&#64;drawable/ic_notification" /&gt;
200    ...
201&lt;application&gt;
202</pre>
203
204<p class="note"><strong>Note:</strong> The icon you provide should have transparency enabled, so the
205icon's background gets filled in with the app's primary color.</p>
206
207
208<h2 id="implement_browser">Build a Browser Service</h2>
209
210<p>Auto devices interact with your app by contacting its implementation of a
211  {@link android.service.media.MediaBrowserService}, which
212you declare in your app manifest. This service allows Auto devices to find out what content your app
213provides. Connected Auto devices can also query your app's media browser service to contact the
214{@link android.media.session.MediaSession} provided by your app, which handles content playback
215commands.</p>
216
217<p>You create a media browser service by extending the
218{@link android.service.media.MediaBrowserService} class.
219Connected Auto devices can contact your service to do the following:</p>
220
221<ul>
222  <li>Browse your app's content hierarchy, in order to present a menu to the
223    user</li>
224  <li>Get the token for your app's {@link android.media.session.MediaSession}
225    object, in order to control audio playback</li>
226</ul>
227
228
229<h3 id="browser_workflow">Media browser service workflow</h3>
230
231<ol>
232
233<li>When your app's audio services are requested by a user through a connected Auto device, the
234dashboard system contacts your app's media browser service.
235In your implementation of the {@link android.service.media.MediaBrowserService#onCreate()
236onCreate()} method, you must create and register a {@link
237android.media.session.MediaSession} object and its callback object.</li>
238
239<li>The Auto device calls the browser service's {@link
240android.service.media.MediaBrowserService#onGetRoot onGetRoot()} method to get the top node of
241your content hierarchy. The node retrieved by this call is not used as a menu item, it is only used
242to retrieve its child nodes, which are subsequently displayed as the top menu items.
243</li>
244
245<li>Auto invokes the {@link android.service.media.MediaBrowserService#onLoadChildren
246onLoadChildren()} method to get the children of the root node, and uses this information to
247present a menu to the user.</li>
248
249<li>If the user selects a submenu, Auto invokes
250{@link android.service.media.MediaBrowserService#onLoadChildren
251onLoadChildren()} again to retrieve the child nodes of the selected menu item.</li>
252
253<li>If the user begins playback, Auto invokes the appropriate media session
254callback method to perform that action. For more information, see the section about how to
255<a href="#implement_callback">Implement Playback Controls</a>. </li>
256
257</ol>
258
259
260<h3 id="build_hierarchy">Building your content hierarchy</h3>
261
262<p>Auto devices acting as audio clients call your app's {@link
263android.service.media.MediaBrowserService} to find out what content you have
264available. You need to implement two methods in your browser service to support
265this: {@link android.service.media.MediaBrowserService#onGetRoot
266onGetRoot()} and {@link
267android.service.media.MediaBrowserService#onLoadChildren
268onLoadChildren()}.</p>
269
270<p>Each node in your content hierarchy is represented by a  {@link
271android.media.browse.MediaBrowser.MediaItem} object. Each of these objects is
272identified by a unique ID string. The client treats these ID strings as
273opaque tokens. When a client wants to browse to a submenu, or play a content
274item, it passes the ID token. Your app is responsible for associating the ID
275token with the appropriate menu node or content item.</p>
276
277<p class="note"><strong>Note:</strong> You should consider providing different content
278hierarchies depending on what client is making the query. In particular, Auto
279applications have strict limits on how large a menu they can display. This is
280intended to prevent distracting the driver, and to make it easy for the driver
281to operate the app via voice commands. For more information on the Auto user
282experience restrictions, see the <a href="{@docRoot}shareables/auto/AndroidAuto-media-apps.pdf">
283Auto Media Apps</a> guidelines.</p>
284
285<p>Your implementation of {@link android.service.media.MediaBrowserService#onGetRoot
286onGetRoot()} returns information about the root node of the menu
287hierarchy. This root node is the parent of the top items your browse hierarchy.
288The method is passed information about the calling client. You can use this
289information to decide if the client should have access to your content at all.
290For example, if you want to limit your app's content to a list of approved
291clients, you can compare the passed {@code clientPackageName} to your whitelist.
292If the caller isn't an approved package, you can return null to deny access to
293your content.</p>
294
295<p>A typical implementation of {@link
296android.service.media.MediaBrowserService#onGetRoot onGetRoot()} might
297look like this:</p>
298
299<pre>
300&#64;Override
301public BrowserRoot onGetRoot(String clientPackageName, int clientUid,
302    Bundle rootHints) {
303
304    // To ensure you are not allowing any arbitrary app to browse your app's
305    // contents, you need to check the origin:
306    if (!PackageValidator.isCallerAllowed(this, clientPackageName, clientUid)) {
307        // If the request comes from an untrusted package, return null.
308        // No further calls will be made to other media browsing methods.
309        LogHelper.w(TAG, "OnGetRoot: IGNORING request from untrusted package "
310                + clientPackageName);
311        return null;
312    }
313    if (ANDROID_AUTO_PACKAGE_NAME.equals(clientPackageName)) {
314        // Optional: if your app needs to adapt ads, music library or anything
315        // else that needs to run differently when connected to the car, this
316        // is where you should handle it.
317    }
318    return new BrowserRoot(MEDIA_ID_ROOT, null);
319}
320</pre>
321
322<p>
323  The Auto device client builds the top-level menu by calling {@link
324  android.service.media.MediaBrowserService#onLoadChildren onLoadChildren()}
325  with the root node object and getting it's children. The client builds
326  submenus by calling the same method with other child nodes. The following
327  example code shows a simple implementation of {@link
328  android.service.media.MediaBrowserService#onLoadChildren onLoadChildren()} method:
329</p>
330
331<pre>
332&#64;Override
333public void onLoadChildren(final String parentMediaId,
334    final Result&lt;List&lt;MediaItem&gt;&gt; result) {
335
336    // Assume for example that the music catalog is already loaded/cached.
337
338    List&lt;MediaBrowser.MediaItem&gt; mediaItems = new ArrayList&lt;&gt;();
339
340    // Check if this is the root menu:
341    if (MEDIA_BROWSER_ROOT.equals(parentMediaId)) {
342
343        // build the MediaItem objects for the top level,
344        // and put them in the &lt;result&gt; list
345    } else {
346
347        // examine the passed parentMediaId to see which submenu we're at,
348        // and put the children of that menu in the &lt;result&gt; list
349    }
350}
351</pre>
352
353
354<h2 id="implement_callback">Enable Playback Control</h2>
355
356<p>
357  Auto devices use {@link android.media.session.MediaSession} objects to pass playback control
358  commands to an app that is providing audio services. Your audio app must create an instance of
359  this object to pass to the dashboard device and implement callback methods to enable remote
360  control of audio playback.
361</p>
362
363<h3 id="registering_mediasession">Register a media session</h3>
364
365<p>An Auto device using your app as audio service needs to obtain a {@link
366android.media.session.MediaSession} object from your app. The Auto device uses the session object
367to send playback commands requested by the Auto user back to your app.</p>
368
369<p>When you initialize your browser service, you register that session object with your {@link
370android.service.media.MediaBrowserService} by calling the {@link
371android.service.media.MediaBrowserService#setSessionToken setSessionToken()} method. This step
372allows clients such as an Auto device to retrieve that object by calling your browser service's
373{@link android.service.media.MediaBrowserService#getSessionToken getSessionToken()} method.</p>
374
375<p>In your browser service's {@link
376android.service.media.MediaBrowserService#onCreate() onCreate()} method,
377create a {@link android.media.session.MediaSession}. You can then query
378the {@link android.media.session.MediaSession} to get its token, and register
379the token with your browser service:</p>
380
381<pre>
382public void onCreate() {
383        super.onCreate();
384
385    ...
386    // Start a new MediaSession
387    MediaSession mSession = new MediaSession(this, "session tag");
388    setSessionToken(mSession.getSessionToken());
389
390    // Set a callback object to handle play control requests, which
391    // implements MediaSession.Callback
392    mSession.setCallback(new MyMediaSessionCallback());
393
394    ...
395</pre>
396
397<p>
398  When you create the media session object, you set a callback object that is used to handle
399  playback control requests. You create this callback object by providing an implementation of the
400  {@link android.media.session.MediaSession.Callback} class for your app. The next section
401  discusses how to implement this object.
402</p>
403
404
405<h3 id="playback-commands">Implement play commands</h3>
406
407<p>When an Auto device requests playback of an audio track from your app, it uses the
408{@link android.media.session.MediaSession.Callback} class from your app's
409{@link android.media.session.MediaSession} object, which it obtained from your app's
410media browse service. When an Auto user wants to play content or control content playback,
411such as pausing play or skipping to the next track, Auto invokes one
412of the callback object's methods.</p>
413
414<p>To handle content playback, your app must extend the abstract {@link
415android.media.session.MediaSession.Callback} class and implement the methods
416that your app supports. The most important callback methods are as follows:</p>
417
418<dl>
419
420<dt>{@link android.media.session.MediaSession.Callback#onPlay onPlay()}</dt>
421<dd>Invoked if the user chooses play without choosing a specific item. Your
422app should play its default content. If playback was paused with
423{@link android.media.session.MediaSession.Callback#onPause onPause()}, your
424app should resume playback.</dd>
425
426<dt>{@link android.media.session.MediaSession.Callback#onPlayFromMediaId
427onPlayFromMediaId()}</dt>
428<dd>Invoked when the user chooses to play a specific item. The method is passed
429the item's media ID, which you assigned to the item in the content
430hierarchy.</dd>
431
432<dt>{@link android.media.session.MediaSession.Callback#onPlayFromSearch
433onPlayFromSearch()}</dt>
434<dd>Invoked when the user chooses to play from a search query. The app should
435make an appropriate choice based on the passed search string.</dd>
436
437<dt>{@link android.media.session.MediaSession.Callback#onPause onPause()}</dt>
438<dd>Pause playback.</dd>
439
440<dt>{@link android.media.session.MediaSession.Callback#onSkipToNext
441onSkipToNext()}</dt>
442<dd>Skip to the next item.</dd>
443
444<dt>{@link android.media.session.MediaSession.Callback#onSkipToPrevious
445onSkipToPrevious()}</dt>
446<dd>Skip to the previous item.</dd>
447
448<dt>{@link android.media.session.MediaSession.Callback#onStop onStop()}</dt>
449<dd>Stop playback.</dd>
450
451</dl>
452
453<p>Your app should override these methods to provide any desired functionality.
454In some cases you might not implement a method if it is not supported by your app.
455For example, if your app plays a live stream (such as a sports
456broadcast), the skip to next function might not make sense. In that case, you
457could simply use the default implementation of
458{@link android.media.session.MediaSession.Callback#onSkipToNext
459onSkipToNext()}.</p>
460
461<p>When your app receives a request to play content, it should play audio the same way it
462would in a non-Auto situation (as if the user was listening through a device speaker
463or connected headphones). The audio content is automatically sent to the dashboard system
464to be played over the car's speakers.</p>
465
466<p>For more information about playing audio content, see
467<a href="{@docRoot}guide/topics/media/mediaplayer.html">Media Playback</a>,
468<a href="{@docRoot}training/managing-audio/index.html">Managing Audio Playback</a>, and
469<a href="{@docRoot}guide/topics/media/exoplayer.html">ExoPlayer</a>.
470
471
472(for example, by using a {@link
473android.media.MediaPlayer} or <a
474href="{@docRoot}guide/topics/media/exoplayer.html">ExoPlayer</a>). If the phone
475is connected to an Auto device, .</p>
476