blob: 456bd156fbdefc3c7139fb30ed82fd7e89329e18 [file] [log] [blame]
/*
* 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.supportv7.media;
import com.example.android.supportv7.R;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.FragmentManager;
import android.support.v4.view.MenuItemCompat;
import android.support.v7.app.ActionBarActivity;
import android.support.v7.app.MediaRouteActionProvider;
import android.support.v7.app.MediaRouteDiscoveryFragment;
import android.support.v7.media.MediaControlIntent;
import android.support.v7.media.MediaRouter;
import android.support.v7.media.MediaRouter.Callback;
import android.support.v7.media.MediaRouter.RouteInfo;
import android.support.v7.media.MediaRouter.ProviderInfo;
import android.support.v7.media.MediaRouteSelector;
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 ActionBarActivity {
private static final String TAG = "MediaRouterSupport";
private static final String DISCOVERY_FRAGMENT_TAG = "DiscoveryFragment";
private MediaRouter mMediaRouter;
private MediaRouteSelector mSelector;
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);
// Create a route selector for the type of routes that we care about.
mSelector = new MediaRouteSelector.Builder()
.addControlCategory(MediaControlIntent.CATEGORY_LIVE_AUDIO)
.addControlCategory(MediaControlIntent.CATEGORY_LIVE_VIDEO)
.addControlCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK)
.addControlCategory(SampleMediaRouteProvider.CATEGORY_SAMPLE_ROUTE)
.build();
// Add a fragment to take care of media route discovery.
// This fragment automatically adds or removes a callback whenever the activity
// is started or stopped.
FragmentManager fm = getSupportFragmentManager();
if (fm.findFragmentByTag(DISCOVERY_FRAGMENT_TAG) == null) {
DiscoveryFragment fragment = new DiscoveryFragment();
fragment.setRouteSelector(mSelector);
fm.beginTransaction()
.add(fragment, DISCOVERY_FRAGMENT_TAG)
.commit();
}
// 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
public void onStart() {
// Be sure to call the super class.
super.onStart();
updateRouteDescription();
}
@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);
MenuItem mediaRouteMenuItem = menu.findItem(R.id.media_route_menu_item);
MediaRouteActionProvider mediaRouteActionProvider =
(MediaRouteActionProvider)MenuItemCompat.getActionProvider(mediaRouteMenuItem);
mediaRouteActionProvider.setRouteSelector(mSelector);
// Return true to show the menu.
return true;
}
private void updateRouteDescription() {
RouteInfo route = mMediaRouter.getSelectedRoute();
mInfoTextView.setText("Currently selected route: " + route.getName()
+ " from provider " + route.getProvider().getPackageName()
+ ", description: " + route.getDescription());
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(Bundle data) {
String streamId = data != null ? data.getString(
MediaControlIntent.EXTRA_ITEM_ID) : null;
Log.d(TAG, "Play request succeeded: data=" + data + " , streamId=" + streamId);
Toast.makeText(SampleMediaRouterActivity.this,
"Now playing " + item.mName,
Toast.LENGTH_LONG).show();
}
@Override
public void onError(String error, Bundle data) {
Log.d(TAG, "Play request failed: error=" + error + ", data=" + data);
Toast.makeText(SampleMediaRouterActivity.this,
"Unable to play " + item.mName + ", error: " + error,
Toast.LENGTH_LONG).show();
}
};
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(Bundle data) {
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();
}
}
@Override
public void onError(String error, Bundle data) {
Log.d(TAG, "Statistics request failed: error=" + error + ", data=" + data);
Toast.makeText(SampleMediaRouterActivity.this,
"Unable to query statistics, error: " + error,
Toast.LENGTH_LONG).show();
}
};
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 class DiscoveryFragment extends MediaRouteDiscoveryFragment {
@Override
public Callback onCreateCallback() {
// Return a custom callback that will simply log all of the route events
// for demonstration purposes.
return 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);
updateRouteDescription();
}
@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);
updateRouteDescription();
}
@Override
public void onRouteUnselected(MediaRouter router, RouteInfo route) {
Log.d(TAG, "onRouteUnselected: route=" + route);
updateRouteDescription();
}
@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);
}
@Override
public void onProviderChanged(MediaRouter router, ProviderInfo provider) {
Log.d(TAG, "onRouteProviderChanged: provider=" + provider);
}
};
}
@Override
public int onPrepareCallbackFlags() {
// Add the CALLBACK_FLAG_UNFILTERED_EVENTS flag to ensure that we will
// observe and log all route events including those that are for routes
// that do not match our selector. This is only for demonstration purposes
// and should not be needed by most applications.
return super.onPrepareCallbackFlags()
| MediaRouter.CALLBACK_FLAG_UNFILTERED_EVENTS;
}
}
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;
}
}
/**
* Trivial subclass of this activity used to provide another copy of the
* same activity using a light theme instead of the dark theme.
*/
public static class Light extends SampleMediaRouterActivity {
}
/**
* Trivial subclass of this activity used to provide another copy of the
* same activity using a light theme with dark action bar instead of the dark theme.
*/
public static class LightWithDarkActionBar extends SampleMediaRouterActivity {
}
}