674 lines
28 KiB
Plaintext
674 lines
28 KiB
Plaintext
page.title=Providing Audio Playback for Auto
|
||
page.tags="auto", "car", "automotive", "audio"
|
||
page.article=true
|
||
|
||
page.metaDescription=Learn how to extend your audio apps for use in Android Auto devices.
|
||
page.image=auto/images/assets/icons/media_app_playback.png
|
||
|
||
@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>
|
||
<li><a href="#support_voice">Support Voice Actions</a></li>
|
||
</ol>
|
||
|
||
<h2>Related Samples</h2>
|
||
|
||
<ul>
|
||
<li><a href="{@docRoot}samples/MediaBrowserService/index.html">
|
||
MediaBrowserService</a></li>
|
||
<li><a href="//github.com/googlesamples/android-UniversalMusicPlayer">Universal Media
|
||
Player</a></li>
|
||
</ul>
|
||
|
||
<h2>See Also</h2>
|
||
|
||
<ul>
|
||
<li>
|
||
<a href="{@docRoot}shareables/auto/AndroidAuto-audio-apps.pdf">
|
||
User Experience Guidelines: Audio 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 simple, yet customizable 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 minimize 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-audio-apps.pdf">
|
||
Auto Audio 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) {
|
||
|
||
// To ensure you are not allowing any arbitrary app to browse your app's
|
||
// contents, you need to check the origin:
|
||
if (!PackageValidator.isCallerAllowed(this, clientPackageName, clientUid)) {
|
||
// If the request comes from an untrusted package, return null.
|
||
// No further calls will be made to other media browsing methods.
|
||
LogHelper.w(TAG, "OnGetRoot: IGNORING request from untrusted package "
|
||
+ clientPackageName);
|
||
return null;
|
||
}
|
||
if (ANDROID_AUTO_PACKAGE_NAME.equals(clientPackageName)) {
|
||
// Optional: if your app needs to adapt ads, music library or anything
|
||
// else that needs to run differently when connected to the car, this
|
||
// is where you should handle it.
|
||
}
|
||
return new BrowserRoot(MEDIA_ID_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>
|
||
|
||
<p class="note">
|
||
<strong>Note:</strong> Google Play requires your app not to play music immediately when it
|
||
launches. For more information on this and other requirements, see
|
||
<a href="{@docRoot}distribute/essentials/quality/auto.html">Auto App Quality</a>.
|
||
</p>
|
||
|
||
<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>.</p>
|
||
|
||
|
||
<h2 id="support_voice">Support Voice Actions</h2>
|
||
|
||
<p>To reduce driver distractions, you can add voice actions in your audio playback app. With voice
|
||
action support, users can launch your app and play audio by providing voice input on Auto screens.
|
||
If your audio playback app is already active and the user says
|
||
<i>“Play a song”</i>, the system starts playing music without requiring the user to look at or touch
|
||
the screen.</p>
|
||
|
||
<h3 id="enable_playback">Enable your app to handle audio playback requests</h3>
|
||
|
||
<p>Enable your audio app to launch with a voice command such as <i>"Play [search query] on
|
||
[your app name]"</i> by adding the following entry in your manifest:</p>
|
||
|
||
<pre>
|
||
<activity>
|
||
<intent-filter>
|
||
<action android:name=
|
||
"android.media.action.MEDIA_PLAY_FROM_SEARCH" />
|
||
<category android:name=
|
||
"android.intent.category.DEFAULT" />
|
||
</intent-filter>
|
||
</activity>
|
||
</pre>
|
||
|
||
<p>When the user says <i>“Play music on [your app name]”</i> on an Auto screen, Auto
|
||
attempts to launch your app and play audio by calling your app’s
|
||
<a href="{@docRoot}reference/android/media/session/MediaSession.Callback.html#onPlayFromSearch(java.lang.String, android.os.Bundle)"><code>MediaSession.Callback.onPlayFromSearch()</code></a>
|
||
method. If the user has not specified criteria such as a track name or music genre, the
|
||
<a href="{@docRoot}reference/android/media/session/MediaSession.Callback.html#onPlayFromSearch(java.lang.String, android.os.Bundle)"><code>MediaSession.Callback.onPlayFromSearch()</code></a>
|
||
method receives an empty query parameter. Your app should respond by immediately playing audio, such
|
||
as a song from a random queue or the most recent playlist.
|
||
</p>
|
||
|
||
<h3 id="parse_voice">Parse the voice query to build the playback queue</h3>
|
||
|
||
<p>When a user searches for a specific criteria, such as <i>“Play jazz on [your app name]”</i>
|
||
or <i>“Listen to [song title]”</i>, the
|
||
<a href="{@docRoot}reference/android/media/session/MediaSession.Callback.html#onPlayFromSearch(java.lang.String, android.os.Bundle)"><code>onPlayFromSearch()</code></a>
|
||
callback method receives the voice search results in the query parameter and an extras bundle. For
|
||
more information on how to handle search queries to play audio content, see
|
||
<a href="https://developer.android.com/guide/components/intents-common.html#PlaySearch">Play music
|
||
based on a search query</a>.
|
||
</p>
|
||
|
||
<p>To parse the voice search query to play back audio content in your app, follow these steps:</p>
|
||
|
||
<ol>
|
||
<li>Use the extras bundle and search query string returned from the voice search to filter
|
||
results.</li>
|
||
<li>Build the audio content queue based on these results.</li>
|
||
<li>Play the audio content.</li>
|
||
</ol>
|
||
|
||
<p>The
|
||
<a href="{@docRoot}reference/android/media/session/MediaSession.Callback.html#onPlayFromSearch(java.lang.String, android.os.Bundle)"><code>onPlayFromSearch()</code></a>
|
||
method takes an extras parameter with more detailed information from the voice search.
|
||
These extras help you find the audio content in your app for playback. If the search results are
|
||
unable to provide this data, you can implement logic to parse the raw search query and play the
|
||
appropriate tracks based on the query.
|
||
</p>
|
||
|
||
<p>The following extras are supported in Android Auto:</p>
|
||
|
||
<ul>
|
||
<li><a href="{@docRoot}reference/android/provider/MediaStore.html#EXTRA_MEDIA_ALBUM"><code>android.intent.extra.album</code></a></li>
|
||
<li><a href="{@docRoot}reference/android/provider/MediaStore.html#EXTRA_MEDIA_ARTIST"><code>android.intent.extra.artist</code></a></li>
|
||
<li><a href="{@docRoot}reference/android/provider/MediaStore.html#EXTRA_MEDIA_GENRE"><code>android.intent.extra.genre</code></a></li>
|
||
<li><a href="{@docRoot}reference/android/provider/MediaStore.html#EXTRA_MEDIA_PLAYLIST"><code>android.intent.extra.playlist</code></a></li>
|
||
<li><a href="{@docRoot}reference/android/provider/MediaStore.html#EXTRA_MEDIA_TITLE"><code>android.intent.extra.title</code></a></li>
|
||
</ul>
|
||
|
||
<p>The following snippet shows how to override the
|
||
<a href="{@docRoot}reference/android/media/session/MediaSession.Callback.html#onPlayFromSearch(java.lang.String, android.os.Bundle)"><code>onPlayFromSearch()</code></a>
|
||
method in your
|
||
<a href="{@docRoot}reference/android/media/session/MediaSession.Callback.html"><code>MediaSession.Callback</code></a>
|
||
implementation to handle the search query and extras for playing audio content in your app:
|
||
</p>
|
||
|
||
<pre>
|
||
@Override
|
||
public void onPlayFromSearch(String query, Bundle extras) {
|
||
if (TextUtils.isEmpty(query)) {
|
||
// The user provided generic string e.g. 'Play music'
|
||
// Build appropriate playlist queue
|
||
} else {
|
||
// Build a queue based on songs that match "query" or "extras" param
|
||
String mediaFocus = extras.getString(MediaStore.EXTRA_MEDIA_FOCUS);
|
||
if (TextUtils.equals(mediaFocus,
|
||
MediaStore.Audio.Artists.ENTRY_CONTENT_TYPE)) {
|
||
isArtistFocus = true;
|
||
artist = extras.getString(MediaStore.EXTRA_MEDIA_ARTIST);
|
||
} else if (TextUtils.equals(mediaFocus,
|
||
MediaStore.Audio.Albums.ENTRY_CONTENT_TYPE)) {
|
||
isAlbumFocus = true;
|
||
album = extras.getString(MediaStore.EXTRA_MEDIA_ALBUM);
|
||
}
|
||
|
||
// Implement additional "extras" param filtering
|
||
}
|
||
|
||
// Implement your logic to retrieve the queue
|
||
if (isArtistFocus) {
|
||
result = searchMusicByArtist(artist);
|
||
} else if (isAlbumFocus) {
|
||
result = searchMusicByAlbum(album);
|
||
}
|
||
|
||
if (result == null) {
|
||
// No focus found, search by query for song title
|
||
result = searchMusicBySongTitle(query);
|
||
}
|
||
|
||
if (result != null && !result.isEmpty()) {
|
||
// Immediately start playing from the beginning of the search results
|
||
// Implement your logic to start playing music
|
||
playMusic(result);
|
||
} else {
|
||
// Handle no queue found. Stop playing if the app
|
||
// is currently playing a song
|
||
}
|
||
}
|
||
</pre>
|
||
|
||
<p class="note">
|
||
<strong>Note:</strong> To minimize driver distractions, immediately initiate audio content
|
||
playback in the
|
||
<a href="{@docRoot}reference/android/media/session/MediaSession.Callback.html#onPlayFromSearch(java.lang.String, android.os.Bundle)"><code>onPlayFromSearch()</code></a>
|
||
method when you have generated the audio content queue based on the user's request.
|
||
</p>
|
||
|
||
<p>For a more detailed example on how to implement voice search to play audio content in your app,
|
||
see the
|
||
<a href="//github.com/googlesamples/android-UniversalMusicPlayer/">Universal Media Player</a>
|
||
sample.
|
||
</p>
|
||
|
||
<h3 id="implement_playback_controls">Implement playback control actions</h3>
|
||
|
||
<p>To provide a hands-free experience while users drive and listen to audio content in Android Auto,
|
||
your app should allow users to control audio content playback with voice actions. When users speak
|
||
commands such as <i>“Next song”</i>, <i>“Pause music”</i>, or <i>“Resume music”</i>, the system
|
||
triggers the corresponding callback method where you implement the playback control action.
|
||
</p>
|
||
|
||
<p>To provide voice-enabled playback controls, first enable the hardware controls by setting these
|
||
flags in your app’s
|
||
<a href="{@docRoot}reference/android/media/session/MediaSession.html"><code>MediaSession</code></a>
|
||
object:
|
||
</p>
|
||
|
||
<pre>
|
||
mSession.setFlags(MediaSession.FLAG_HANDLES_MEDIA_BUTTONS |
|
||
MediaSession.FLAG_HANDLES_TRANSPORT_CONTROLS);
|
||
</pre>
|
||
|
||
<p>Then, implement the callback methods with the playback controls that you support in your app.
|
||
Here’s a list of voice-enabled playback controls supported by Android Auto:
|
||
</p>
|
||
|
||
<table>
|
||
<tr>
|
||
<th>Example phrase</th>
|
||
<th>Callback method</th>
|
||
</tr>
|
||
<tr>
|
||
<td><i>"Next song"</i></td>
|
||
<td><a href="{@docRoot}reference/android/media/session/MediaSession.Callback.html#onSkipToNext()"><code>onSkipToNext()</code></a></td>
|
||
</tr>
|
||
<tr>
|
||
<td><i>"Previous song"</i></td>
|
||
<td><a href="{@docRoot}reference/android/media/session/MediaSession.Callback.html#onSkipToPrevious()"><code>onSkipToPrevious()</code></a></td>
|
||
</tr>
|
||
<tr>
|
||
<td><i>"Pause music"</i></td>
|
||
<td><a href="{@docRoot}reference/android/media/session/MediaSession.Callback.html#onPause()"><code>onPause()</code></a></td>
|
||
</tr>
|
||
<tr>
|
||
<td><i>"Stop music"</i></td>
|
||
<td><a href="{@docRoot}reference/android/media/session/MediaSession.Callback.html#onStop()"><code>onStop()</code></a></td>
|
||
</tr>
|
||
<tr>
|
||
<td><i>"Resume music"</i></td>
|
||
<td><a href="{@docRoot}reference/android/media/session/MediaSession.Callback.html#onPlay()"><code>onPlay()</code></a></td>
|
||
</tr>
|
||
</table>
|
||
|
||
<p>For a more detailed example on how to implement voice-enabled playback actions in your app, see
|
||
the
|
||
<a href="//github.com/googlesamples/android-UniversalMusicPlayer/">Universal Media Player</a>
|
||
sample.
|
||
</p> |