454 lines
21 KiB
Plaintext
454 lines
21 KiB
Plaintext
page.title=Media Route Provider
|
|
page.tags="mediarouteprovider","mediacontrolintent"
|
|
@jd:body
|
|
|
|
<div id="qv-wrapper">
|
|
<div id="qv">
|
|
<h2>In this document</h2>
|
|
<ol>
|
|
<li><a href="#overview">Overview</a>
|
|
<ol>
|
|
<li><a href="#dist">Distribution of route providers</a></li>
|
|
<li><a href="#playback-types">Types of playback</a></li>
|
|
<li><a href="#mr-packages">Media router packages</a></li>
|
|
</ol>
|
|
</li>
|
|
<li><a href="#provider-service">Creating a Provider Service</a></li>
|
|
<li><a href="#route-caps">Specifying Route Capabilities</a>
|
|
<ol>
|
|
<li><a href="#route-cat">Route categories</a></li>
|
|
<li><a href="#media-types">Media types and protocols</a></li>
|
|
<li><a href="#playback-ctrls">Playback controls</a></li>
|
|
<li><a href="#mrpd">MediaRouteProviderDescriptor</a></li>
|
|
</ol>
|
|
</li>
|
|
<li><a href="#ctrl-routes">Controlling Routes</a></li>
|
|
</ol>
|
|
<h2>Key Classes</h2>
|
|
<ol>
|
|
<li>{@link android.support.v7.media.MediaRouteProvider}</li>
|
|
<li>{@link android.support.v7.media.MediaRouteProviderDescriptor}</li>
|
|
<li>{@link android.support.v7.media.MediaRouteProvider.RouteController RouteController}</li>
|
|
</ol>
|
|
<h2>Related Samples</h2>
|
|
<ol>
|
|
<li><a href="{@docRoot}samples/MediaRouter/index.html">MediaRouter</a></li>
|
|
</ol>
|
|
</div>
|
|
</div>
|
|
|
|
<p>Users want to play media content from their Android devices bigger, brighter, and louder on
|
|
connected playback devices such as televisions, stereos,
|
|
and home theater equipment. As a manufacturer of these devices, allowing Android users to
|
|
instantly show a picture, play a song, or share a video for friends and family using your product
|
|
can make it much more compelling and engaging.</p>
|
|
|
|
<p>The Android media router framework allows manufacturers to enable playback on their devices
|
|
through a standardized interface called a {@link android.support.v7.media.MediaRouteProvider}.
|
|
A route provider defines a common interface for playing media on a receiver device, making it
|
|
possible to play media on your equipment from any Android application that supports media
|
|
routes.</p>
|
|
|
|
<p>This guide discusses how to create a media route provider for a receiver device and make it
|
|
available to other media playback applications that run on Android.</p>
|
|
|
|
<h2 id="overview">Overview</h2>
|
|
|
|
<p>The Android media router framework enables media app developers and media playback device
|
|
manufacturers to connect through a common API and common user interface. App developers that
|
|
implement a {@link android.support.v7.media.MediaRouter} interface can then connect to the
|
|
framework and play content to devices that participate in the media router framework. Media
|
|
playback device manufacturers can participate in the framework by publishing a {@link
|
|
android.support.v7.media.MediaRouteProvider} that allows other applications to connect to and
|
|
play media on the receiver devices. Figure 1 illustrates how an app connects to a receiving
|
|
device through the media router framework.</p>
|
|
|
|
<img src="{@docRoot}images/mediarouter/media-route-provider-framework.png" alt="" id="figure1"/>
|
|
<p class="img-caption">
|
|
<strong>Figure 1.</strong> Overview of how media route provider classes provide communication
|
|
from a media app to a receiver device.
|
|
</p>
|
|
|
|
<p>When you build a media route provider for your receiver device, the provider serves the
|
|
following purposes:</p>
|
|
|
|
<ul>
|
|
<li>Describe and publish the capabilities of the receiver device so other apps can discover it
|
|
and use its playback features.</li>
|
|
<li>Wrap the programming interface of the receiver device and its communication
|
|
transport mechanisms to make the device compatible with the media router framework.</li>
|
|
</ul>
|
|
|
|
|
|
<h3 id="dist">Distribution of route providers</h3>
|
|
|
|
<p>A media route provider is distributed as part of an Android app. Your route provider can be
|
|
made available to other apps by extending
|
|
{@link android.support.v7.media.MediaRouteProviderService} or wrapping your implementation of
|
|
{@link android.support.v7.media.MediaRouteProvider} with your own service and declaring an intent
|
|
filter for the media route provider. These steps allow other apps to discover and make use of
|
|
your media route.</p>
|
|
|
|
<p>
|
|
<strong>Note:</strong> The app containing the media route provider can also include a
|
|
<a href="{@docRoot}guide/topics/media/mediarouter.html">MediaRouter</a> interface to the
|
|
route provider, but this is not required.
|
|
</p>
|
|
|
|
|
|
<h3 id="playback-types">Types of playback</h3>
|
|
|
|
<p>There are two main types of playback supported by the media router framework. A media route
|
|
provider can support one or both types of playback, depending on the capabilities of your playback
|
|
equipment and the functionality you want to support:</p>
|
|
|
|
<ul>
|
|
<li><strong>Remote Playback</strong> — This approach uses the receiver device to handle the
|
|
content data retrieval, decoding, and playback, while an Android device in the user's hand is
|
|
used as a remote control. This approach is used by Android apps that support
|
|
<a href="https://developers.google.com/cast/">Google Cast</a>.</li>
|
|
<li><strong>Secondary Output</strong> — With this approach, the Android media application
|
|
retrieves, renders and streams video or music directly to the receiver device. This approach is
|
|
used to support Wireless Display output on Android.</li>
|
|
</ul>
|
|
|
|
|
|
<h3 id="mr-packages">Media router packages</h3>
|
|
|
|
<p>
|
|
The media router APIs are provided as part of the Android Support Library version 18 and higher,
|
|
in the <a href="{@docRoot}tools/support-library/features.html#v7-mediarouter">v7-mediarouter</a>
|
|
support library. You should use the classes in the
|
|
{@link android.support.v7.media} package for media route provider functions.
|
|
These APIs are compatible with devices running Android 2.1 (API level 7) and higher.
|
|
</p>
|
|
|
|
<p class="caution">
|
|
<strong>Caution:</strong> There is another set of media router APIs provided in the
|
|
{@link android.media} class package that have been superseded by the
|
|
<a href="{@docRoot}tools/support-library/features.html#v7-mediarouter">v7-mediarouter</a>
|
|
support library. You <em>should not</em> use the {@link android.media} classes for
|
|
implementing media route provider functions.
|
|
</p>
|
|
|
|
<p>In order to use the {@link android.support.v7.media} media router classes, you
|
|
must add the <a href="{@docRoot}tools/support-library/features.html#v7-mediarouter"
|
|
>v7-mediarouter support library package</a> to your app development project. For more
|
|
information on adding support libraries to your app development project, see
|
|
<a href="{@docRoot}tools/support-library/setup.html">Support Library Setup</a>.
|
|
</p>
|
|
|
|
|
|
<h2 id="provider-service">Creating a Provider Service</h2>
|
|
|
|
<p>The media router framework must be able to discover and connect to your media route provider
|
|
to allow other applications to use your route. In order to do this, the media router framework
|
|
looks for apps that declare a media route provider intent action. When another app wants to
|
|
connect to your provider, the framework must be able to invoke and connect to it, so your provider
|
|
must be encapsulated in a {@link android.app.Service}.</p>
|
|
|
|
<p>The following example code shows the declaration of a media route provider service and the
|
|
intent filter in a manifest, which allows it to be discovered and used by the media router
|
|
framework:</p>
|
|
|
|
<pre>
|
|
<service android:name=".provider.SampleMediaRouteProviderService"
|
|
android:label="@string/sample_media_route_provider_service"
|
|
android:process=":mrp">
|
|
<intent-filter>
|
|
<action android:name="android.media.MediaRouteProviderService" />
|
|
</intent-filter>
|
|
</service>
|
|
</pre>
|
|
|
|
<p>This manifest example declares a service that wraps the actual media route provider classes.
|
|
The Android media router framework provides the
|
|
{@link android.support.v7.media.MediaRouteProviderService} class for use as a service wrapper for
|
|
media route providers. The following example code demonstrates how to use this wrapper
|
|
class:</p>
|
|
|
|
<pre>
|
|
public class SampleMediaRouteProviderService extends MediaRouteProviderService {
|
|
|
|
@Override
|
|
public MediaRouteProvider onCreateMediaRouteProvider() {
|
|
return new SampleMediaRouteProvider(this);
|
|
}
|
|
}
|
|
</pre>
|
|
|
|
|
|
<h2 id="route-caps">Specifying Route Capabilities</h2>
|
|
|
|
<p>Apps connecting to the media router framework can discover your media route through your
|
|
app's manifest declarations, but they also need to know the capabilities of the media routes you
|
|
are providing. Media routes can be of different types and have different features, and other apps
|
|
need to be able to discover these details to determine if they are compatible with your route.</p>
|
|
|
|
<p>The media router framework allows you to define and publish the capabilities of your media
|
|
route through {@link android.content.IntentFilter} objects, {@link
|
|
android.support.v7.media.MediaRouteDescriptor} objects and a {@link
|
|
android.support.v7.media.MediaRouteProviderDescriptor}. This section explains how to use these
|
|
classes to publish the details of your media route for other apps.</p>
|
|
|
|
|
|
<h3 id="route-cat">Route categories</h3>
|
|
|
|
<p>As part of the programmatic description of your media route provider, you must specify
|
|
whether your provider supports remote playback, secondary output, or both. These are the route
|
|
categories provided by the media router framework:</p>
|
|
|
|
<ul>
|
|
<li>{@link android.support.v7.media.MediaControlIntent#CATEGORY_LIVE_AUDIO CATEGORY_LIVE_AUDIO}
|
|
— Output of audio to a secondary output device, such as a wireless-enabled music system.
|
|
</li>
|
|
<li>{@link android.support.v7.media.MediaControlIntent#CATEGORY_LIVE_VIDEO CATEGORY_LIVE_VIDEO}
|
|
— Output of video to a secondary output device, such as Wireless Display devices.</li>
|
|
<li>{@link android.support.v7.media.MediaControlIntent#CATEGORY_REMOTE_PLAYBACK
|
|
CATEGORY_REMOTE_PLAYBACK} — Play video or audio on a separate device which handles media
|
|
retrieval, decoding, and playback, such as
|
|
<a href="https://www.google.com/url?q=http://www.google.com/chromecast">Chromecast</a> devices.
|
|
</li>
|
|
</ul>
|
|
|
|
<p>In order to include these settings in a description of your media route, you insert them into
|
|
an {@link android.content.IntentFilter} object, which you later add to a
|
|
{@link android.support.v7.media.MediaRouteDescriptor} object:</p>
|
|
|
|
<pre>
|
|
public final class SampleMediaRouteProvider extends MediaRouteProvider {
|
|
private static final ArrayList<IntentFilter> CONTROL_FILTERS_BASIC;
|
|
static {
|
|
IntentFilter videoPlayback = new IntentFilter();
|
|
<strong>videoPlayback.addCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK);</strong>
|
|
CONTROL_FILTERS_BASIC = new ArrayList<IntentFilter>();
|
|
CONTROL_FILTERS_BASIC.add(videoPlayback);
|
|
}
|
|
}
|
|
|
|
</pre>
|
|
|
|
<p>If you specify the {@link android.support.v7.media.MediaControlIntent#CATEGORY_REMOTE_PLAYBACK
|
|
CATEGORY_REMOTE_PLAYBACK} intent, you must also define what media types and
|
|
playback controls are supported by your media route provider. The next section describes how to
|
|
specify these settings for your device.</p>
|
|
|
|
|
|
<h3 id="media-types">Media types and protocols</h3>
|
|
|
|
<p>A media route provider for a remote playback device must specify the media types and transfer
|
|
protocols it supports. You specify these settings using the {@link android.content.IntentFilter}
|
|
class and the {@link android.content.IntentFilter#addDataScheme addDataScheme()} and
|
|
{@link android.content.IntentFilter#addDataType addDataType()} methods of that object. The
|
|
following code snippet demonstrates how to define an intent filter for supporting remote video
|
|
playback using http, https, and Real Time Streaming Protocol (RTSP):</p>
|
|
|
|
<pre>
|
|
public final class SampleMediaRouteProvider extends MediaRouteProvider {
|
|
|
|
private static final ArrayList<IntentFilter> CONTROL_FILTERS_BASIC;
|
|
|
|
static {
|
|
IntentFilter videoPlayback = new IntentFilter();
|
|
videoPlayback.addCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK);
|
|
videoPlayback.addAction(MediaControlIntent.ACTION_PLAY);
|
|
videoPlayback.addDataScheme("http");
|
|
videoPlayback.addDataScheme("https");
|
|
videoPlayback.addDataScheme("rtsp");
|
|
addDataTypeUnchecked(videoPlayback, "video/*");
|
|
CONTROL_FILTERS_BASIC = new ArrayList<IntentFilter>();
|
|
CONTROL_FILTERS_BASIC.add(videoPlayback);
|
|
}
|
|
...
|
|
|
|
private static void addDataTypeUnchecked(IntentFilter filter, String type) {
|
|
try {
|
|
filter.addDataType(type);
|
|
} catch (MalformedMimeTypeException ex) {
|
|
throw new RuntimeException(ex);
|
|
}
|
|
}
|
|
}
|
|
|
|
</pre>
|
|
|
|
|
|
<h3 id="playback-ctrls">Playback controls</h3>
|
|
|
|
<p>A media route provider that offers remote playback must specify the types of media controls
|
|
it supports. These are the general types of control that media routes can provide:</p>
|
|
|
|
<ul>
|
|
<li><strong>Playback controls</strong>, such as play, pause, rewind, and fast-forward.</li>
|
|
<li><strong>Queuing features</strong>, which allow the sending app to add and remove items
|
|
from a playlist which is maintained by the receiver device.</li>
|
|
<li><strong>Session features</strong>, which prevent sending apps from interfering with each
|
|
other by having the receiver device provide a session id to the requesting app and then checking
|
|
that id with each subsequent playback control request.</li>
|
|
</ul>
|
|
|
|
<p>The following code example demonstrates how to construct an intent filter for supporting
|
|
basic media route playback controls:</p>
|
|
|
|
<pre>
|
|
public final class SampleMediaRouteProvider extends MediaRouteProvider {
|
|
private static final ArrayList<IntentFilter> CONTROL_FILTERS_BASIC;
|
|
static {
|
|
...
|
|
IntentFilter playControls = new IntentFilter();
|
|
playControls.addCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK);
|
|
playControls.addAction(MediaControlIntent.ACTION_SEEK);
|
|
playControls.addAction(MediaControlIntent.ACTION_GET_STATUS);
|
|
playControls.addAction(MediaControlIntent.ACTION_PAUSE);
|
|
playControls.addAction(MediaControlIntent.ACTION_RESUME);
|
|
playControls.addAction(MediaControlIntent.ACTION_STOP);
|
|
CONTROL_FILTERS_BASIC = new ArrayList<IntentFilter>();
|
|
CONTROL_FILTERS_BASIC.add(videoPlayback);
|
|
CONTROL_FILTERS_BASIC.add(playControls);
|
|
}
|
|
...
|
|
}
|
|
</pre>
|
|
|
|
<p>For more information about the available playback control intents, see the
|
|
{@link android.support.v7.media.MediaControlIntent} class.</p>
|
|
|
|
|
|
<h3 id="mrpd">MediaRouteProviderDescriptor</h3>
|
|
|
|
<p>After defining the capabilities of your media route using {@link
|
|
android.content.IntentFilter} objects, you can then create a descriptor object for publishing to
|
|
the Android media router framework. This descriptor object contains the specifics of your media
|
|
route's capabilities so that other applications can determine how to interact with your media
|
|
route.</p>
|
|
|
|
<p>The following example code demonstrates how to add the previously created intent filters to a
|
|
{@link android.support.v7.media.MediaRouteProviderDescriptor} and set the descriptor for use by
|
|
the media router framework:</p>
|
|
|
|
<pre>
|
|
public SampleMediaRouteProvider(Context context) {
|
|
super(context);
|
|
publishRoutes();
|
|
}
|
|
|
|
private void publishRoutes() {
|
|
Resources r = getContext().getResources();
|
|
// Create a route descriptor using previously created IntentFilters
|
|
MediaRouteDescriptor routeDescriptor = new MediaRouteDescriptor.Builder(
|
|
VARIABLE_VOLUME_BASIC_ROUTE_ID,
|
|
r.getString(R.string.variable_volume_basic_route_name))
|
|
.setDescription(r.getString(R.string.sample_route_description))
|
|
.addControlFilters(CONTROL_FILTERS_BASIC)
|
|
.setPlaybackStream(AudioManager.STREAM_MUSIC)
|
|
.setPlaybackType(MediaRouter.RouteInfo.PLAYBACK_TYPE_REMOTE)
|
|
.setVolumeHandling(MediaRouter.RouteInfo.PLAYBACK_VOLUME_VARIABLE)
|
|
.setVolumeMax(VOLUME_MAX)
|
|
.setVolume(mVolume)
|
|
.build();
|
|
// Add the route descriptor to the provider descriptor
|
|
MediaRouteProviderDescriptor providerDescriptor =
|
|
new MediaRouteProviderDescriptor.Builder()
|
|
.addRoute(routeDescriptor)
|
|
.build();
|
|
|
|
// Publish the descriptor to the framework
|
|
setDescriptor(providerDescriptor);
|
|
}
|
|
</pre>
|
|
|
|
<p>For more information on the available descriptor settings, see the reference documentation
|
|
for {@link android.support.v7.media.MediaRouteDescriptor} and {@link
|
|
android.support.v7.media.MediaRouteProviderDescriptor}.</p>
|
|
|
|
|
|
<h2 id="ctrl-routes">Controlling Routes</h2>
|
|
|
|
<p>When an application connects to your media route provider, the provider receives playback
|
|
commands through the media router framework sent to your route by other apps. To handle these
|
|
requests, you must provide an implementation of a {@link
|
|
android.support.v7.media.MediaRouteProvider.RouteController} class, which processes the commands
|
|
and handles the actual communication to your receiver device.</p>
|
|
|
|
<p>The media router framework calls the {@link
|
|
android.support.v7.media.MediaRouteProvider#onCreateRouteController onCreateRouteController()}
|
|
method of your route provider to obtain an instance of this class and then routes requests to it.
|
|
These are the key methods of the {@link
|
|
android.support.v7.media.MediaRouteProvider.RouteController} class, which you must implement for
|
|
your media route provider:</p>
|
|
|
|
<ul>
|
|
<li>{@link android.support.v7.media.MediaRouteProvider.RouteController#onSelect onSelect()}
|
|
— Called when an application selects your route for playback. You use this method to do
|
|
any preparation work that may be required before media playback begins.</li>
|
|
<li>{@link android.support.v7.media.MediaRouteProvider.RouteController#onControlRequest
|
|
onControlRequest()} — Sends specific playback commands to the receiving device.</li>
|
|
<li>{@link android.support.v7.media.MediaRouteProvider.RouteController#onSetVolume
|
|
onSetVolume()} — Sends a request to the receiving device to set the playback volume to a
|
|
specific value.</li>
|
|
<li>{@link android.support.v7.media.MediaRouteProvider.RouteController#onUpdateVolume
|
|
onUpdateVolume()} — Sends a request to the receiving device to modify the playback
|
|
volume by a specified amount.</li>
|
|
<li>{@link android.support.v7.media.MediaRouteProvider.RouteController#onUnselect
|
|
onUnselect()} — Called when an application unselects a route.</li>
|
|
<li>{@link android.support.v7.media.MediaRouteProvider.RouteController#onRelease onRelease()}
|
|
— Called when the route is no longer needed by the framework, allowing it to free its
|
|
resources.</li>
|
|
</ul>
|
|
|
|
<p>All playback control requests, except for volume changes, are directed to the {@link
|
|
android.support.v7.media.MediaRouteProvider.RouteController#onControlRequest onControlRequest()}
|
|
method. Your implementation of this method must parse the control requests and respond to them
|
|
appropriately. Here is an example implementation of this method which processes commands for a
|
|
remote playback media route:</p>
|
|
|
|
<pre>
|
|
private final class SampleRouteController extends
|
|
MediaRouteProvider.RouteController {
|
|
...
|
|
|
|
@Override
|
|
public boolean onControlRequest(Intent intent, ControlRequestCallback callback) {
|
|
|
|
String action = intent.getAction();
|
|
|
|
if (intent.hasCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK)) {
|
|
boolean success = false;
|
|
if (action.equals(MediaControlIntent.ACTION_PLAY)) {
|
|
success = handlePlay(intent, callback);
|
|
} else if (action.equals(MediaControlIntent.ACTION_ENQUEUE)) {
|
|
success = handleEnqueue(intent, callback);
|
|
} else if (action.equals(MediaControlIntent.ACTION_REMOVE)) {
|
|
success = handleRemove(intent, callback);
|
|
} else if (action.equals(MediaControlIntent.ACTION_SEEK)) {
|
|
success = handleSeek(intent, callback);
|
|
} else if (action.equals(MediaControlIntent.ACTION_GET_STATUS)) {
|
|
success = handleGetStatus(intent, callback);
|
|
} else if (action.equals(MediaControlIntent.ACTION_PAUSE)) {
|
|
success = handlePause(intent, callback);
|
|
} else if (action.equals(MediaControlIntent.ACTION_RESUME)) {
|
|
success = handleResume(intent, callback);
|
|
} else if (action.equals(MediaControlIntent.ACTION_STOP)) {
|
|
success = handleStop(intent, callback);
|
|
} else if (action.equals(MediaControlIntent.ACTION_START_SESSION)) {
|
|
success = handleStartSession(intent, callback);
|
|
} else if (action.equals(MediaControlIntent.ACTION_GET_SESSION_STATUS)) {
|
|
success = handleGetSessionStatus(intent, callback);
|
|
} else if (action.equals(MediaControlIntent.ACTION_END_SESSION)) {
|
|
success = handleEndSession(intent, callback);
|
|
}
|
|
|
|
Log.d(TAG, mSessionManager.toString());
|
|
return success;
|
|
}
|
|
return false;
|
|
}
|
|
...
|
|
}
|
|
</pre>
|
|
|
|
<p>It is important to understand that the {@link
|
|
android.support.v7.media.MediaRouteProvider.RouteController} class is intended to act as a wrapper
|
|
for the API to your media playback equipment. The implementation of the methods in this class is
|
|
entirely dependent on the programmatic interface provided by your receiving device.</p>
|