1 /* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.example.android.apis.app; 18 19 import com.example.android.apis.R; 20 import com.example.android.apis.graphics.CubeRenderer; 21 22 import android.app.Activity; 23 import android.app.MediaRouteActionProvider; 24 import android.app.Presentation; 25 import android.content.Context; 26 import android.content.DialogInterface; 27 import android.content.res.Resources; 28 import android.media.MediaRouter; 29 import android.media.MediaRouter.RouteInfo; 30 import android.opengl.GLSurfaceView; 31 import android.os.Bundle; 32 import android.util.Log; 33 import android.view.Display; 34 import android.view.Menu; 35 import android.view.MenuItem; 36 import android.view.View; 37 import android.view.WindowManager; 38 import android.widget.TextView; 39 40 //BEGIN_INCLUDE(activity) 41 /** 42 * <h3>Presentation Activity</h3> 43 * 44 * <p> 45 * This demonstrates how to create an activity that shows some content 46 * on a secondary display using a {@link Presentation}. 47 * </p><p> 48 * The activity uses the {@link MediaRouter} API to automatically detect when 49 * a presentation display is available and to allow the user to control the 50 * media routes using a menu item. When a presentation display is available, 51 * we stop showing content in the main activity and instead open up a 52 * {@link Presentation} on the preferred presentation display. When a presentation 53 * display is removed, we revert to showing content in the main activity. 54 * We also write information about displays and display-related events to 55 * the Android log which you can read using <code>adb logcat</code>. 56 * </p><p> 57 * You can try this out using an HDMI or Wifi display or by using the 58 * "Simulate secondary displays" feature in Development Settings to create a few 59 * simulated secondary displays. Each display will appear in the list along with a 60 * checkbox to show a presentation on that display. 61 * </p><p> 62 * See also the {@link PresentationActivity} sample which 63 * uses the low-level display manager to enumerate displays and to show multiple 64 * simultaneous presentations on different displays. 65 * </p> 66 */ 67 public class PresentationWithMediaRouterActivity extends Activity { 68 private final String TAG = "PresentationWithMediaRouterActivity"; 69 70 private MediaRouter mMediaRouter; 71 private DemoPresentation mPresentation; 72 private GLSurfaceView mSurfaceView; 73 private TextView mInfoTextView; 74 private boolean mPaused; 75 76 /** 77 * Initialization of the Activity after it is first created. Must at least 78 * call {@link android.app.Activity#setContentView setContentView()} to 79 * describe what is to be displayed in the screen. 80 */ 81 @Override onCreate(Bundle savedInstanceState)82 protected void onCreate(Bundle savedInstanceState) { 83 // Be sure to call the super class. 84 super.onCreate(savedInstanceState); 85 86 // Get the media router service. 87 mMediaRouter = (MediaRouter)getSystemService(Context.MEDIA_ROUTER_SERVICE); 88 89 // See assets/res/any/layout/presentation_with_media_router_activity.xml for this 90 // view layout definition, which is being set here as 91 // the content of our screen. 92 setContentView(R.layout.presentation_with_media_router_activity); 93 94 // Set up the surface view for visual interest. 95 mSurfaceView = (GLSurfaceView)findViewById(R.id.surface_view); 96 mSurfaceView.setRenderer(new CubeRenderer(false)); 97 98 // Get a text view where we will show information about what's happening. 99 mInfoTextView = (TextView)findViewById(R.id.info); 100 } 101 102 @Override onResume()103 protected void onResume() { 104 // Be sure to call the super class. 105 super.onResume(); 106 107 // Listen for changes to media routes. 108 mMediaRouter.addCallback(MediaRouter.ROUTE_TYPE_LIVE_VIDEO, mMediaRouterCallback); 109 110 // Update the presentation based on the currently selected route. 111 mPaused = false; 112 updatePresentation(); 113 } 114 115 @Override onPause()116 protected void onPause() { 117 // Be sure to call the super class. 118 super.onPause(); 119 120 // Stop listening for changes to media routes. 121 mMediaRouter.removeCallback(mMediaRouterCallback); 122 123 // Pause rendering. 124 mPaused = true; 125 updateContents(); 126 } 127 128 @Override onStop()129 protected void onStop() { 130 // Be sure to call the super class. 131 super.onStop(); 132 133 // Dismiss the presentation when the activity is not visible. 134 if (mPresentation != null) { 135 Log.i(TAG, "Dismissing presentation because the activity is no longer visible."); 136 mPresentation.dismiss(); 137 mPresentation = null; 138 } 139 } 140 141 @Override onCreateOptionsMenu(Menu menu)142 public boolean onCreateOptionsMenu(Menu menu) { 143 // Be sure to call the super class. 144 super.onCreateOptionsMenu(menu); 145 146 // Inflate the menu and configure the media router action provider. 147 getMenuInflater().inflate(R.menu.presentation_with_media_router_menu, menu); 148 149 MenuItem mediaRouteMenuItem = menu.findItem(R.id.menu_media_route); 150 MediaRouteActionProvider mediaRouteActionProvider = 151 (MediaRouteActionProvider)mediaRouteMenuItem.getActionProvider(); 152 mediaRouteActionProvider.setRouteTypes(MediaRouter.ROUTE_TYPE_LIVE_VIDEO); 153 154 // Return true to show the menu. 155 return true; 156 } 157 updatePresentation()158 private void updatePresentation() { 159 // Get the current route and its presentation display. 160 MediaRouter.RouteInfo route = mMediaRouter.getSelectedRoute( 161 MediaRouter.ROUTE_TYPE_LIVE_VIDEO); 162 Display presentationDisplay = route != null ? route.getPresentationDisplay() : null; 163 164 // Dismiss the current presentation if the display has changed. 165 if (mPresentation != null && mPresentation.getDisplay() != presentationDisplay) { 166 Log.i(TAG, "Dismissing presentation because the current route no longer " 167 + "has a presentation display."); 168 mPresentation.dismiss(); 169 mPresentation = null; 170 } 171 172 // Show a new presentation if needed. 173 if (mPresentation == null && presentationDisplay != null) { 174 Log.i(TAG, "Showing presentation on display: " + presentationDisplay); 175 mPresentation = new DemoPresentation(this, presentationDisplay); 176 mPresentation.setOnDismissListener(mOnDismissListener); 177 try { 178 mPresentation.show(); 179 } catch (WindowManager.InvalidDisplayException ex) { 180 Log.w(TAG, "Couldn't show presentation! Display was removed in " 181 + "the meantime.", ex); 182 mPresentation = null; 183 } 184 } 185 186 // Update the contents playing in this activity. 187 updateContents(); 188 } 189 updateContents()190 private void updateContents() { 191 // Show either the content in the main activity or the content in the presentation 192 // along with some descriptive text about what is happening. 193 if (mPresentation != null) { 194 mInfoTextView.setText(getResources().getString( 195 R.string.presentation_with_media_router_now_playing_remotely, 196 mPresentation.getDisplay().getName())); 197 mSurfaceView.setVisibility(View.INVISIBLE); 198 mSurfaceView.onPause(); 199 if (mPaused) { 200 mPresentation.getSurfaceView().onPause(); 201 } else { 202 mPresentation.getSurfaceView().onResume(); 203 } 204 } else { 205 mInfoTextView.setText(getResources().getString( 206 R.string.presentation_with_media_router_now_playing_locally, 207 getWindowManager().getDefaultDisplay().getName())); 208 mSurfaceView.setVisibility(View.VISIBLE); 209 if (mPaused) { 210 mSurfaceView.onPause(); 211 } else { 212 mSurfaceView.onResume(); 213 } 214 } 215 } 216 217 private final MediaRouter.SimpleCallback mMediaRouterCallback = 218 new MediaRouter.SimpleCallback() { 219 @Override 220 public void onRouteSelected(MediaRouter router, int type, RouteInfo info) { 221 Log.d(TAG, "onRouteSelected: type=" + type + ", info=" + info); 222 updatePresentation(); 223 } 224 225 @Override 226 public void onRouteUnselected(MediaRouter router, int type, RouteInfo info) { 227 Log.d(TAG, "onRouteUnselected: type=" + type + ", info=" + info); 228 updatePresentation(); 229 } 230 231 @Override 232 public void onRoutePresentationDisplayChanged(MediaRouter router, RouteInfo info) { 233 Log.d(TAG, "onRoutePresentationDisplayChanged: info=" + info); 234 updatePresentation(); 235 } 236 }; 237 238 /** 239 * Listens for when presentations are dismissed. 240 */ 241 private final DialogInterface.OnDismissListener mOnDismissListener = 242 new DialogInterface.OnDismissListener() { 243 @Override 244 public void onDismiss(DialogInterface dialog) { 245 if (dialog == mPresentation) { 246 Log.i(TAG, "Presentation was dismissed."); 247 mPresentation = null; 248 updateContents(); 249 } 250 } 251 }; 252 253 /** 254 * The presentation to show on the secondary display. 255 * <p> 256 * Note that this display may have different metrics from the display on which 257 * the main activity is showing so we must be careful to use the presentation's 258 * own {@link Context} whenever we load resources. 259 * </p> 260 */ 261 private final static class DemoPresentation extends Presentation { 262 private GLSurfaceView mSurfaceView; 263 DemoPresentation(Context context, Display display)264 public DemoPresentation(Context context, Display display) { 265 super(context, display); 266 } 267 268 @Override onCreate(Bundle savedInstanceState)269 protected void onCreate(Bundle savedInstanceState) { 270 // Be sure to call the super class. 271 super.onCreate(savedInstanceState); 272 273 // Get the resources for the context of the presentation. 274 // Notice that we are getting the resources from the context of the presentation. 275 Resources r = getContext().getResources(); 276 277 // Inflate the layout. 278 setContentView(R.layout.presentation_with_media_router_content); 279 280 // Set up the surface view for visual interest. 281 mSurfaceView = (GLSurfaceView)findViewById(R.id.surface_view); 282 mSurfaceView.setRenderer(new CubeRenderer(false)); 283 } 284 getSurfaceView()285 public GLSurfaceView getSurfaceView() { 286 return mSurfaceView; 287 } 288 } 289 } 290 //END_INCLUDE(activity) 291