Merge "Add a demo for using Presentations with the MediaRouter." into jb-mr1-dev
diff --git a/samples/ApiDemos/AndroidManifest.xml b/samples/ApiDemos/AndroidManifest.xml
index b7f6819..8db231c 100644
--- a/samples/ApiDemos/AndroidManifest.xml
+++ b/samples/ApiDemos/AndroidManifest.xml
@@ -262,6 +262,14 @@
</intent-filter>
</activity>
+ <activity android:name=".app.PresentationWithMediaRouterActivity"
+ android:label="@string/activity_presentation_with_media_router">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
+
<activity android:name=".app.SecureWindowActivity"
android:label="@string/activity_secure_window">
<intent-filter>
diff --git a/samples/ApiDemos/res/layout/presentation_activity.xml b/samples/ApiDemos/res/layout/presentation_activity.xml
index 62670e4..52c5022 100644
--- a/samples/ApiDemos/res/layout/presentation_activity.xml
+++ b/samples/ApiDemos/res/layout/presentation_activity.xml
@@ -32,6 +32,13 @@
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="@string/presentation_activity_text"/>
+ <!-- A checkbox to toggle between showing all displays or only presentation displays. -->
+ <CheckBox android:id="@+id/show_all_displays"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_weight="0"
+ android:text="@string/presentation_show_all_displays" />
+
<!-- List that will show information about all connected displays. -->
<ListView android:id="@+id/display_list"
android:layout_width="match_parent"
diff --git a/samples/ApiDemos/res/layout/presentation_with_media_router_activity.xml b/samples/ApiDemos/res/layout/presentation_with_media_router_activity.xml
new file mode 100644
index 0000000..005002c
--- /dev/null
+++ b/samples/ApiDemos/res/layout/presentation_with_media_router_activity.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2012 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 PresentationWithMediaRouterActivity.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/presentation_with_media_router_activity_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 content for visual interest in the case where no presentation is showing. -->
+ <android.opengl.GLSurfaceView android:id="@+id/surface_view"
+ android:layout_width="match_parent"
+ android:layout_height="0dp"
+ android:layout_weight="1" />
+</LinearLayout>
diff --git a/samples/ApiDemos/res/layout/presentation_with_media_router_content.xml b/samples/ApiDemos/res/layout/presentation_with_media_router_content.xml
new file mode 100644
index 0000000..8eb981b
--- /dev/null
+++ b/samples/ApiDemos/res/layout/presentation_with_media_router_content.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2012 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.
+-->
+
+<!-- The content that we show on secondary displays.
+ See corresponding Java code PresentationWithMediaRouterActivity.java. -->
+
+<android.opengl.GLSurfaceView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/surface_view"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" />
diff --git a/samples/ApiDemos/res/menu/presentation_with_media_router_menu.xml b/samples/ApiDemos/res/menu/presentation_with_media_router_menu.xml
new file mode 100644
index 0000000..08ef0dc
--- /dev/null
+++ b/samples/ApiDemos/res/menu/presentation_with_media_router_menu.xml
@@ -0,0 +1,23 @@
+<?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">
+ <item android:id="@+id/menu_media_route"
+ android:title="@string/presentation_with_media_router_play_on"
+ android:showAsAction="always"
+ android:orderInCategory="1"
+ android:actionProviderClass="android.app.MediaRouteActionProvider"/>
+</menu>
diff --git a/samples/ApiDemos/res/values/strings.xml b/samples/ApiDemos/res/values/strings.xml
index 9d8616d..6211a0d 100644
--- a/samples/ApiDemos/res/values/strings.xml
+++ b/samples/ApiDemos/res/values/strings.xml
@@ -113,15 +113,27 @@
<string name="apply">Apply</string>
<string name="activity_presentation">App/Activity/Presentation</string>
- <string name="presentation_activity_text">This activity demonstrates how to use the Presentation activity to show content on other Displays.\n
+ <string name="presentation_activity_text">This activity demonstrates how to use a
+ Presentation and the DisplayManager to show content on other Displays.\n
Try connecting a secondary display and watch what happens.\n
Selecting a Display will open a Presentation on it.</string>
- <string name="presentation_channel_text">You\'re watching channel %1$d on display %2$d.</string>
+ <string name="presentation_show_all_displays">Show all displays</string>
+ <string name="presentation_photo_text">Showing photo #%1$d on display #%2$d: %3$s.</string>
<string name="presentation_info_text">Info</string>
- <string name="presentation_display_id_text">Display #%1$d</string>
- <string name="presentation_alert_info_text">Display %1$d Info</string>
+ <string name="presentation_display_id_text">Display #%1$d: %2$s</string>
+ <string name="presentation_alert_info_text">Display #%1$d Info</string>
<string name="presentation_alert_dismiss_text">OK</string>
+ <string name="activity_presentation_with_media_router">App/Activity/Presentation with Media Router</string>
+ <string name="presentation_with_media_router_activity_text">This activity demonstrates how to
+ use a Presentation and the MediaRouter to automatically
+ show content on a secondary display when available based on the currently
+ selected media route.\n
+ Try connecting a secondary display and watch what happens.</string>
+ <string name="presentation_with_media_router_play_on">Play on...</string>
+ <string name="presentation_with_media_router_now_playing_locally">Now playing on main display \'%s\'.</string>
+ <string name="presentation_with_media_router_now_playing_remotely">Now playing on secondary display \'%s\'.</string>
+
<string name="activity_secure_window">App/Activity/Secure Surfaces/Secure Window</string>
<string name="secure_window_activity_text">This activity demonstrates how to make an activity
use a secure surface so that its contents will only be visible on secure displays.
diff --git a/samples/ApiDemos/src/com/example/android/apis/app/PresentationActivity.java b/samples/ApiDemos/src/com/example/android/apis/app/PresentationActivity.java
index 3e561aa..c626022 100644
--- a/samples/ApiDemos/src/com/example/android/apis/app/PresentationActivity.java
+++ b/samples/ApiDemos/src/com/example/android/apis/app/PresentationActivity.java
@@ -30,6 +30,9 @@
import android.graphics.drawable.GradientDrawable;
import android.hardware.display.DisplayManager;
import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.os.Parcelable.Creator;
import android.util.Log;
import android.util.SparseArray;
import android.view.Display;
@@ -45,6 +48,7 @@
import android.widget.ListView;
import android.widget.TextView;
+//BEGIN_INCLUDE(activity)
/**
* <h3>Presentation Activity</h3>
*
@@ -52,18 +56,32 @@
* This demonstrates how to create an activity that shows some content
* on a secondary display using a {@link Presentation}.
* </p><p>
- * The activity automatically creates and displays a {@link Presentation} whenever
- * a new non-default display is detected. You can try this out by using
- * the "Simulate secondary displays" feature in Development Settings to create
- * a few simulated secondary displays.
+ * The activity uses the {@link DisplayManager} API to enumerate displays.
+ * When the user selects a display, the activity opens a {@link Presentation}
+ * on that display. We show a different photograph in each presentation
+ * on a unique background along with a label describing the display.
+ * We also write information about displays and display-related events to
+ * the Android log which you can read using <code>adb logcat</code>.
+ * </p><p>
+ * You can try this out using an HDMI or Wifi display or by using the
+ * "Simulate secondary displays" feature in Development Settings to create a few
+ * simulated secondary displays. Each display will appear in the list along with a
+ * checkbox to show a presentation on that display.
+ * </p><p>
+ * See also the {@link PresentationWithMediaRouterActivity} sample which
+ * uses the media router to automatically select a secondary display
+ * on which to show content based on the currently selected route.
* </p>
*/
public class PresentationActivity extends Activity
implements OnCheckedChangeListener, OnClickListener {
private final String TAG = "PresentationActivity";
+ // Key for storing saved instance state.
+ private static final String PRESENTATION_KEY = "presentation";
+
// The content that we want to show on the presentation.
- private static final int[] CHANNELS = new int[] {
+ private static final int[] PHOTOS = new int[] {
R.drawable.frantic,
R.drawable.photo1, R.drawable.photo2, R.drawable.photo3,
R.drawable.photo4, R.drawable.photo5, R.drawable.photo6,
@@ -72,14 +90,16 @@
private DisplayManager mDisplayManager;
private DisplayListAdapter mDisplayListAdapter;
+ private CheckBox mShowAllDisplaysCheckbox;
private ListView mListView;
- private int mNextChannelNumber;
+ private int mNextImageNumber;
- // Indexed by displayId. Persists across pause/resume.
- private final SparseArray<PresentationContents> mSavedPresentationContents =
- new SparseArray<PresentationContents>();
+ // List of presentation contents indexed by displayId.
+ // This state persists so that we can restore the old presentation
+ // contents when the activity is paused or resumed.
+ private SparseArray<PresentationContents> mSavedPresentationContents;
- // Indexed by displayId. Contains all currently displayed Presentations.
+ // List of all currently visible presentations indexed by display id.
private final SparseArray<DemoPresentation> mActivePresentations =
new SparseArray<DemoPresentation>();
@@ -93,6 +113,14 @@
// Be sure to call the super class.
super.onCreate(savedInstanceState);
+ // Restore saved instance state.
+ if (savedInstanceState != null) {
+ mSavedPresentationContents =
+ savedInstanceState.getSparseParcelableArray(PRESENTATION_KEY);
+ } else {
+ mSavedPresentationContents = new SparseArray<PresentationContents>();
+ }
+
// Get the display manager service.
mDisplayManager = (DisplayManager)getSystemService(Context.DISPLAY_SERVICE);
@@ -101,6 +129,11 @@
// the content of our screen.
setContentView(R.layout.presentation_activity);
+ // Set up checkbox to toggle between showing all displays or only presentation displays.
+ mShowAllDisplaysCheckbox = (CheckBox)findViewById(R.id.show_all_displays);
+ mShowAllDisplaysCheckbox.setOnCheckedChangeListener(this);
+
+ // Set up the list of displays.
mDisplayListAdapter = new DisplayListAdapter(this);
mListView = (ListView)findViewById(R.id.display_list);
mListView.setAdapter(mDisplayListAdapter);
@@ -114,6 +147,7 @@
// Update our list of displays on resume.
mDisplayListAdapter.updateContents();
+ // Restore presentations from before the activity was paused.
final int numDisplays = mDisplayListAdapter.getCount();
for (int i = 0; i < numDisplays; i++) {
final Display display = mDisplayListAdapter.getItem(i);
@@ -137,7 +171,7 @@
// Unregister from the display manager.
mDisplayManager.unregisterDisplayListener(mDisplayListener);
- // Dismiss all of our presentations.
+ // Dismiss all of our presentations but remember their contents.
Log.d(TAG, "Activity is being paused. Dismissing all active presentation.");
for (int i = 0; i < mActivePresentations.size(); i++) {
DemoPresentation presentation = mActivePresentations.valueAt(i);
@@ -148,6 +182,13 @@
mActivePresentations.clear();
}
+ @Override
+ protected void onSaveInstanceState(Bundle outState) {
+ // Be sure to call the super class.
+ super.onSaveInstanceState(outState);
+ outState.putSparseParcelableArray(PRESENTATION_KEY, mSavedPresentationContents);
+ }
+
/**
* Shows a {@link Presentation} on the specified display.
*/
@@ -157,8 +198,8 @@
return;
}
- Log.d(TAG, "Showing presentation channel " + contents.channel
- + " on display " + displayId + ".");
+ Log.d(TAG, "Showing presentation photo #" + contents.photo
+ + " on display #" + displayId + ".");
DemoPresentation presentation = new DemoPresentation(this, display, contents);
presentation.show();
@@ -176,32 +217,44 @@
return;
}
- Log.d(TAG, "Dismissing presentation on display " + displayId + ".");
+ Log.d(TAG, "Dismissing presentation on display #" + displayId + ".");
presentation.dismiss();
mActivePresentations.delete(displayId);
}
- private int getNextChannel() {
- final int channel = mNextChannelNumber;
- mNextChannelNumber = (mNextChannelNumber + 1) % CHANNELS.length;
- return channel;
+ private int getNextPhoto() {
+ final int photo = mNextImageNumber;
+ mNextImageNumber = (mNextImageNumber + 1) % PHOTOS.length;
+ return photo;
}
+ /**
+ * Called when the show all displays checkbox is toggled or when
+ * an item in the list of displays is checked or unchecked.
+ */
@Override
- /** Presentation CheckBox */
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
- final Display display = (Display)buttonView.getTag();
- if (isChecked) {
- PresentationContents contents = new PresentationContents(getNextChannel());
- showPresentation(display, contents);
+ if (buttonView == mShowAllDisplaysCheckbox) {
+ // Show all displays checkbox was toggled.
+ mDisplayListAdapter.updateContents();
} else {
- hidePresentation(display);
+ // Display item checkbox was toggled.
+ final Display display = (Display)buttonView.getTag();
+ if (isChecked) {
+ PresentationContents contents = new PresentationContents(getNextPhoto());
+ showPresentation(display, contents);
+ } else {
+ hidePresentation(display);
+ }
}
}
+ /**
+ * Called when the Info button next to a display is clicked to show information
+ * about the display.
+ */
@Override
- /** Info Button */
public void onClick(View v) {
Context context = v.getContext();
AlertDialog.Builder builder = new AlertDialog.Builder(context);
@@ -235,19 +288,19 @@
new DisplayManager.DisplayListener() {
@Override
public void onDisplayAdded(int displayId) {
- Log.d(TAG, "Display " + displayId + " added.");
+ Log.d(TAG, "Display #" + displayId + " added.");
mDisplayListAdapter.updateContents();
}
@Override
public void onDisplayChanged(int displayId) {
- Log.d(TAG, "Display " + displayId + " changed.");
+ Log.d(TAG, "Display #" + displayId + " changed.");
mDisplayListAdapter.updateContents();
}
@Override
public void onDisplayRemoved(int displayId) {
- Log.d(TAG, "Display " + displayId + " removed.");
+ Log.d(TAG, "Display #" + displayId + " removed.");
mDisplayListAdapter.updateContents();
}
};
@@ -261,7 +314,7 @@
public void onDismiss(DialogInterface dialog) {
DemoPresentation presentation = (DemoPresentation)dialog;
int displayId = presentation.getDisplay().getDisplayId();
- Log.d(TAG, "Presentation on display " + displayId + " was dismissed.");
+ Log.d(TAG, "Presentation on display #" + displayId + " was dismissed.");
mActivePresentations.delete(displayId);
mDisplayListAdapter.notifyDataSetChanged();
}
@@ -300,7 +353,7 @@
TextView tv = (TextView)v.findViewById(R.id.display_id);
tv.setText(v.getContext().getResources().getString(
- R.string.presentation_display_id_text, displayId));
+ R.string.presentation_display_id_text, displayId, display.getName()));
Button b = (Button)v.findViewById(R.id.info);
b.setTag(display);
@@ -316,7 +369,8 @@
public void updateContents() {
clear();
- Display[] displays = mDisplayManager.getDisplays();
+ String displayCategory = getDisplayCategory();
+ Display[] displays = mDisplayManager.getDisplays(displayCategory);
addAll(displays);
Log.d(TAG, "There are currently " + displays.length + " displays connected.");
@@ -324,12 +378,17 @@
Log.d(TAG, " " + display);
}
}
+
+ private String getDisplayCategory() {
+ return mShowAllDisplaysCheckbox.isChecked() ? null :
+ DisplayManager.DISPLAY_CATEGORY_PRESENTATION;
+ }
}
/**
* The presentation to show on the secondary display.
*
- * Note that this display may have different metrics from the display on which
+ * Note that the presentation display may have different metrics from the display on which
* the main activity is showing so we must be careful to use the presentation's
* own {@link Context} whenever we load resources.
*/
@@ -356,15 +415,16 @@
final Display display = getDisplay();
final int displayId = display.getDisplayId();
- final int channel = mContents.channel;
+ final int photo = mContents.photo;
- // Show a text message to describe what's going on.
+ // Show a caption to describe what's going on.
TextView text = (TextView)findViewById(R.id.text);
- text.setText(r.getString(R.string.presentation_channel_text, channel, displayId));
+ text.setText(r.getString(R.string.presentation_photo_text,
+ photo, displayId, display.getName()));
// Show a n image for visual interest.
ImageView image = (ImageView)findViewById(R.id.image);
- image.setImageDrawable(r.getDrawable(CHANNELS[channel]));
+ image.setImageDrawable(r.getDrawable(PHOTOS[photo]));
GradientDrawable drawable = new GradientDrawable();
drawable.setShape(GradientDrawable.RECTANGLE);
@@ -379,15 +439,49 @@
}
}
- private final static class PresentationContents {
- final int channel;
+ /**
+ * Information about the content we want to show in a presentation.
+ */
+ private final static class PresentationContents implements Parcelable {
+ final int photo;
final int[] colors;
- public PresentationContents(int channel) {
- this.channel = channel;
+ public static final Creator<PresentationContents> CREATOR =
+ new Creator<PresentationContents>() {
+ @Override
+ public PresentationContents createFromParcel(Parcel in) {
+ return new PresentationContents(in);
+ }
+
+ @Override
+ public PresentationContents[] newArray(int size) {
+ return new PresentationContents[size];
+ }
+ };
+
+ public PresentationContents(int photo) {
+ this.photo = photo;
colors = new int[] {
((int) (Math.random() * Integer.MAX_VALUE)) | 0xFF000000,
((int) (Math.random() * Integer.MAX_VALUE)) | 0xFF000000 };
}
+
+ private PresentationContents(Parcel in) {
+ photo = in.readInt();
+ colors = new int[] { in.readInt(), in.readInt() };
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeInt(photo);
+ dest.writeInt(colors[0]);
+ dest.writeInt(colors[1]);
+ }
}
}
+//END_INCLUDE(activity)
diff --git a/samples/ApiDemos/src/com/example/android/apis/app/PresentationWithMediaRouterActivity.java b/samples/ApiDemos/src/com/example/android/apis/app/PresentationWithMediaRouterActivity.java
new file mode 100644
index 0000000..5ba476e
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/app/PresentationWithMediaRouterActivity.java
@@ -0,0 +1,290 @@
+/*
+ * Copyright (C) 2012 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.apis.app;
+
+import com.example.android.apis.R;
+import com.example.android.apis.graphics.CubeRenderer;
+
+import android.app.Activity;
+import android.app.MediaRouteActionProvider;
+import android.app.Presentation;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.res.Resources;
+import android.media.MediaRouter;
+import android.media.MediaRouter.RouteInfo;
+import android.opengl.GLSurfaceView;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.Display;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.WindowManager;
+import android.widget.TextView;
+
+//BEGIN_INCLUDE(activity)
+/**
+ * <h3>Presentation Activity</h3>
+ *
+ * <p>
+ * This demonstrates how to create an activity that shows some content
+ * on a secondary display using a {@link Presentation}.
+ * </p><p>
+ * The activity uses the {@link MediaRouter} API to automatically detect when
+ * a presentation display is available and to allow the user to control the
+ * media routes using a menu item. When a presentation display is available,
+ * we stop showing content in the main activity and instead open up a
+ * {@link Presentation} on the preferred presentation display. When a presentation
+ * display is removed, we revert to showing content in the main activity.
+ * We also write information about displays and display-related events to
+ * the Android log which you can read using <code>adb logcat</code>.
+ * </p><p>
+ * You can try this out using an HDMI or Wifi display or by using the
+ * "Simulate secondary displays" feature in Development Settings to create a few
+ * simulated secondary displays. Each display will appear in the list along with a
+ * checkbox to show a presentation on that display.
+ * </p><p>
+ * See also the {@link PresentationActivity} sample which
+ * uses the low-level display manager to enumerate displays and to show multiple
+ * simultaneous presentations on different displays.
+ * </p>
+ */
+public class PresentationWithMediaRouterActivity extends Activity {
+ private final String TAG = "PresentationWithMediaRouterActivity";
+
+ private MediaRouter mMediaRouter;
+ private DemoPresentation mPresentation;
+ private GLSurfaceView mSurfaceView;
+ private TextView mInfoTextView;
+ private boolean mPaused;
+
+ /**
+ * Initialization of the Activity after it is first created. Must at least
+ * call {@link android.app.Activity#setContentView setContentView()} to
+ * describe what is to be displayed in the screen.
+ */
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ // Be sure to call the super class.
+ super.onCreate(savedInstanceState);
+
+ // Get the media router service.
+ mMediaRouter = (MediaRouter)getSystemService(Context.MEDIA_ROUTER_SERVICE);
+
+ // See assets/res/any/layout/presentation_with_media_router_activity.xml for this
+ // view layout definition, which is being set here as
+ // the content of our screen.
+ setContentView(R.layout.presentation_with_media_router_activity);
+
+ // Set up the surface view for visual interest.
+ mSurfaceView = (GLSurfaceView)findViewById(R.id.surface_view);
+ mSurfaceView.setRenderer(new CubeRenderer(false));
+
+ // Get a text view where we will show information about what's happening.
+ mInfoTextView = (TextView)findViewById(R.id.info);
+ }
+
+ @Override
+ protected void onResume() {
+ // Be sure to call the super class.
+ super.onResume();
+
+ // Listen for changes to media routes.
+ mMediaRouter.addCallback(MediaRouter.ROUTE_TYPE_LIVE_VIDEO, mMediaRouterCallback);
+
+ // Update the presentation based on the currently selected route.
+ mPaused = false;
+ updatePresentation();
+ }
+
+ @Override
+ protected void onPause() {
+ // Be sure to call the super class.
+ super.onPause();
+
+ // Stop listening for changes to media routes.
+ mMediaRouter.removeCallback(mMediaRouterCallback);
+
+ // Pause rendering.
+ mPaused = true;
+ updateContents();
+ }
+
+ @Override
+ protected void onStop() {
+ // Be sure to call the super class.
+ super.onStop();
+
+ // Dismiss the presentation when the activity is not visible.
+ if (mPresentation != null) {
+ Log.i(TAG, "Dismissing presentation because the activity is no longer visible.");
+ mPresentation.dismiss();
+ mPresentation = null;
+ }
+ }
+
+ @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.presentation_with_media_router_menu, menu);
+
+ MenuItem mediaRouteMenuItem = menu.findItem(R.id.menu_media_route);
+ MediaRouteActionProvider mediaRouteActionProvider =
+ (MediaRouteActionProvider)mediaRouteMenuItem.getActionProvider();
+ mediaRouteActionProvider.setRouteTypes(MediaRouter.ROUTE_TYPE_LIVE_VIDEO);
+
+ // Return true to show the menu.
+ return true;
+ }
+
+ private void updatePresentation() {
+ // Get the current route and its presentation display.
+ MediaRouter.RouteInfo route = mMediaRouter.getSelectedRoute(
+ MediaRouter.ROUTE_TYPE_LIVE_VIDEO);
+ Display presentationDisplay = route != null ? route.getPresentationDisplay() : null;
+
+ // Dismiss the current presentation if the display has changed.
+ if (mPresentation != null && mPresentation.getDisplay() != presentationDisplay) {
+ Log.i(TAG, "Dismissing presentation because the current route no longer "
+ + "has a presentation display.");
+ mPresentation.dismiss();
+ mPresentation = null;
+ }
+
+ // Show a new presentation if needed.
+ if (mPresentation == null && presentationDisplay != null) {
+ Log.i(TAG, "Showing presentation on display: " + presentationDisplay);
+ mPresentation = new DemoPresentation(this, presentationDisplay);
+ mPresentation.setOnDismissListener(mOnDismissListener);
+ try {
+ mPresentation.show();
+ } catch (WindowManager.InvalidDisplayException ex) {
+ Log.w(TAG, "Couldn't show presentation! Display was removed in "
+ + "the meantime.", ex);
+ mPresentation = null;
+ }
+ }
+
+ // Update the contents playing in this activity.
+ updateContents();
+ }
+
+ private void updateContents() {
+ // Show either the content in the main activity or the content in the presentation
+ // along with some descriptive text about what is happening.
+ if (mPresentation != null) {
+ mInfoTextView.setText(getResources().getString(
+ R.string.presentation_with_media_router_now_playing_remotely,
+ mPresentation.getDisplay().getName()));
+ mSurfaceView.setVisibility(View.INVISIBLE);
+ mSurfaceView.onPause();
+ if (mPaused) {
+ mPresentation.getSurfaceView().onPause();
+ } else {
+ mPresentation.getSurfaceView().onResume();
+ }
+ } else {
+ mInfoTextView.setText(getResources().getString(
+ R.string.presentation_with_media_router_now_playing_locally,
+ getWindowManager().getDefaultDisplay().getName()));
+ mSurfaceView.setVisibility(View.VISIBLE);
+ if (mPaused) {
+ mSurfaceView.onPause();
+ } else {
+ mSurfaceView.onResume();
+ }
+ }
+ }
+
+ private final MediaRouter.SimpleCallback mMediaRouterCallback =
+ new MediaRouter.SimpleCallback() {
+ @Override
+ public void onRouteSelected(MediaRouter router, int type, RouteInfo info) {
+ Log.d(TAG, "onRouteSelected: type=" + type + ", info=" + info);
+ updatePresentation();
+ }
+
+ @Override
+ public void onRouteUnselected(MediaRouter router, int type, RouteInfo info) {
+ Log.d(TAG, "onRouteUnselected: type=" + type + ", info=" + info);
+ updatePresentation();
+ }
+
+ @Override
+ public void onRoutePresentationDisplayChanged(MediaRouter router, RouteInfo info) {
+ Log.d(TAG, "onRoutePresentationDisplayChanged: info=" + info);
+ updatePresentation();
+ }
+ };
+
+ /**
+ * Listens for when presentations are dismissed.
+ */
+ private final DialogInterface.OnDismissListener mOnDismissListener =
+ new DialogInterface.OnDismissListener() {
+ @Override
+ public void onDismiss(DialogInterface dialog) {
+ if (dialog == mPresentation) {
+ Log.i(TAG, "Presentation was dismissed.");
+ mPresentation = null;
+ updateContents();
+ }
+ }
+ };
+
+ /**
+ * The presentation to show on the secondary display.
+ * <p>
+ * Note that this display may have different metrics from the display on which
+ * the main activity is showing so we must be careful to use the presentation's
+ * own {@link Context} whenever we load resources.
+ * </p>
+ */
+ private final static class DemoPresentation extends Presentation {
+ private GLSurfaceView mSurfaceView;
+
+ public DemoPresentation(Context context, Display display) {
+ super(context, display);
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ // Be sure to call the super class.
+ super.onCreate(savedInstanceState);
+
+ // Get the resources for the context of the presentation.
+ // Notice that we are getting the resources from the context of the presentation.
+ Resources r = getContext().getResources();
+
+ // Inflate the layout.
+ setContentView(R.layout.presentation_with_media_router_content);
+
+ // Set up the surface view for visual interest.
+ mSurfaceView = (GLSurfaceView)findViewById(R.id.surface_view);
+ mSurfaceView.setRenderer(new CubeRenderer(false));
+ }
+
+ public GLSurfaceView getSurfaceView() {
+ return mSurfaceView;
+ }
+ }
+}
+//END_INCLUDE(activity)
diff --git a/samples/ApiDemos/src/com/example/android/apis/app/SecureSurfaceViewActivity.java b/samples/ApiDemos/src/com/example/android/apis/app/SecureSurfaceViewActivity.java
index 2c3abed..978c70c 100644
--- a/samples/ApiDemos/src/com/example/android/apis/app/SecureSurfaceViewActivity.java
+++ b/samples/ApiDemos/src/com/example/android/apis/app/SecureSurfaceViewActivity.java
@@ -51,6 +51,8 @@
* </p>
*/
public class SecureSurfaceViewActivity extends Activity {
+ private GLSurfaceView mSurfaceView;
+
/**
* Initialization of the Activity after it is first created. Must at least
* call {@link android.app.Activity#setContentView setContentView()} to
@@ -69,13 +71,31 @@
// Set up the surface view.
// We use a GLSurfaceView in this demonstration but ordinary
// SurfaceViews also support the same secure surface functionality.
- GLSurfaceView surfaceView = (GLSurfaceView)findViewById(R.id.surface_view);
- surfaceView.setRenderer(new CubeRenderer(false));
+ mSurfaceView = (GLSurfaceView)findViewById(R.id.surface_view);
+ mSurfaceView.setRenderer(new CubeRenderer(false));
// Make the surface view secure. This must be done at the time the surface view
// is created before the surface view's containing window is attached to
// the window manager which happens after onCreate returns.
// It cannot be changed later.
- surfaceView.setSecure(true);
+ mSurfaceView.setSecure(true);
+ }
+
+ @Override
+ protected void onResume() {
+ // Be sure to call the super class.
+ super.onResume();
+
+ // Resume rendering.
+ mSurfaceView.onResume();
+ }
+
+ @Override
+ protected void onPause() {
+ // Be sure to call the super class.
+ super.onPause();
+
+ // Pause rendering.
+ mSurfaceView.onPause();
}
}