Home | History | Annotate | Download | only in audio
      1 page.title=Providing Audio Playback for Auto
      2 page.tags="auto", "car", "automotive", "audio"
      3 page.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"
     47 href="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
    205 icon'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
    212 you declare in your app manifest. This service allows Auto devices to find out what content your app
    213 provides. 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
    215 commands.</p>
    216 
    217 <p>You create a media browser service by extending the
    218 {@link android.service.media.MediaBrowserService} class.
    219 Connected 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
    234 dashboard system contacts your app's media browser service.
    235 In your implementation of the {@link android.service.media.MediaBrowserService#onCreate()
    236 onCreate()} method, you must create and register a {@link
    237 android.media.session.MediaSession} object and its callback object.</li>
    238 
    239 <li>The Auto device calls the browser service's {@link
    240 android.service.media.MediaBrowserService#onGetRoot onGetRoot()} method to get the top node of
    241 your content hierarchy. The node retrieved by this call is not used as a menu item, it is only used
    242 to 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
    246 onLoadChildren()} method to get the children of the root node, and uses this information to
    247 present a menu to the user.</li>
    248 
    249 <li>If the user selects a submenu, Auto invokes
    250 {@link android.service.media.MediaBrowserService#onLoadChildren
    251 onLoadChildren()} 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
    254 callback 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
    263 android.service.media.MediaBrowserService} to find out what content you have
    264 available. You need to implement two methods in your browser service to support
    265 this: {@link android.service.media.MediaBrowserService#onGetRoot
    266 onGetRoot()} and {@link
    267 android.service.media.MediaBrowserService#onLoadChildren
    268 onLoadChildren()}.</p>
    269 
    270 <p>Each node in your content hierarchy is represented by a  {@link
    271 android.media.browse.MediaBrowser.MediaItem} object. Each of these objects is
    272 identified by a unique ID string. The client treats these ID strings as
    273 opaque tokens. When a client wants to browse to a submenu, or play a content
    274 item, it passes the ID token. Your app is responsible for associating the ID
    275 token with the appropriate menu node or content item.</p>
    276 
    277 <p class="note"><strong>Note:</strong> You should consider providing different content
    278 hierarchies depending on what client is making the query. In particular, Auto
    279 applications have strict limits on how large a menu they can display. This is
    280 intended to prevent distracting the driver, and to make it easy for the driver
    281 to operate the app via voice commands. For more information on the Auto user
    282 experience restrictions, see the <a href="{@docRoot}shareables/auto/AndroidAuto-media-apps.pdf">
    283 Auto Media Apps</a> guidelines.</p>
    284 
    285 <p>Your implementation of {@link android.service.media.MediaBrowserService#onGetRoot
    286 onGetRoot()} returns information about the root node of the menu
    287 hierarchy. This root node is the parent of the top items your browse hierarchy.
    288 The method is passed information about the calling client. You can use this
    289 information to decide if the client should have access to your content at all.
    290 For example, if you want to limit your app's content to a list of approved
    291 clients, you can compare the passed {@code clientPackageName} to your whitelist.
    292 If the caller isn't an approved package, you can return null to deny access to
    293 your content.</p>
    294 
    295 <p>A typical implementation of {@link
    296 android.service.media.MediaBrowserService#onGetRoot onGetRoot()} might
    297 look like this:</p>
    298 
    299 <pre>
    300 &#64;Override
    301 public 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
    333 public 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
    366 android.media.session.MediaSession} object from your app. The Auto device uses the session object
    367 to 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
    370 android.service.media.MediaBrowserService} by calling the {@link
    371 android.service.media.MediaBrowserService#setSessionToken setSessionToken()} method. This step
    372 allows 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
    376 android.service.media.MediaBrowserService#onCreate() onCreate()} method,
    377 create a {@link android.media.session.MediaSession}. You can then query
    378 the {@link android.media.session.MediaSession} to get its token, and register
    379 the token with your browser service:</p>
    380 
    381 <pre>
    382 public 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
    410 media browse service. When an Auto user wants to play content or control content playback,
    411 such as pausing play or skipping to the next track, Auto invokes one
    412 of the callback object's methods.</p>
    413 
    414 <p>To handle content playback, your app must extend the abstract {@link
    415 android.media.session.MediaSession.Callback} class and implement the methods
    416 that 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
    422 app should play its default content. If playback was paused with
    423 {@link android.media.session.MediaSession.Callback#onPause onPause()}, your
    424 app should resume playback.</dd>
    425 
    426 <dt>{@link android.media.session.MediaSession.Callback#onPlayFromMediaId
    427 onPlayFromMediaId()}</dt>
    428 <dd>Invoked when the user chooses to play a specific item. The method is passed
    429 the item's media ID, which you assigned to the item in the content
    430 hierarchy.</dd>
    431 
    432 <dt>{@link android.media.session.MediaSession.Callback#onPlayFromSearch
    433 onPlayFromSearch()}</dt>
    434 <dd>Invoked when the user chooses to play from a search query. The app should
    435 make 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
    441 onSkipToNext()}</dt>
    442 <dd>Skip to the next item.</dd>
    443 
    444 <dt>{@link android.media.session.MediaSession.Callback#onSkipToPrevious
    445 onSkipToPrevious()}</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.
    454 In some cases you might not implement a method if it is not supported by your app.
    455 For example, if your app plays a live stream (such as a sports
    456 broadcast), the skip to next function might not make sense. In that case, you
    457 could simply use the default implementation of
    458 {@link android.media.session.MediaSession.Callback#onSkipToNext
    459 onSkipToNext()}.</p>
    460 
    461 <p>When your app receives a request to play content, it should play audio the same way it
    462 would in a non-Auto situation (as if the user was listening through a device speaker
    463 or connected headphones). The audio content is automatically sent to the dashboard system
    464 to 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
    473 android.media.MediaPlayer} or <a
    474 href="{@docRoot}guide/topics/media/exoplayer.html">ExoPlayer</a>). If the phone
    475 is connected to an Auto device, .</p>
    476