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