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<application> 124 ... 125 <meta-data android:name="com.google.android.gms.car.application" 126 android:resource="@xml/automotive_app_desc"/> 127 ... 128<application> 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<automotiveApp> 139 <uses name="media"/> 140</automotiveApp> 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<application> 161 ... 162 <service android:name="<em>.MyMediaBrowserService</em>" 163 android:exported="true"> 164 <intent-filter> 165 <strong><action android:name=</strong> 166 <strong>"android.media.browse.MediaBrowserService"/></strong> 167 </intent-filter> 168 </service> 169 ... 170<application> 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<application> 197 ... 198 <meta-data android:name="com.google.android.gms.car.notification.SmallIcon" 199 android:resource="@drawable/ic_notification" /> 200 ... 201<application> 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@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@Override 333public void onLoadChildren(final String parentMediaId, 334 final Result<List<MediaItem>> result) { 335 336 // Assume for example that the music catalog is already loaded/cached. 337 338 List<MediaBrowser.MediaItem> mediaItems = new ArrayList<>(); 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 <result> 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 <result> 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