diff --git a/docs/html/guide/guide_toc.cs b/docs/html/guide/guide_toc.cs index 73d5b7437fc99..0a234aa172794 100644 --- a/docs/html/guide/guide_toc.cs +++ b/docs/html/guide/guide_toc.cs @@ -368,7 +368,10 @@ Media Playback
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.
+ +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.
+ +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.
+ +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.
+ +
++ Figure 1. Overview of how media route provider classes provide communication + from a media app to a receiver device. +
+ +When you build a media route provider for your receiver device, the provider serves the +following purposes:
+ +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.
+ ++ Note: The app containing the media route provider can also include a + MediaRouter interface to the + route provider, but this is not required. +
+ + +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:
+ ++ The media router APIs are provided as part of the Android Support Library version 18 and higher, + in the v7-mediarouter + 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. +
+ ++ Caution: There is another set of media router APIs provided in the + {@link android.media} class package that have been superseded by the + v7-mediarouter + support library. You should not use the {@link android.media} classes for + implementing media route provider functions. +
+ +In order to use the {@link android.support.v7.media} media router classes, you + must add the v7-mediarouter support library package to your app development project. For more + information on adding support libraries to your app development project, see + Support Library Setup. +
+ + +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}.
+ +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:
+ ++<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> ++ +
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:
+ +
+public class SampleMediaRouteProviderService extends MediaRouteProviderService {
+
+ @Override
+ public MediaRouteProvider onCreateMediaRouteProvider() {
+ return new SampleMediaRouteProvider(this);
+ }
+}
+
+
+
+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.
+ +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.
+ + +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:
+ +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:
+ +
+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);
+ CONTROL_FILTERS_BASIC = new ArrayList<IntentFilter>();
+ CONTROL_FILTERS_BASIC.add(videoPlayback);
+ }
+}
+
+
+
+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.
+ + +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):
+ +
+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);
+ }
+ }
+}
+
+
+
+
+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:
+ +The following code example demonstrates how to construct an intent filter for supporting + basic media route playback controls:
+ +
+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);
+ }
+ ...
+}
+
+
+For more information about the available playback control intents, see the + {@link android.support.v7.media.MediaControlIntent} class.
+ + +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.
+ +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:
+ +
+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);
+}
+
+
+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}.
+ + +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.
+ +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:
+ +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:
+ +
+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;
+ }
+ ...
+}
+
+
+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.
diff --git a/docs/html/guide/topics/media/mediarouter.jd b/docs/html/guide/topics/media/mediarouter.jd index 1b102652b4237..e0bf88914899b 100644 --- a/docs/html/guide/topics/media/mediarouter.jd +++ b/docs/html/guide/topics/media/mediarouter.jd @@ -1,5 +1,5 @@ -page.title=MediaRouter -page.tags="cast","chromecast","wireless display","miracast" +page.title=Media Router +page.tags="mediarouter","cast","chromecast","wireless display","miracast" @jd:body- Note: There is another set of media router APIs provided in the +
+ Caution: There is another set of media router APIs provided in the {@link android.media} that have been superseded by the v7-mediarouter support library. You should not use the {@link android.media} classes for media router functions.
In order to use the {@link android.support.v7.media} media router classes, you must add the v7-mediarouter - support library package to your app development project. + support library package to your app development project. For more + information on adding support libraries to your app development project, see + Support Library Setup.
@@ -211,9 +217,9 @@ page.tags="cast","chromecast","wireless display","miracast" CATEGORY_LIVE_VIDEO} — Output of video to a secondary output device, such as Wireless Display devices.In order to connect to a media route selected by the user, your app must obtain the {@link android.support.v7.media.MediaRouter} framework object and then attach a {@link android.support.v7.media.MediaRouter.Callback} object. The callback object receives messages - from the media router framework when a route selected, changed or disconnected by the user.
+ from the media router framework when a route is selected, changed, or disconnected by the user.To obtain an instance of the {@link android.support.v7.media.MediaRouter} framework object, call {@link android.support.v7.media.MediaRouter#getInstance MediaRouter.getInstance()} @@ -299,11 +305,11 @@ public boolean onCreateOptionsMenu(Menu menu) {
The media router framework communicates with an app through a callback object that you attach to the {@link android.support.v7.media.MediaRouter} framework object. An app that uses the media router framework must extend the {@link - android.support.v7.media.MediaRouter.Callback} object to receive messages when a media route is - connected and provide content to the connected device through that route.
+ android.support.v7.media.MediaRouter.Callback} object in order to receive messages when a + media route is connected. -There are several methods in the callback that can be overwritten to receive messages about - media router events. At the minimum, your implementation of the {@link +
There are several methods in the callback that you can override to receive information about + media router events. At minimum, your implementation of the {@link android.support.v7.media.MediaRouter.Callback} class should override the following methods:
@@ -440,12 +446,12 @@ public class MediaRouterPlaybackActivity extends ActionBarActivity {Note: The media route framework also provides a - {@link android.support.v7.app.MediaRouteDiscoveryFragment} class which takes care of adding and - removing the call back for an activity. + {@link android.support.v7.app.MediaRouteDiscoveryFragment} class, which takes care of adding and + removing the callback for an activity.
Now when you run your application, you should see a Cast button appear in your activity. - When you press the button the media router framework, a route selection dialog appears as shown + When you touch the button, a route selection dialog appears as shown in figure 3, allowing your user to select an available media route. Make sure you have a supported device available on your local network when testing this interface.
diff --git a/docs/html/images/mediarouter/media-route-provider-framework.png b/docs/html/images/mediarouter/media-route-provider-framework.png new file mode 100644 index 0000000000000..60cc29a35325a Binary files /dev/null and b/docs/html/images/mediarouter/media-route-provider-framework.png differ diff --git a/docs/image_sources/mediarouter/media-route-provider-framework.graffle/._data.plist b/docs/image_sources/mediarouter/media-route-provider-framework.graffle/._data.plist new file mode 100644 index 0000000000000..d82ea050f0c0d Binary files /dev/null and b/docs/image_sources/mediarouter/media-route-provider-framework.graffle/._data.plist differ diff --git a/docs/image_sources/mediarouter/media-route-provider-framework.graffle/._image1.png b/docs/image_sources/mediarouter/media-route-provider-framework.graffle/._image1.png new file mode 100644 index 0000000000000..3435e35bbff4c Binary files /dev/null and b/docs/image_sources/mediarouter/media-route-provider-framework.graffle/._image1.png differ diff --git a/docs/image_sources/mediarouter/media-route-provider-framework.graffle/data.plist b/docs/image_sources/mediarouter/media-route-provider-framework.graffle/data.plist new file mode 100644 index 0000000000000..07791df4a0edb Binary files /dev/null and b/docs/image_sources/mediarouter/media-route-provider-framework.graffle/data.plist differ diff --git a/docs/image_sources/mediarouter/media-route-provider-framework.graffle/image1.png b/docs/image_sources/mediarouter/media-route-provider-framework.graffle/image1.png new file mode 100644 index 0000000000000..d6e3e9591212a Binary files /dev/null and b/docs/image_sources/mediarouter/media-route-provider-framework.graffle/image1.png differ diff --git a/docs/image_sources/mediarouter/media-router-framework.graffle/data.plist b/docs/image_sources/mediarouter/media-router-framework.graffle/data.plist new file mode 100644 index 0000000000000..ffd82121845b0 Binary files /dev/null and b/docs/image_sources/mediarouter/media-router-framework.graffle/data.plist differ diff --git a/docs/image_sources/mediarouter/media-router-framework.graffle/image1.png b/docs/image_sources/mediarouter/media-router-framework.graffle/image1.png new file mode 100644 index 0000000000000..d6e3e9591212a Binary files /dev/null and b/docs/image_sources/mediarouter/media-router-framework.graffle/image1.png differ