diff options
author | Andrew Solovay <asolovay@google.com> | 2014-11-18 09:56:01 +0000 |
---|---|---|
committer | Android Git Automerger <android-git-automerger@android.com> | 2014-11-18 09:56:01 +0000 |
commit | 7ca874e71c014718e2107e2f50e095bcc2c474fc (patch) | |
tree | 6ddad65e7f3130280554ff3c35b132227aa3f1f4 | |
parent | 1f03a234ff757736c771d1e99625f173f36ab89c (diff) | |
parent | 4a9945e9c03e8a2c006febf4b8325f0c1bf84b39 (diff) | |
download | frameworks_base-7ca874e71c014718e2107e2f50e095bcc2c474fc.zip frameworks_base-7ca874e71c014718e2107e2f50e095bcc2c474fc.tar.gz frameworks_base-7ca874e71c014718e2107e2f50e095bcc2c474fc.tar.bz2 |
am 4a9945e9: am 7fe755e6: docs: (Preview) Building Android Audio Playback Apps guide.
* commit '4a9945e9c03e8a2c006febf4b8325f0c1bf84b39':
docs: (Preview) Building Android Audio Playback Apps guide.
-rw-r--r-- | docs/html/training/auto/audio/index.jd | 476 | ||||
-rw-r--r-- | docs/html/training/training_toc.cs | 6 |
2 files changed, 482 insertions, 0 deletions
diff --git a/docs/html/training/auto/audio/index.jd b/docs/html/training/auto/audio/index.jd new file mode 100644 index 0000000..2656b96 --- /dev/null +++ b/docs/html/training/auto/audio/index.jd @@ -0,0 +1,476 @@ +page.title=Providing Audio Playback for Auto +page.tags="auto", "car", "automotive", "audio" +page.article=true + +@jd:body + +<div id="tb-wrapper"> +<div id="tb"> + <h2>Dependencies and Prerequisites</h2> + <ul> + <li>Android 5.0 (API level 21) or higher</li> + </ul> + + <h2>This class teaches you how to</h2> + + <ol> + <li><a href="#overview">Provide Audio Services</a></li> + <li><a href="#config_manifest">Configure Your Manifest</a></li> + <li><a href="#implement_browser">Build a Browser Service</a></li> + <li><a href="#implement_callback">Implement Play Controls</a></li> + </ol> + + <h2>Related Samples</h2> + + <ul> + <li><a href="{@docRoot}samples/MediaBrowserService/index.html"> + MediaBrowserService</a></li> + </ul> + + <h2>See Also</h2> + + <ul> + <li> + <a href="{@docRoot}shareables/auto/AndroidAuto-media-apps.pdf"> + User Experience Guidelines: Media Apps</a> + </li> + <li><a href="{@docRoot}training/managing-audio/index.html">Managing Audio + Playback</a></li> + <li><a href="{@docRoot}guide/topics/media/exoplayer.html">ExoPlayer</a> + </li> + </ul> + +</div> +</div> + +<a class="notice-developers-video wide" +href="https://www.youtube.com/watch?v=Q96Sw6v4ULg"> +<div> + <h3>Video</h3> + <p>Devbytes: Android Auto Audio</p> +</div> +</a> + +<p> + Drivers want to access their music and other audio content on the road. Audio books, podcasts, + sports commentary, and recorded talks can make a long trip educational, inspirational, and + enjoyable. The Android framework allows you to extend your audio app so users can listen to their + favorite tunes and audio content using a simpler, safer user interface. +</p> + +<p> + Apps running on mobile devices with Android 5.0 or higher can provide audio services for + dashboard systems running Android Auto. By configuring your app with a few settings and + implementing a service for accessing music tracks, you can enable Auto devices to discover your + app and provide a browse and playback interface for your app's audio content. +</p> + +<p> + This class assumes that you have built an app that plays audio through an Android device's + integrated speakers or connected headphones. It describes how to extend your app to allow Auto + devices to browse your content listings and play it through a car stereo system. +</p> + + +<h2 id="overview">Provide Audio Services</h2> + +<p> + Audio apps do not directly control a car dashboard device that runs Android Auto. When the user + connects an Android mobile device into a dashboard system, Android Auto discovers your app through + manifest entries that indicate what audio services your app can provide. The dashboard system + displays a launcher icon for your app as a music provider and the user can choose to use your + app's services. If the user launches your app, the Auto device queries your app to see what + content is available, displays your content items to the user, and sends requests to your app to + control playback with actions such as play, pause, or skip track. +</p> + +<p>To enable your app to provide audio content for Auto devices, you need to: +</p> + +<ul> + <li>Configure your app manifest to do the following:</li> + <ul> + <li>Declare that your app can provide audio content for Auto devices.</li> + <li>Define a service that provides a browsable list of your audio tracks.</li> + </ul> + </li> + <li>Build a service that provides audio track listing information extending + {@link android.service.media.MediaBrowserService}.</li> + <li>Register a {@link android.media.session.MediaSession} object and implement the + {@link android.media.session.MediaSession.Callback} object to enable playback controls.</li> +</ul> + + +<h2 id="config_manifest">Configure Your Manifest</h2> + +<p> + When a user plugs an Android mobile device into a dashboard device running Auto, the system + requests a list of installed apps that include <a href= + "{@docRoot}guide/topics/manifest/manifest-intro.html">app manifest</a> entries to indicate they + support services for Auto devices and how to access them. This section describes how to configure + your app manifest to indicate your app supports audio services for Auto devices, and allow + dashboard system to connect with your app. +</p> + + +<h3 id="manifest-car-app">Declare Auto audio support</h3> + +<p> + You indicate that your app supports cars capabilities using the following manifest entry: +</p> + +<pre> +<application> + ... + <meta-data android:name="com.google.android.gms.car.application" + android:resource="@xml/automotive_app_desc"/> + ... +<application> +</pre> + +<p> + This manifest entry refers to a secondary XML file, where you declare what Auto capabilities your + app supports. For an app that supports audio for cars, add an XML file to the {@code res/xml/} + resources directory as {@code automotive_app_desc.xml}, with the following content: +</p> + +<pre> +<automotiveApp> + <uses name="media"/> +</automotiveApp> +</pre> + +<p> + For more information about declaring capabilities for Auto devices, see <a href= + "{@docRoot}training/auto/start/index.html#auto-metadata">Getting Started with Auto</a>. +</p> + + +<h3 id="manifest-service">Declare your media browser service</h3> + +<p> + Auto devices expect to connect to a service in order to browse audio track + listings. You declare this service in your manifest to allow the dashboard system to discover + this service and connect to your app. +</p> + +<p>The following code example shows how to declare this listing browser service in your manifest:</p> + +<pre> +<application> + ... + <service android:name="<em>.MyMediaBrowserService</em>" + android:exported="true"> + <intent-filter> + <strong><action android:name=</strong> + <strong>"android.media.browse.MediaBrowserService"/></strong> + </intent-filter> + </service> + ... +<application> +</pre> + +<p> + The service your app provides for browsing audio tracks must extend the + {@link android.service.media.MediaBrowserService}. The implementation of this service is discussed + in the <a href="#implement_browser">Build a Browser Service</a> section. +</p> + +<p class="note"> + <strong>Note:</strong> Other clients can also contact your app's browser service aside from Auto + devices. These media clients might be other apps on a user's mobile device, or they might be other + remote clients. +</p> + +<h3 id="manifest-icon">Specify a notification icon</h3> + +<p> + The Auto user interface shows notifications about your audio app to the user during the course + of operation. For example, if the user has a navigation app running, and one song finishes + and a new song starts, the Auto device shows the user a notification to indicate the change with + an icon from your app. You can specify an icon that is used to represent your app for these + notifications using the following manifest declaration: +</p> + +<pre> +<application> + ... + <meta-data android:name="com.google.android.gms.car.notification.SmallIcon" + android:resource="@drawable/ic_notification" /> + ... +<application> +</pre> + +<p class="note"><strong>Note:</strong> The icon you provide should have transparency enabled, so the +icon's background gets filled in with the app's primary color.</p> + + +<h2 id="implement_browser">Build a Browser Service</h2> + +<p>Auto devices interact with your app by contacting its implementation of a + {@link android.service.media.MediaBrowserService}, which +you declare in your app manifest. This service allows Auto devices to find out what content your app +provides. Connected Auto devices can also query your app's media browser service to contact the +{@link android.media.session.MediaSession} provided by your app, which handles content playback +commands.</p> + +<p>You create a media browser service by extending the +{@link android.service.media.MediaBrowserService} class. +Connected Auto devices can contact your service to do the following:</p> + +<ul> + <li>Browse your app's content hierarchy, in order to present a menu to the + user</li> + <li>Get the token for your app's {@link android.media.session.MediaSession} + object, in order to control audio playback</li> +</ul> + + +<h3 id="browser_workflow">Media browser service workflow</h3> + +<ol> + +<li>When your app's audio services are requested by a user through a connected Auto device, the +dashboard system contacts your app's media browser service. +In your implementation of the {@link android.service.media.MediaBrowserService#onCreate() +onCreate()} method, you must create and register a {@link +android.media.session.MediaSession} object and its callback object.</li> + +<li>The Auto device calls the browser service's {@link +android.service.media.MediaBrowserService#onGetRoot onGetRoot()} method to get the top node of +your content hierarchy. The node retrieved by this call is not used as a menu item, it is only used +to retrieve its child nodes, which are subsequently displayed as the top menu items. +</li> + +<li>Auto invokes the {@link android.service.media.MediaBrowserService#onLoadChildren +onLoadChildren()} method to get the children of the root node, and uses this information to +present a menu to the user.</li> + +<li>If the user selects a submenu, Auto invokes +{@link android.service.media.MediaBrowserService#onLoadChildren +onLoadChildren()} again to retrieve the child nodes of the selected menu item.</li> + +<li>If the user begins playback, Auto invokes the appropriate media session +callback method to perform that action. For more information, see the section about how to +<a href="#implement_callback">Implement Playback Controls</a>. </li> + +</ol> + + +<h3 id="build_hierarchy">Building your content hierarchy</h3> + +<p>Auto devices acting as audio clients call your app's {@link +android.service.media.MediaBrowserService} to find out what content you have +available. You need to implement two methods in your browser service to support +this: {@link android.service.media.MediaBrowserService#onGetRoot +onGetRoot()} and {@link +android.service.media.MediaBrowserService#onLoadChildren +onLoadChildren()}.</p> + +<p>Each node in your content hierarchy is represented by a {@link +android.media.browse.MediaBrowser.MediaItem} object. Each of these objects is +identified by a unique ID string. The client treats these ID strings as +opaque tokens. When a client wants to browse to a submenu, or play a content +item, it passes the ID token. Your app is responsible for associating the ID +token with the appropriate menu node or content item.</p> + +<p class="note"><strong>Note:</strong> You should consider providing different content +hierarchies depending on what client is making the query. In particular, Auto +applications have strict limits on how large a menu they can display. This is +intended to prevent distracting the driver, and to make it easy for the driver +to operate the app via voice commands. For more information on the Auto user +experience restrictions, see the <a href="{@docRoot}shareables/auto/AndroidAuto-media-apps.pdf"> +Auto Media Apps</a> guidelines.</p> + +<p>Your implementation of {@link android.service.media.MediaBrowserService#onGetRoot +onGetRoot()} returns information about the root node of the menu +hierarchy. This root node is the parent of the top items your browse hierarchy. +The method is passed information about the calling client. You can use this +information to decide if the client should have access to your content at all. +For example, if you want to limit your app's content to a list of approved +clients, you can compare the passed {@code clientPackageName} to your whitelist. +If the caller isn't an approved package, you can return null to deny access to +your content.</p> + +<p>A typical implementation of {@link +android.service.media.MediaBrowserService#onGetRoot onGetRoot()} might +look like this:</p> + +<pre> +@Override +public BrowserRoot onGetRoot(String clientPackageName, int clientUid, + Bundle rootHints) { + + // Check the calling client to make sure it's one you approve. + // For example, to limit access to just Auto, the Auto emulator, + // and this app: + + if (!clientPackageName.equals("com.google.android.projection.gearhead") && + !clientPackageName.equals("com.example.android.media") && + !clientPackageName.equals(getApplication().getPackageName()) { + + // If the request comes from an untrusted package, return null. + // No further calls will be made to other media browsing methods. + return null; + } + + // Return a BrowserRoot. If you wish, you could have multiple BrowserRoot + // objects and return different ones depending on the calling client. + // In this example, there's just a single BrowserRoot. + return new BrowserRoot(MEDIA_BROWSER_ROOT, null); + } +</pre> + +<p> + The Auto device client builds the top-level menu by calling {@link + android.service.media.MediaBrowserService#onLoadChildren onLoadChildren()} with the root node + object and getting it's children. The client builds submenus by calling the same method with + other child nodes. The following example code shows a simple implementation of {@link + android.service.media.MediaBrowserService#onLoadChildren onLoadChildren()} method: +</p> + +<pre> +@Override +public void onLoadChildren(final String parentMediaId, + final Result<List<MediaItem>> result) { + + // Assume for example that the music catalog is already loaded/cached. + + List<MediaBrowser.MediaItem> mediaItems = new ArrayList<>(); + + // Check if this is the root menu: + if (MEDIA_BROWSER_ROOT.equals(parentMediaId)) { + + // build the MediaItem objects for the top level, + // and put them in the <result> list + } else { + + // examine the passed parentMediaId to see which submenu we're at, + // and put the children of that menu in the <result> list + } +} +</pre> + + +<h2 id="implement_callback">Enable Playback Control</h2> + +<p> + Auto devices use {@link android.media.session.MediaSession} objects to pass playback control + commands to an app that is providing audio services. Your audio app must create an instance of + this object to pass to the dashboard device and implement callback methods to enable remote + control of audio playback. +</p> + +<h3 id="registering_mediasession">Register a media session</h3> + +<p>An Auto device using your app as audio service needs to obtain a {@link +android.media.session.MediaSession} object from your app. The Auto device uses the session object +to send playback commands requested by the Auto user back to your app.</p> + +<p>When you initialize your browser service, you register that session object with your {@link +android.service.media.MediaBrowserService} by calling the {@link +android.service.media.MediaBrowserService#setSessionToken setSessionToken()} method. This step +allows clients such as an Auto device to retrieve that object by calling your browser service's +{@link android.service.media.MediaBrowserService#getSessionToken getSessionToken()} method.</p> + +<p>In your browser service's {@link +android.service.media.MediaBrowserService#onCreate() onCreate()} method, +create a {@link android.media.session.MediaSession}. You can then query +the {@link android.media.session.MediaSession} to get its token, and register +the token with your browser service:</p> + +<pre> +public void onCreate() { + super.onCreate(); + + ... + // Start a new MediaSession + MediaSession mSession = new MediaSession(this, "session tag"); + setSessionToken(mSession.getSessionToken()); + + // Set a callback object to handle play control requests, which + // implements MediaSession.Callback + mSession.setCallback(new MyMediaSessionCallback()); + + ... +</pre> + +<p> + When you create the media session object, you set a callback object that is used to handle + playback control requests. You create this callback object by providing an implementation of the + {@link android.media.session.MediaSession.Callback} class for your app. The next section + discusses how to implement this object. +</p> + + +<h3 id="playback-commands">Implement play commands</h3> + +<p>When an Auto device requests playback of an audio track from your app, it uses the +{@link android.media.session.MediaSession.Callback} class from your app's +{@link android.media.session.MediaSession} object, which it obtained from your app's +media browse service. When an Auto user wants to play content or control content playback, +such as pausing play or skipping to the next track, Auto invokes one +of the callback object's methods.</p> + +<p>To handle content playback, your app must extend the abstract {@link +android.media.session.MediaSession.Callback} class and implement the methods +that your app supports. The most important callback methods are as follows:</p> + +<dl> + +<dt>{@link android.media.session.MediaSession.Callback#onPlay onPlay()}</dt> +<dd>Invoked if the user chooses play without choosing a specific item. Your +app should play its default content. If playback was paused with +{@link android.media.session.MediaSession.Callback#onPause onPause()}, your +app should resume playback.</dd> + +<dt>{@link android.media.session.MediaSession.Callback#onPlayFromMediaId +onPlayFromMediaId()}</dt> +<dd>Invoked when the user chooses to play a specific item. The method is passed +the item's media ID, which you assigned to the item in the content +hierarchy.</dd> + +<dt>{@link android.media.session.MediaSession.Callback#onPlayFromSearch +onPlayFromSearch()}</dt> +<dd>Invoked when the user chooses to play from a search query. The app should +make an appropriate choice based on the passed search string.</dd> + +<dt>{@link android.media.session.MediaSession.Callback#onPause onPause()}</dt> +<dd>Pause playback.</dd> + +<dt>{@link android.media.session.MediaSession.Callback#onSkipToNext +onSkipToNext()}</dt> +<dd>Skip to the next item.</dd> + +<dt>{@link android.media.session.MediaSession.Callback#onSkipToPrevious +onSkipToPrevious()}</dt> +<dd>Skip to the previous item.</dd> + +<dt>{@link android.media.session.MediaSession.Callback#onStop onStop()}</dt> +<dd>Stop playback.</dd> + +</dl> + +<p>Your app should override these methods to provide any desired functionality. +In some cases you might not implement a method if it is not supported by your app. +For example, if your app plays a live stream (such as a sports +broadcast), the skip to next function might not make sense. In that case, you +could simply use the default implementation of +{@link android.media.session.MediaSession.Callback#onSkipToNext +onSkipToNext()}.</p> + +<p>When your app receives a request to play content, it should play audio the same way it +would in a non-Auto situation (as if the user was listening through a device speaker +or connected headphones). The audio content is automatically sent to the dashboard system +to be played over the car's speakers.</p> + +<p>For more information about playing audio content, see +<a href="{@docRoot}guide/topics/media/mediaplayer.html">Media Playback</a>, +<a href="{@docRoot}training/managing-audio/index.html">Managing Audio Playback</a>, and +<a href="{@docRoot}guide/topics/media/exoplayer.html">ExoPlayer</a>. + + +(for example, by using a {@link +android.media.MediaPlayer} or <a +href="{@docRoot}guide/topics/media/exoplayer.html">ExoPlayer</a>). If the phone +is connected to an Auto device, .</p> diff --git a/docs/html/training/training_toc.cs b/docs/html/training/training_toc.cs index f246a0f..791aef6 100644 --- a/docs/html/training/training_toc.cs +++ b/docs/html/training/training_toc.cs @@ -938,6 +938,7 @@ include the action bar on devices running Android 2.1 or higher." </li> <!-- End: Building for TV --> + <!-- Start: Building for Auto --> <li class="nav-section"> <div class="nav-section-header"> @@ -953,6 +954,11 @@ include the action bar on devices running Android 2.1 or higher." with Auto devices."> Getting Started with Auto</a> </li> + <li> + <a href="<?cs var:toroot ?>training/auto/audio/index.html" + description="How to extend audio apps to play content on Auto devices."> + Playing Audio for Auto</a> + </li> </ul> </li> <!-- End: Building for Auto --> |