am fd5a3f30: Samples for media router support library.
* commit 'fd5a3f30de4ef0cf1119089d547bba6b36ad0068': Samples for media router support library.
This commit is contained in:
@@ -301,5 +301,22 @@
|
|||||||
</provider>
|
</provider>
|
||||||
<!-- END_INCLUDE(file_provider_declaration) -->
|
<!-- END_INCLUDE(file_provider_declaration) -->
|
||||||
|
|
||||||
|
<!-- MediaRouter Support Samples -->
|
||||||
|
|
||||||
|
<activity android:name=".media.SampleMediaRouterActivity"
|
||||||
|
android:label="@string/sample_media_router_activity">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
<category android:name="com.example.android.supportv4.SUPPORT4_SAMPLE_CODE" />
|
||||||
|
</intent-filter>
|
||||||
|
</activity>
|
||||||
|
|
||||||
|
<service android:name=".media.SampleMediaRouteProviderService"
|
||||||
|
android:label="@string/sample_media_route_provider_service"
|
||||||
|
android:process=":mediarouteprovider">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.media.MediaRouteProviderService" />
|
||||||
|
</intent-filter>
|
||||||
|
</service>
|
||||||
</application>
|
</application>
|
||||||
</manifest>
|
</manifest>
|
||||||
|
|||||||
BIN
samples/Support4Demos/res/drawable-hdpi/media_route_icon.png
Executable file
BIN
samples/Support4Demos/res/drawable-hdpi/media_route_icon.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 3.5 KiB |
BIN
samples/Support4Demos/res/drawable-mdpi/media_route_icon.png
Normal file
BIN
samples/Support4Demos/res/drawable-mdpi/media_route_icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.1 KiB |
64
samples/Support4Demos/res/layout/sample_media_router.xml
Normal file
64
samples/Support4Demos/res/layout/sample_media_router.xml
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Copyright (C) 2013 The Android Open Source Project
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<!-- See corresponding Java code SampleMediaRouterActivity.java. -->
|
||||||
|
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<!-- Message to show to use. -->
|
||||||
|
<TextView android:id="@+id/text"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="0"
|
||||||
|
android:gravity="center_vertical|center_horizontal"
|
||||||
|
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||||
|
android:text="@string/sample_media_router_text"/>
|
||||||
|
|
||||||
|
<!-- Some information about what's going on. -->
|
||||||
|
<TextView android:id="@+id/info"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="0"
|
||||||
|
android:gravity="center_vertical|center_horizontal"
|
||||||
|
android:textAppearance="?android:attr/textAppearanceMedium"/>
|
||||||
|
|
||||||
|
<!-- Some media to play. -->
|
||||||
|
<ListView android:id="@+id/media"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"/>
|
||||||
|
|
||||||
|
<!-- Control buttons for the currently selected route. -->
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="0">
|
||||||
|
<Button android:id="@+id/play_button"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="0"
|
||||||
|
android:text="@string/play_button_text" />
|
||||||
|
|
||||||
|
<Button android:id="@+id/statistics_button"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="0"
|
||||||
|
android:text="@string/statistics_button_text" />
|
||||||
|
</LinearLayout>
|
||||||
|
</LinearLayout>
|
||||||
24
samples/Support4Demos/res/menu/sample_media_router_menu.xml
Normal file
24
samples/Support4Demos/res/menu/sample_media_router_menu.xml
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Copyright (C) 2012 Google Inc.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<!-- TODO: Use MediaRouter support library -->
|
||||||
|
<item android:id="@+id/menu_media_route"
|
||||||
|
android:title="@string/sample_media_router_play_on"
|
||||||
|
android:showAsAction="always"
|
||||||
|
android:orderInCategory="1"
|
||||||
|
android:actionProviderClass="android.app.MediaRouteActionProvider"/>
|
||||||
|
</menu>
|
||||||
33
samples/Support4Demos/res/values/arrays.xml
Normal file
33
samples/Support4Demos/res/values/arrays.xml
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Copyright (C) 2013 The Android Open Source Project
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<resources>
|
||||||
|
<string-array name="media_names">
|
||||||
|
<item>My favorite video of cats</item>
|
||||||
|
<item>Cats on parade</item>
|
||||||
|
<item>Cats with hats</item>
|
||||||
|
<item>Hats on cats</item>
|
||||||
|
<item>Cats on mats</item>
|
||||||
|
</string-array>
|
||||||
|
|
||||||
|
<string-array name="media_uris">
|
||||||
|
<item>http://cats.example.com/favorite-cats.mp4</item>
|
||||||
|
<item>http://cats.example.com/cats-on-parade.mp4</item>
|
||||||
|
<item>http://cats.example.com/cats-with-hats.mp4</item>
|
||||||
|
<item>http://cats.example.com/hats-on-cats.mp4</item>
|
||||||
|
<item>http://cats.example.com/cats-on-mats.mp4</item>
|
||||||
|
</string-array>
|
||||||
|
</resources>
|
||||||
@@ -136,4 +136,17 @@
|
|||||||
|
|
||||||
<string name="file_provider_example">FileProvider example</string>
|
<string name="file_provider_example">FileProvider example</string>
|
||||||
|
|
||||||
|
<!-- MediaRouter -->
|
||||||
|
|
||||||
|
<string name="sample_media_router_activity">Media/MediaRouter</string>
|
||||||
|
<string name="sample_media_router_text">This activity demonstrates how to
|
||||||
|
use MediaRouter from the support library. Select a route from the action bar.</string>
|
||||||
|
<string name="sample_media_router_play_on">Play on...</string>
|
||||||
|
|
||||||
|
<string name="play_button_text">Play</string>
|
||||||
|
<string name="statistics_button_text">Show Statistics</string>
|
||||||
|
|
||||||
|
<string name="sample_media_route_provider_service">Media Route Provider Service Support Library Sample</string>
|
||||||
|
<string name="fixed_volume_route_name">Fixed Volume Remote Playback Route</string>
|
||||||
|
<string name="variable_volume_route_name">Variable Volume Remote Playback Route</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -0,0 +1,218 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2013 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.example.android.supportv4.media;
|
||||||
|
|
||||||
|
import com.example.android.supportv4.R;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.IntentFilter;
|
||||||
|
import android.content.IntentFilter.MalformedMimeTypeException;
|
||||||
|
import android.content.res.Resources;
|
||||||
|
import android.media.MediaRouter;
|
||||||
|
import android.net.Uri;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.support.v4.media.MediaControlIntent;
|
||||||
|
import android.support.v4.media.MediaRouteProvider;
|
||||||
|
import android.support.v4.media.MediaRouter.ControlRequestCallback;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Demonstrates how to create a custom media route provider.
|
||||||
|
*
|
||||||
|
* @see SampleMediaRouteProviderService
|
||||||
|
*/
|
||||||
|
final class SampleMediaRouteProvider extends MediaRouteProvider {
|
||||||
|
private static final String TAG = "SampleMediaRouteProvider";
|
||||||
|
|
||||||
|
private static final String FIXED_VOLUME_ROUTE_ID = "fixed";
|
||||||
|
private static final String VARIABLE_VOLUME_ROUTE_ID = "variable";
|
||||||
|
private static final int VOLUME_MAX = 10;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A custom media control intent category for special requests that are
|
||||||
|
* supported by this provider's routes.
|
||||||
|
*/
|
||||||
|
public static final String CATEGORY_SAMPLE_ROUTE =
|
||||||
|
"com.example.android.supportv4.media.CATEGORY_SAMPLE_ROUTE";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A custom media control intent action for special requests that are
|
||||||
|
* supported by this provider's routes.
|
||||||
|
* <p>
|
||||||
|
* This particular request is designed to return a bundle of not very
|
||||||
|
* interesting statistics for demonstration purposes.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @see #DATA_PLAYBACK_COUNT
|
||||||
|
*/
|
||||||
|
public static final String ACTION_GET_STATISTICS =
|
||||||
|
"com.example.android.supportv4.media.ACTION_GET_STATISTICS";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link #ACTION_GET_STATISTICS} result data: Number of times the
|
||||||
|
* playback action was invoked.
|
||||||
|
*/
|
||||||
|
public static final String DATA_PLAYBACK_COUNT =
|
||||||
|
"com.example.android.supportv4.media.EXTRA_PLAYBACK_COUNT";
|
||||||
|
|
||||||
|
private static final IntentFilter[] CONTROL_FILTERS;
|
||||||
|
static {
|
||||||
|
CONTROL_FILTERS = new IntentFilter[2];
|
||||||
|
|
||||||
|
CONTROL_FILTERS[0] = new IntentFilter();
|
||||||
|
CONTROL_FILTERS[0].addCategory(CATEGORY_SAMPLE_ROUTE);
|
||||||
|
CONTROL_FILTERS[0].addAction(ACTION_GET_STATISTICS);
|
||||||
|
|
||||||
|
CONTROL_FILTERS[1] = new IntentFilter();
|
||||||
|
CONTROL_FILTERS[1].addCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK);
|
||||||
|
CONTROL_FILTERS[1].addAction(MediaControlIntent.ACTION_PLAY);
|
||||||
|
CONTROL_FILTERS[1].addDataScheme("http");
|
||||||
|
CONTROL_FILTERS[1].addDataScheme("https");
|
||||||
|
addDataTypeUnchecked(CONTROL_FILTERS[1], "video/*");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void addDataTypeUnchecked(IntentFilter filter, String type) {
|
||||||
|
try {
|
||||||
|
filter.addDataType(type);
|
||||||
|
} catch (MalformedMimeTypeException ex) {
|
||||||
|
throw new RuntimeException(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int mVolume = 5;
|
||||||
|
private int mPlaybackCount;
|
||||||
|
|
||||||
|
public SampleMediaRouteProvider(Context context) {
|
||||||
|
super(context);
|
||||||
|
|
||||||
|
publishRoutes();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RouteController onCreateRouteController(String routeId) {
|
||||||
|
return new SampleRouteController(routeId);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void publishRoutes() {
|
||||||
|
Resources r = getContext().getResources();
|
||||||
|
|
||||||
|
RouteDescriptor routeDescriptor1 = new RouteDescriptor(
|
||||||
|
FIXED_VOLUME_ROUTE_ID,
|
||||||
|
r.getString(R.string.fixed_volume_route_name));
|
||||||
|
routeDescriptor1.setControlFilters(CONTROL_FILTERS);
|
||||||
|
routeDescriptor1.setIconResource(R.drawable.media_route_icon);
|
||||||
|
routeDescriptor1.setPlaybackType(MediaRouter.RouteInfo.PLAYBACK_TYPE_REMOTE);
|
||||||
|
routeDescriptor1.setVolumeHandling(MediaRouter.RouteInfo.PLAYBACK_VOLUME_FIXED);
|
||||||
|
routeDescriptor1.setVolume(VOLUME_MAX);
|
||||||
|
|
||||||
|
RouteDescriptor routeDescriptor2 = new RouteDescriptor(
|
||||||
|
VARIABLE_VOLUME_ROUTE_ID,
|
||||||
|
r.getString(R.string.variable_volume_route_name));
|
||||||
|
routeDescriptor2.setControlFilters(CONTROL_FILTERS);
|
||||||
|
routeDescriptor2.setIconResource(R.drawable.media_route_icon);
|
||||||
|
routeDescriptor2.setPlaybackType(MediaRouter.RouteInfo.PLAYBACK_TYPE_REMOTE);
|
||||||
|
routeDescriptor2.setVolumeHandling(MediaRouter.RouteInfo.PLAYBACK_VOLUME_VARIABLE);
|
||||||
|
routeDescriptor2.setVolumeMax(VOLUME_MAX);
|
||||||
|
routeDescriptor2.setVolume(mVolume);
|
||||||
|
|
||||||
|
ProviderDescriptor providerDescriptor = new ProviderDescriptor();
|
||||||
|
providerDescriptor.setRoutes(new RouteDescriptor[] {
|
||||||
|
routeDescriptor1, routeDescriptor2
|
||||||
|
});
|
||||||
|
setDescriptor(providerDescriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
private final class SampleRouteController extends MediaRouteProvider.RouteController {
|
||||||
|
private final String mRouteId;
|
||||||
|
|
||||||
|
public SampleRouteController(String routeId) {
|
||||||
|
mRouteId = routeId;
|
||||||
|
Log.d(TAG, mRouteId + ": Controller created");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void release() {
|
||||||
|
Log.d(TAG, mRouteId + ": Controller released");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void select() {
|
||||||
|
Log.d(TAG, mRouteId + ": Selected");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void unselect() {
|
||||||
|
Log.d(TAG, mRouteId + ": Unselected");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setVolume(int volume) {
|
||||||
|
Log.d(TAG, mRouteId + ": Set volume to " + volume);
|
||||||
|
if (mRouteId.equals(VARIABLE_VOLUME_ROUTE_ID)) {
|
||||||
|
setVolumeInternal(volume);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateVolume(int delta) {
|
||||||
|
Log.d(TAG, mRouteId + ": Update volume by " + delta);
|
||||||
|
if (mRouteId.equals(VARIABLE_VOLUME_ROUTE_ID)) {
|
||||||
|
setVolumeInternal(mVolume + delta);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setVolumeInternal(int volume) {
|
||||||
|
if (volume >= 0 && volume <= VOLUME_MAX) {
|
||||||
|
mVolume = volume;
|
||||||
|
Log.d(TAG, mRouteId + ": New volume is " + mVolume);
|
||||||
|
publishRoutes();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean sendControlRequest(Intent intent, ControlRequestCallback callback) {
|
||||||
|
Log.d(TAG, mRouteId + ": Received control request " + intent);
|
||||||
|
if (intent.getAction().equals(MediaControlIntent.ACTION_PLAY)
|
||||||
|
&& intent.hasCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK)
|
||||||
|
&& intent.getData() != null) {
|
||||||
|
mPlaybackCount +=1;
|
||||||
|
|
||||||
|
Uri uri = intent.getData();
|
||||||
|
Log.d(TAG, mRouteId + ": Received play request, uri=" + uri);
|
||||||
|
Toast.makeText(getContext(), "Route received play request: uri=" + uri,
|
||||||
|
Toast.LENGTH_LONG).show();
|
||||||
|
if (callback != null) {
|
||||||
|
callback.onResult(ControlRequestCallback.REQUEST_SUCCEEDED, null);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (intent.getAction().equals(ACTION_GET_STATISTICS)
|
||||||
|
&& intent.hasCategory(CATEGORY_SAMPLE_ROUTE)) {
|
||||||
|
Bundle data = new Bundle();
|
||||||
|
data.putInt(DATA_PLAYBACK_COUNT, mPlaybackCount);
|
||||||
|
if (callback != null) {
|
||||||
|
callback.onResult(ControlRequestCallback.REQUEST_SUCCEEDED, data);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2013 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.example.android.supportv4.media;
|
||||||
|
|
||||||
|
import android.support.v4.media.MediaRouteProvider;
|
||||||
|
import android.support.v4.media.MediaRouteProviderService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Demonstrates how to register a custom media route provider service
|
||||||
|
* using the support library.
|
||||||
|
*
|
||||||
|
* @see SampleMediaRouteProvider
|
||||||
|
*/
|
||||||
|
public class SampleMediaRouteProviderService extends MediaRouteProviderService {
|
||||||
|
@Override
|
||||||
|
public MediaRouteProvider onCreateMediaRouteProvider() {
|
||||||
|
return new SampleMediaRouteProvider(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,340 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2013 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.example.android.supportv4.media;
|
||||||
|
|
||||||
|
import com.example.android.supportv4.R;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.app.MediaRouteActionProvider;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.net.Uri;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.support.v4.media.MediaControlIntent;
|
||||||
|
import android.support.v4.media.MediaRouter;
|
||||||
|
import android.support.v4.media.MediaRouter.RouteInfo;
|
||||||
|
import android.support.v4.media.MediaRouter.ProviderInfo;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.Menu;
|
||||||
|
import android.view.MenuItem;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.View.OnClickListener;
|
||||||
|
import android.widget.AdapterView.OnItemClickListener;
|
||||||
|
import android.widget.AdapterView;
|
||||||
|
import android.widget.ArrayAdapter;
|
||||||
|
import android.widget.Button;
|
||||||
|
import android.widget.ListView;
|
||||||
|
import android.widget.TextView;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <h3>Media Router Support Activity</h3>
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* This demonstrates how to use the {@link MediaRouter} API to build an
|
||||||
|
* application that allows the user to send content to various rendering
|
||||||
|
* targets.
|
||||||
|
* </p>
|
||||||
|
*/
|
||||||
|
public class SampleMediaRouterActivity extends Activity {
|
||||||
|
private final String TAG = "MediaRouterSupport";
|
||||||
|
|
||||||
|
private MediaRouter mMediaRouter;
|
||||||
|
private ArrayAdapter<MediaItem> mMediaItems;
|
||||||
|
private TextView mInfoTextView;
|
||||||
|
private ListView mMediaListView;
|
||||||
|
private Button mPlayButton;
|
||||||
|
private Button mStatisticsButton;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
// Be sure to call the super class.
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
|
// Get the media router service.
|
||||||
|
mMediaRouter = MediaRouter.getInstance(this);
|
||||||
|
|
||||||
|
// Populate an array adapter with fake media items.
|
||||||
|
String[] mediaNames = getResources().getStringArray(R.array.media_names);
|
||||||
|
String[] mediaUris = getResources().getStringArray(R.array.media_uris);
|
||||||
|
mMediaItems = new ArrayAdapter<MediaItem>(this,
|
||||||
|
android.R.layout.simple_list_item_single_choice, android.R.id.text1);
|
||||||
|
for (int i = 0; i < mediaNames.length; i++) {
|
||||||
|
mMediaItems.add(new MediaItem(mediaNames[i], Uri.parse(mediaUris[i])));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize the layout.
|
||||||
|
setContentView(R.layout.sample_media_router);
|
||||||
|
|
||||||
|
mInfoTextView = (TextView)findViewById(R.id.info);
|
||||||
|
|
||||||
|
mMediaListView = (ListView)findViewById(R.id.media);
|
||||||
|
mMediaListView.setAdapter(mMediaItems);
|
||||||
|
mMediaListView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
|
||||||
|
mMediaListView.setOnItemClickListener(new OnItemClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
||||||
|
updateButtons();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
mPlayButton = (Button)findViewById(R.id.play_button);
|
||||||
|
mPlayButton.setOnClickListener(new OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
play();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
mStatisticsButton = (Button)findViewById(R.id.statistics_button);
|
||||||
|
mStatisticsButton.setOnClickListener(new OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
showStatistics();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onResume() {
|
||||||
|
// Be sure to call the super class.
|
||||||
|
super.onResume();
|
||||||
|
|
||||||
|
// Listen for changes to media routes.
|
||||||
|
mMediaRouter.addCallback(mMediaRouterCallback);
|
||||||
|
updateRouteStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPause() {
|
||||||
|
// Be sure to call the super class.
|
||||||
|
super.onPause();
|
||||||
|
|
||||||
|
// Stop listening for changes to media routes.
|
||||||
|
mMediaRouter.removeCallback(mMediaRouterCallback);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Use ActionBar support library.
|
||||||
|
@Override
|
||||||
|
public boolean onCreateOptionsMenu(Menu menu) {
|
||||||
|
// Be sure to call the super class.
|
||||||
|
super.onCreateOptionsMenu(menu);
|
||||||
|
|
||||||
|
// Inflate the menu and configure the media router action provider.
|
||||||
|
getMenuInflater().inflate(R.menu.sample_media_router_menu, menu);
|
||||||
|
|
||||||
|
// TODO: Use support library media route action provider.
|
||||||
|
MenuItem mediaRouteMenuItem = menu.findItem(R.id.menu_media_route);
|
||||||
|
MediaRouteActionProvider mediaRouteActionProvider =
|
||||||
|
(MediaRouteActionProvider)mediaRouteMenuItem.getActionProvider();
|
||||||
|
mediaRouteActionProvider.setRouteTypes(
|
||||||
|
android.media.MediaRouter.ROUTE_TYPE_LIVE_AUDIO
|
||||||
|
| android.media.MediaRouter.ROUTE_TYPE_LIVE_VIDEO
|
||||||
|
| android.media.MediaRouter.ROUTE_TYPE_USER);
|
||||||
|
|
||||||
|
// Return true to show the menu.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateRouteStatus() {
|
||||||
|
RouteInfo route = mMediaRouter.getSelectedRoute();
|
||||||
|
mInfoTextView.setText("Currently selected route: " + route.getName()
|
||||||
|
+ " from provider " + route.getProvider().getPackageName()
|
||||||
|
+ ", status: " + route.getStatus());
|
||||||
|
updateButtons();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateButtons() {
|
||||||
|
MediaRouter.RouteInfo route = mMediaRouter.getSelectedRoute();
|
||||||
|
|
||||||
|
MediaItem item = getCheckedMediaItem();
|
||||||
|
if (item != null) {
|
||||||
|
mPlayButton.setEnabled(route.supportsControlRequest(makePlayIntent(item)));
|
||||||
|
} else {
|
||||||
|
mPlayButton.setEnabled(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
mStatisticsButton.setEnabled(route.supportsControlRequest(makeStatisticsIntent()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void play() {
|
||||||
|
final MediaItem item = getCheckedMediaItem();
|
||||||
|
if (item == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
MediaRouter.RouteInfo route = mMediaRouter.getSelectedRoute();
|
||||||
|
Intent intent = makePlayIntent(item);
|
||||||
|
if (route.supportsControlRequest(intent)) {
|
||||||
|
MediaRouter.ControlRequestCallback callback =
|
||||||
|
new MediaRouter.ControlRequestCallback() {
|
||||||
|
@Override
|
||||||
|
public void onResult(int result, Bundle data) {
|
||||||
|
switch (result) {
|
||||||
|
case REQUEST_SUCCEEDED:
|
||||||
|
Log.d(TAG, "Play request succeeded: data=" + data);
|
||||||
|
Toast.makeText(SampleMediaRouterActivity.this,
|
||||||
|
"Now playing " + item.mName,
|
||||||
|
Toast.LENGTH_LONG).show();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case REQUEST_FAILED:
|
||||||
|
Log.d(TAG, "Play request failed: data=" + data);
|
||||||
|
Toast.makeText(SampleMediaRouterActivity.this,
|
||||||
|
"Unable to play " + item.mName,
|
||||||
|
Toast.LENGTH_LONG).show();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Log.d(TAG, "Sending play request: intent=" + intent);
|
||||||
|
route.sendControlRequest(intent, callback);
|
||||||
|
} else {
|
||||||
|
Log.d(TAG, "Play request not supported: intent=" + intent);
|
||||||
|
Toast.makeText(SampleMediaRouterActivity.this,
|
||||||
|
"Play not supported for " + item.mName, Toast.LENGTH_LONG).show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showStatistics() {
|
||||||
|
MediaRouter.RouteInfo route = mMediaRouter.getSelectedRoute();
|
||||||
|
Intent intent = makeStatisticsIntent();
|
||||||
|
if (route.supportsControlRequest(intent)) {
|
||||||
|
MediaRouter.ControlRequestCallback callback = new MediaRouter.ControlRequestCallback() {
|
||||||
|
@Override
|
||||||
|
public void onResult(int result, Bundle data) {
|
||||||
|
switch (result) {
|
||||||
|
case REQUEST_SUCCEEDED:
|
||||||
|
Log.d(TAG, "Statistics request succeeded: data=" + data);
|
||||||
|
if (data != null) {
|
||||||
|
int playbackCount = data.getInt(
|
||||||
|
SampleMediaRouteProvider.DATA_PLAYBACK_COUNT, -1);
|
||||||
|
Toast.makeText(SampleMediaRouterActivity.this,
|
||||||
|
"Total playback count: " + playbackCount,
|
||||||
|
Toast.LENGTH_LONG).show();
|
||||||
|
} else {
|
||||||
|
Toast.makeText(SampleMediaRouterActivity.this,
|
||||||
|
"Statistics query did not return any data",
|
||||||
|
Toast.LENGTH_LONG).show();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case REQUEST_FAILED:
|
||||||
|
Log.d(TAG, "Statistics request failed: data=" + data);
|
||||||
|
Toast.makeText(SampleMediaRouterActivity.this,
|
||||||
|
"Unable to query statistics.",
|
||||||
|
Toast.LENGTH_LONG).show();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Log.d(TAG, "Sent statistics request: intent=" + intent);
|
||||||
|
route.sendControlRequest(intent, callback);
|
||||||
|
} else {
|
||||||
|
Log.d(TAG, "Statistics request not supported: intent=" + intent);
|
||||||
|
Toast.makeText(SampleMediaRouterActivity.this,
|
||||||
|
"Statistics not supported.", Toast.LENGTH_LONG).show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Intent makePlayIntent(MediaItem item) {
|
||||||
|
Intent intent = new Intent(MediaControlIntent.ACTION_PLAY);
|
||||||
|
intent.addCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK);
|
||||||
|
intent.setDataAndType(item.mUri, "video/mp4");
|
||||||
|
return intent;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Intent makeStatisticsIntent() {
|
||||||
|
Intent intent = new Intent(SampleMediaRouteProvider.ACTION_GET_STATISTICS);
|
||||||
|
intent.addCategory(SampleMediaRouteProvider.CATEGORY_SAMPLE_ROUTE);
|
||||||
|
return intent;
|
||||||
|
}
|
||||||
|
|
||||||
|
private MediaItem getCheckedMediaItem() {
|
||||||
|
int index = mMediaListView.getCheckedItemPosition();
|
||||||
|
if (index >= 0 && index < mMediaItems.getCount()) {
|
||||||
|
return mMediaItems.getItem(index);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private final MediaRouter.Callback mMediaRouterCallback = new MediaRouter.Callback() {
|
||||||
|
@Override
|
||||||
|
public void onRouteAdded(MediaRouter router, RouteInfo route) {
|
||||||
|
Log.d(TAG, "onRouteAdded: route=" + route);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onRouteChanged(MediaRouter router, RouteInfo route) {
|
||||||
|
Log.d(TAG, "onRouteChanged: route=" + route);
|
||||||
|
updateRouteStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onRouteRemoved(MediaRouter router, RouteInfo route) {
|
||||||
|
Log.d(TAG, "onRouteRemoved: route=" + route);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onRouteSelected(MediaRouter router, RouteInfo route) {
|
||||||
|
Log.d(TAG, "onRouteSelected: route=" + route);
|
||||||
|
updateRouteStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onRouteUnselected(MediaRouter router, RouteInfo route) {
|
||||||
|
Log.d(TAG, "onRouteUnselected: route=" + route);
|
||||||
|
updateRouteStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onRouteVolumeChanged(MediaRouter router, RouteInfo route) {
|
||||||
|
Log.d(TAG, "onRouteVolumeChanged: route=" + route);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onRoutePresentationDisplayChanged(MediaRouter router, RouteInfo route) {
|
||||||
|
Log.d(TAG, "onRoutePresentationDisplayChanged: route=" + route);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onProviderAdded(MediaRouter router, ProviderInfo provider) {
|
||||||
|
Log.d(TAG, "onRouteProviderAdded: provider=" + provider);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onProviderRemoved(MediaRouter router, ProviderInfo provider) {
|
||||||
|
Log.d(TAG, "onRouteProviderRemoved: provider=" + provider);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private static final class MediaItem {
|
||||||
|
public final String mName;
|
||||||
|
public final Uri mUri;
|
||||||
|
|
||||||
|
public MediaItem(String name, Uri uri) {
|
||||||
|
mName = name;
|
||||||
|
mUri = uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return mName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user