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<service android:name=".provider.SampleMediaRouteProviderService" 156 android:label="@string/sample_media_route_provider_service" 157 android:process=":mrp"> 158 <intent-filter> 159 <action android:name="android.media.MediaRouteProviderService" /> 160 </intent-filter> 161</service> 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 @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 — 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 — 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} — 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<IntentFilter> 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<IntentFilter>(); 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<IntentFilter> 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<IntentFilter>(); 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<IntentFilter> 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<IntentFilter>(); 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 — 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()} — Sends specific playback commands to the receiving device.</li> 386 <li>{@link android.support.v7.media.MediaRouteProvider.RouteController#onSetVolume 387 onSetVolume()} — 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()} — 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()} — Called when an application unselects a route.</li> 394 <li>{@link android.support.v7.media.MediaRouteProvider.RouteController#onRelease onRelease()} 395 — 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 @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