1page.title=Media Route Provider
2page.tags="mediarouteprovider","mediacontrolintent"
3@jd:body
4
5<div id="qv-wrapper">
6  <div id="qv">
7    <h2>In this document</h2>
8    <ol>
9      <li><a href="#overview">Overview</a>
10        <ol>
11          <li><a href="#dist">Distribution of route providers</a></li>
12          <li><a href="#playback-types">Types of playback</a></li>
13          <li><a href="#mr-packages">Media router packages</a></li>
14        </ol>
15      </li>
16      <li><a href="#provider-service">Creating a Provider Service</a></li>
17      <li><a href="#route-caps">Specifying Route Capabilities</a>
18        <ol>
19          <li><a href="#route-cat">Route categories</a></li>
20          <li><a href="#media-types">Media types and protocols</a></li>
21          <li><a href="#playback-ctrls">Playback controls</a></li>
22          <li><a href="#mrpd">MediaRouteProviderDescriptor</a></li>
23        </ol>
24      </li>
25      <li><a href="#ctrl-routes">Controlling Routes</a></li>
26    </ol>
27    <h2>Key Classes</h2>
28    <ol>
29      <li>{@link android.support.v7.media.MediaRouteProvider}</li>
30      <li>{@link android.support.v7.media.MediaRouteProviderDescriptor}</li>
31      <li>{@link android.support.v7.media.MediaRouteProvider.RouteController RouteController}</li>
32    </ol>
33    <h2>Related Samples</h2>
34    <ol>
35      <li><a href="{@docRoot}samples/MediaRouter/index.html">MediaRouter</a></li>
36    </ol>
37  </div>
38</div>
39
40<p>Users want to play media content from their Android devices bigger, brighter, and louder on
41  connected playback devices such as televisions, stereos,
42  and home theater equipment. As a manufacturer of these devices, allowing Android users to
43  instantly show a picture, play a song, or share a video for friends and family using your product
44  can make it much more compelling and engaging.</p>
45
46<p>The Android media router framework allows manufacturers to enable playback on their devices
47  through a standardized interface called a {@link android.support.v7.media.MediaRouteProvider}.
48  A route provider defines a common interface for playing media on a receiver device, making it
49  possible to play media on your equipment from any Android application that supports media
50  routes.</p>
51
52<p>This guide discusses how to create a media route provider for a receiver device and make it
53  available to other media playback applications that run on Android.</p>
54
55<h2 id="overview">Overview</h2>
56
57<p>The Android media router framework enables media app developers and media playback device
58  manufacturers to connect through a common API and common user interface. App developers that
59  implement a {@link android.support.v7.media.MediaRouter} interface can then connect to the
60  framework and play content to devices that participate in the media router framework. Media
61  playback device manufacturers can participate in the framework by publishing a {@link
62  android.support.v7.media.MediaRouteProvider} that allows other applications to connect to and
63  play media on the receiver devices. Figure 1 illustrates how an app connects to a receiving
64  device through the media router framework.</p>
65
66<img src="{@docRoot}images/mediarouter/media-route-provider-framework.png" alt="" id="figure1"/>
67<p class="img-caption">
68  <strong>Figure 1.</strong> Overview of how media route provider classes provide communication
69  from a media app to a receiver device.
70</p>
71
72<p>When you build a media route provider for your receiver device, the provider serves the
73following purposes:</p>
74
75<ul>
76  <li>Describe and publish the capabilities of the receiver device so other apps can discover it
77    and use its playback features.</li>
78  <li>Wrap the programming interface of the receiver device and its communication
79    transport mechanisms to make the device compatible with the media router framework.</li>
80</ul>
81
82
83<h3 id="dist">Distribution of route providers</h3>
84
85<p>A media route provider is distributed as part of an Android app. Your route provider can be
86  made available to other apps by extending
87  {@link android.support.v7.media.MediaRouteProviderService} or wrapping your implementation of
88  {@link android.support.v7.media.MediaRouteProvider} with your own service and declaring an intent
89  filter for the media route provider. These steps allow other apps to discover and make use of
90  your media route.</p>
91
92<p>
93  <strong>Note:</strong> The app containing the media route provider can also include a
94  <a href="{@docRoot}guide/topics/media/mediarouter.html">MediaRouter</a> interface to the
95  route provider, but this is not required.
96</p>
97
98
99<h3 id="playback-types">Types of playback</h3>
100
101<p>There are two main types of playback supported by the media router framework. A media route
102  provider can support one or both types of playback, depending on the capabilities of your playback
103  equipment and the functionality you want to support:</p>
104
105<ul>
106  <li><strong>Remote Playback</strong> — This approach uses the receiver device to handle the
107    content data retrieval, decoding, and playback, while an Android device in the user's hand is
108    used as a remote control. This approach is used by Android apps that support
109    <a href="https://developers.google.com/cast/">Google Cast</a>.</li>
110  <li><strong>Secondary Output</strong> — With this approach, the Android media application
111    retrieves, renders and streams video or music directly to the receiver device. This approach is
112    used to support Wireless Display output on Android.</li>
113</ul>
114
115
116<h3 id="mr-packages">Media router packages</h3>
117
118<p>
119  The media router APIs are provided as part of the Android Support Library version 18 and higher,
120  in the <a href="{@docRoot}tools/support-library/features.html#v7-mediarouter">v7-mediarouter</a>
121  support library. You should use the classes in the
122  {@link android.support.v7.media} package for media route provider functions.
123  These APIs are compatible with devices running Android 2.1 (API level 7) and higher.
124</p>
125
126<p class="caution">
127  <strong>Caution:</strong> There is another set of media router APIs provided in the
128  {@link android.media} class package that have been superseded by the
129  <a href="{@docRoot}tools/support-library/features.html#v7-mediarouter">v7-mediarouter</a>
130  support library. You <em>should not</em> use the {@link android.media} classes for
131  implementing media route provider functions.
132</p>
133
134<p>In order to use the {@link android.support.v7.media} media router classes, you
135  must add the <a href="{@docRoot}tools/support-library/features.html#v7-mediarouter"
136  >v7-mediarouter support library package</a> to your app development project. For more
137  information on adding support libraries to your app development project, see
138  <a href="{@docRoot}tools/support-library/setup.html">Support Library Setup</a>.
139</p>
140
141
142<h2 id="provider-service">Creating a Provider Service</h2>
143
144<p>The media router framework must be able to discover and connect to your media route provider
145  to allow other applications to use your route. In order to do this, the media router framework
146  looks for apps that declare a media route provider intent action. When another app wants to
147  connect to your provider, the framework must be able to invoke and connect to it, so your provider
148  must be encapsulated in a {@link android.app.Service}.</p>
149
150<p>The following example code shows the declaration of a media route provider service and the
151  intent filter in a manifest, which allows it to be discovered and used by the media router
152  framework:</p>
153
154<pre>
155&lt;service android:name=".provider.SampleMediaRouteProviderService"
156    android:label="&#64;string/sample_media_route_provider_service"
157    android:process=":mrp"&gt;
158    &lt;intent-filter&gt;
159        &lt;action android:name="android.media.MediaRouteProviderService" /&gt;
160    &lt;/intent-filter&gt;
161&lt;/service&gt;
162</pre>
163
164<p>This manifest example declares a service that wraps the actual media route provider classes.
165  The Android media router framework provides the
166  {@link android.support.v7.media.MediaRouteProviderService} class for use as a service wrapper for
167  media route providers. The following example code demonstrates how to use this wrapper
168  class:</p>
169
170<pre>
171public class SampleMediaRouteProviderService extends MediaRouteProviderService {
172
173    &#64;Override
174    public MediaRouteProvider onCreateMediaRouteProvider() {
175        return new SampleMediaRouteProvider(this);
176    }
177}
178</pre>
179
180
181<h2 id="route-caps">Specifying Route Capabilities</h2>
182
183<p>Apps connecting to the media router framework can discover your media route through your
184  app's manifest declarations, but they also need to know the capabilities of the media routes you
185  are providing. Media routes can be of different types and have different features, and other apps
186  need to be able to discover these details to determine if they are compatible with your route.</p>
187
188<p>The media router framework allows you to define and publish the capabilities of your media
189  route through {@link android.content.IntentFilter} objects, {@link
190  android.support.v7.media.MediaRouteDescriptor} objects and a {@link
191  android.support.v7.media.MediaRouteProviderDescriptor}. This section explains how to use these
192  classes to publish the details of your media route for other apps.</p>
193
194
195<h3 id="route-cat">Route categories</h3>
196
197<p>As part of the programmatic description of your media route provider, you must specify
198  whether your provider supports remote playback, secondary output, or both. These are the route
199  categories provided by the media router framework:</p>
200
201<ul>
202  <li>{@link android.support.v7.media.MediaControlIntent#CATEGORY_LIVE_AUDIO CATEGORY_LIVE_AUDIO}
203    &mdash; Output of audio to a secondary output device, such as a wireless-enabled music system.
204    </li>
205  <li>{@link android.support.v7.media.MediaControlIntent#CATEGORY_LIVE_VIDEO CATEGORY_LIVE_VIDEO}
206    &mdash; Output of video to a secondary output device, such as Wireless Display devices.</li>
207  <li>{@link android.support.v7.media.MediaControlIntent#CATEGORY_REMOTE_PLAYBACK
208    CATEGORY_REMOTE_PLAYBACK} &mdash; Play video or audio on a separate device which handles media
209    retrieval, decoding, and playback, such as
210    <a href="https://www.google.com/url?q=http://www.google.com/chromecast">Chromecast</a> devices.
211    </li>
212</ul>
213
214<p>In order to include these settings in a description of your media route, you insert them into
215  an {@link android.content.IntentFilter} object, which you later add to a
216  {@link android.support.v7.media.MediaRouteDescriptor} object:</p>
217
218<pre>
219public final class SampleMediaRouteProvider extends MediaRouteProvider {
220    private static final ArrayList&lt;IntentFilter&gt; CONTROL_FILTERS_BASIC;
221    static {
222        IntentFilter videoPlayback = new IntentFilter();
223        <strong>videoPlayback.addCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK);</strong>
224        CONTROL_FILTERS_BASIC = new ArrayList&lt;IntentFilter&gt;();
225        CONTROL_FILTERS_BASIC.add(videoPlayback);
226    }
227}
228
229</pre>
230
231<p>If you specify the {@link android.support.v7.media.MediaControlIntent#CATEGORY_REMOTE_PLAYBACK
232  CATEGORY_REMOTE_PLAYBACK} intent, you must also define what media types and
233  playback controls are supported by your media route provider. The next section describes how to
234  specify these settings for your device.</p>
235
236
237<h3 id="media-types">Media types and protocols</h3>
238
239<p>A media route provider for a remote playback device must specify the media types and transfer
240  protocols it supports. You specify these settings using the {@link android.content.IntentFilter}
241  class and the {@link android.content.IntentFilter#addDataScheme addDataScheme()} and
242  {@link android.content.IntentFilter#addDataType addDataType()} methods of that object. The
243  following code snippet demonstrates how to define an intent filter for supporting remote video
244  playback using http, https, and Real Time Streaming Protocol (RTSP):</p>
245
246<pre>
247public final class SampleMediaRouteProvider extends MediaRouteProvider {
248
249    private static final ArrayList&lt;IntentFilter&gt; CONTROL_FILTERS_BASIC;
250
251    static {
252        IntentFilter videoPlayback = new IntentFilter();
253        videoPlayback.addCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK);
254        videoPlayback.addAction(MediaControlIntent.ACTION_PLAY);
255        videoPlayback.addDataScheme("http");
256        videoPlayback.addDataScheme("https");
257        videoPlayback.addDataScheme("rtsp");
258        addDataTypeUnchecked(videoPlayback, "video/*");
259        CONTROL_FILTERS_BASIC = new ArrayList&lt;IntentFilter&gt;();
260        CONTROL_FILTERS_BASIC.add(videoPlayback);
261    }
262    ...
263
264    private static void addDataTypeUnchecked(IntentFilter filter, String type) {
265        try {
266            filter.addDataType(type);
267        } catch (MalformedMimeTypeException ex) {
268            throw new RuntimeException(ex);
269        }
270    }
271}
272
273</pre>
274
275
276<h3 id="playback-ctrls">Playback controls</h3>
277
278<p>A media route provider that offers remote playback must specify the types of media controls
279  it supports. These are the general types of control that media routes can provide:</p>
280
281<ul>
282  <li><strong>Playback controls</strong>, such as play, pause, rewind, and fast-forward.</li>
283  <li><strong>Queuing features</strong>, which allow the sending app to add and remove items
284    from a playlist which is maintained by the receiver device.</li>
285  <li><strong>Session features</strong>, which prevent sending apps from interfering with each
286    other by having the receiver device provide a session id to the requesting app and then checking
287    that id with each subsequent playback control request.</li>
288</ul>
289
290<p>The following code example demonstrates how to construct an intent filter for supporting
291  basic media route playback controls:</p>
292
293<pre>
294public final class SampleMediaRouteProvider extends MediaRouteProvider {
295    private static final ArrayList&lt;IntentFilter&gt; CONTROL_FILTERS_BASIC;
296    static {
297        ...
298        IntentFilter playControls = new IntentFilter();
299        playControls.addCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK);
300        playControls.addAction(MediaControlIntent.ACTION_SEEK);
301        playControls.addAction(MediaControlIntent.ACTION_GET_STATUS);
302        playControls.addAction(MediaControlIntent.ACTION_PAUSE);
303        playControls.addAction(MediaControlIntent.ACTION_RESUME);
304        playControls.addAction(MediaControlIntent.ACTION_STOP);
305        CONTROL_FILTERS_BASIC = new ArrayList&lt;IntentFilter&gt;();
306        CONTROL_FILTERS_BASIC.add(videoPlayback);
307        CONTROL_FILTERS_BASIC.add(playControls);
308    }
309    ...
310}
311</pre>
312
313<p>For more information about the available playback control intents, see the
314  {@link android.support.v7.media.MediaControlIntent} class.</p>
315
316
317<h3 id="mrpd">MediaRouteProviderDescriptor</h3>
318
319<p>After defining the capabilities of your media route using {@link
320  android.content.IntentFilter} objects, you can then create a descriptor object for publishing to
321  the Android media router framework. This descriptor object contains the specifics of your media
322  route's capabilities so that other applications can determine how to interact with your media
323  route.</p>
324
325<p>The following example code demonstrates how to add the previously created intent filters to a
326  {@link android.support.v7.media.MediaRouteProviderDescriptor} and set the descriptor for use by
327  the media router framework:</p>
328
329<pre>
330public SampleMediaRouteProvider(Context context) {
331    super(context);
332    publishRoutes();
333}
334
335private void publishRoutes() {
336    Resources r = getContext().getResources();
337    // Create a route descriptor using previously created IntentFilters
338    MediaRouteDescriptor routeDescriptor = new MediaRouteDescriptor.Builder(
339            VARIABLE_VOLUME_BASIC_ROUTE_ID,
340            r.getString(R.string.variable_volume_basic_route_name))
341            .setDescription(r.getString(R.string.sample_route_description))
342            .addControlFilters(CONTROL_FILTERS_BASIC)
343            .setPlaybackStream(AudioManager.STREAM_MUSIC)
344            .setPlaybackType(MediaRouter.RouteInfo.PLAYBACK_TYPE_REMOTE)
345            .setVolumeHandling(MediaRouter.RouteInfo.PLAYBACK_VOLUME_VARIABLE)
346            .setVolumeMax(VOLUME_MAX)
347            .setVolume(mVolume)
348            .build();
349    // Add the route descriptor to the provider descriptor
350    MediaRouteProviderDescriptor providerDescriptor =
351            new MediaRouteProviderDescriptor.Builder()
352            .addRoute(routeDescriptor)
353            .build();
354
355    // Publish the descriptor to the framework
356    setDescriptor(providerDescriptor);
357}
358</pre>
359
360<p>For more information on the available descriptor settings, see the reference documentation
361  for {@link android.support.v7.media.MediaRouteDescriptor} and {@link
362  android.support.v7.media.MediaRouteProviderDescriptor}.</p>
363
364
365<h2 id="ctrl-routes">Controlling Routes</h2>
366
367<p>When an application connects to your media route provider, the provider receives playback
368  commands through the media router framework sent to your route by other apps. To handle these
369  requests, you must provide an implementation of a {@link
370  android.support.v7.media.MediaRouteProvider.RouteController} class, which processes the commands
371  and handles the actual communication to your receiver device.</p>
372
373<p>The media router framework calls the {@link
374  android.support.v7.media.MediaRouteProvider#onCreateRouteController onCreateRouteController()}
375  method of your route provider to obtain an instance of this class and then routes requests to it.
376  These are the key methods of the {@link
377  android.support.v7.media.MediaRouteProvider.RouteController} class, which you must implement for
378  your media route provider:</p>
379
380<ul>
381  <li>{@link android.support.v7.media.MediaRouteProvider.RouteController#onSelect onSelect()}
382    &mdash; Called when an application selects your route for playback. You use this method to do
383    any preparation work that may be required before media playback begins.</li>
384  <li>{@link android.support.v7.media.MediaRouteProvider.RouteController#onControlRequest
385    onControlRequest()} &mdash; Sends specific playback commands to the receiving device.</li>
386  <li>{@link android.support.v7.media.MediaRouteProvider.RouteController#onSetVolume
387    onSetVolume()} &mdash; Sends a request to the receiving device to set the playback volume to a
388    specific value.</li>
389  <li>{@link android.support.v7.media.MediaRouteProvider.RouteController#onUpdateVolume
390    onUpdateVolume()} &mdash; Sends a request to the receiving device to modify the playback
391    volume by a specified amount.</li>
392  <li>{@link android.support.v7.media.MediaRouteProvider.RouteController#onUnselect
393    onUnselect()} &mdash; Called when an application unselects a route.</li>
394  <li>{@link android.support.v7.media.MediaRouteProvider.RouteController#onRelease onRelease()}
395    &mdash; Called when the route is no longer needed by the framework, allowing it to free its
396    resources.</li>
397</ul>
398
399<p>All playback control requests, except for volume changes, are directed to the {@link
400  android.support.v7.media.MediaRouteProvider.RouteController#onControlRequest onControlRequest()}
401  method. Your implementation of this method must parse the control requests and respond to them
402  appropriately. Here is an example implementation of this method which processes commands for a
403  remote playback media route:</p>
404
405<pre>
406private final class SampleRouteController extends
407        MediaRouteProvider.RouteController {
408    ...
409
410    &#64;Override
411    public boolean onControlRequest(Intent intent, ControlRequestCallback callback) {
412
413        String action = intent.getAction();
414
415        if (intent.hasCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK)) {
416            boolean success = false;
417            if (action.equals(MediaControlIntent.ACTION_PLAY)) {
418                success = handlePlay(intent, callback);
419            } else if (action.equals(MediaControlIntent.ACTION_ENQUEUE)) {
420                success = handleEnqueue(intent, callback);
421            } else if (action.equals(MediaControlIntent.ACTION_REMOVE)) {
422                success = handleRemove(intent, callback);
423            } else if (action.equals(MediaControlIntent.ACTION_SEEK)) {
424                success = handleSeek(intent, callback);
425            } else if (action.equals(MediaControlIntent.ACTION_GET_STATUS)) {
426                success = handleGetStatus(intent, callback);
427            } else if (action.equals(MediaControlIntent.ACTION_PAUSE)) {
428                success = handlePause(intent, callback);
429            } else if (action.equals(MediaControlIntent.ACTION_RESUME)) {
430                success = handleResume(intent, callback);
431            } else if (action.equals(MediaControlIntent.ACTION_STOP)) {
432                success = handleStop(intent, callback);
433            } else if (action.equals(MediaControlIntent.ACTION_START_SESSION)) {
434                success = handleStartSession(intent, callback);
435            } else if (action.equals(MediaControlIntent.ACTION_GET_SESSION_STATUS)) {
436                success = handleGetSessionStatus(intent, callback);
437            } else if (action.equals(MediaControlIntent.ACTION_END_SESSION)) {
438                success = handleEndSession(intent, callback);
439            }
440
441            Log.d(TAG, mSessionManager.toString());
442            return success;
443        }
444        return false;
445    }
446    ...
447}
448</pre>
449
450<p>It is important to understand that the {@link
451  android.support.v7.media.MediaRouteProvider.RouteController} class is intended to act as a wrapper
452  for the API to your media playback equipment. The implementation of the methods in this class is
453  entirely dependent on the programmatic interface provided by your receiving device.</p>
454