am b7e8a4ec: Merge "Add a demo for using Presentations with the MediaRouter." into jb-mr1-dev
* commit 'b7e8a4ecb1b5f5a46e8e5c42c29425bbb16fc2fc': Add a demo for using Presentations with the MediaRouter.
This commit is contained in:
@@ -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>
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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>
|
||||
@@ -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" />
|
||||
@@ -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>
|
||||
@@ -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.
|
||||
|
||||
@@ -30,6 +30,9 @@ import android.graphics.Point;
|
||||
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.ImageView;
|
||||
import android.widget.ListView;
|
||||
import android.widget.TextView;
|
||||
|
||||
//BEGIN_INCLUDE(activity)
|
||||
/**
|
||||
* <h3>Presentation Activity</h3>
|
||||
*
|
||||
@@ -52,18 +56,32 @@ import android.widget.TextView;
|
||||
* 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 @@ public class PresentationActivity extends Activity
|
||||
|
||||
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 @@ public class PresentationActivity extends Activity
|
||||
// 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 @@ public class PresentationActivity extends Activity
|
||||
// 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 @@ public class PresentationActivity extends Activity
|
||||
// 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 @@ public class PresentationActivity extends Activity
|
||||
// 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 @@ public class PresentationActivity extends Activity
|
||||
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 @@ public class PresentationActivity extends Activity
|
||||
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 @@ public class PresentationActivity extends Activity
|
||||
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 @@ public class PresentationActivity extends Activity
|
||||
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 class PresentationActivity extends Activity
|
||||
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 @@ public class PresentationActivity extends Activity
|
||||
|
||||
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 class PresentationActivity extends Activity
|
||||
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 @@ public class PresentationActivity extends Activity
|
||||
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 @@ public class PresentationActivity extends Activity
|
||||
|
||||
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 @@ public class PresentationActivity extends Activity
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
|
||||
@@ -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)
|
||||
@@ -51,6 +51,8 @@ import android.view.WindowManager;
|
||||
* </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 @@ public class SecureSurfaceViewActivity extends Activity {
|
||||
// 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();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user