1
/*
2
* Copyright 2013 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.basicmediarouter;
18
19
import android.app.Activity;
20
import android.app.MediaRouteActionProvider;
21
import android.content.Context;
22
import android.content.DialogInterface;
23
import android.media.MediaRouter;
24
import android.media.MediaRouter.RouteInfo;
25
import android.os.Bundle;
26
import android.view.Display;
27
import android.view.Menu;
28
import android.view.MenuItem;
29
import android.view.View;
30
import android.view.WindowManager;
31
import android.widget.Button;
32
import android.widget.TextView;
33
34
/**
35
* <p>
36
* This sample demonstrates the use of the MediaRouter API to show content on a
37
* secondary display using a {@link android.app.Presentation}.
38
* </p>
39
* <p>
40
* The activity uses the {@link android.media.MediaRouter} API to automatically detect when a
41
* presentation display is available and to allow the user to control the media
42
* routes using a menu item provided by the {@link android.app.MediaRouteActionProvider}.
43
* When a presentation display is available a {@link android.app.Presentation} (implemented
44
* as a {@link SamplePresentation}) is shown on the preferred display. A button
45
* toggles the background color of the secondary screen to show the interaction
46
* between the primary and secondary screens.
47
* </p>
48
* <p>
49
* This sample requires an HDMI or Wifi display. Alternatively, the
50
* "Simulate secondary displays" feature in Development Settings can be enabled
51
* to simulate secondary displays.
52
* </p>
53
*
54
* @see android.app.Presentation
55
* @see android.media.MediaRouter
56
*/
57
public class MainActivity extends Activity {
58
59
private MediaRouter mMediaRouter;
60
61
// Active Presentation, set to null if no secondary screen is enabled
62
private SamplePresentation mPresentation;
63
64
@Override
65
protected void onCreate(Bundle savedInstanceState) {
66
super.onCreate(savedInstanceState);
67
68
setContentView(R.layout.sample_main);
69
mTextStatus = (TextView) findViewById(R.id.textStatus);
70
71
// get the list of background colors
72
mColors = getResources().getIntArray(R.array.androidcolors);
73
74
// Enable clicks on the 'change color' button
75
mButton = (Button) findViewById(R.id.button1);
76
mButton.setOnClickListener(new View.OnClickListener() {
77
78
@Override
79
public void onClick(View v) {
80
showNextColor();
81
}
82
});
83
85
// Get the MediaRouter service
86
mMediaRouter = (MediaRouter) getSystemService(Context.MEDIA_ROUTER_SERVICE);
88
}
89
90
/**
91
* Implementing a {@link android.media.MediaRouter.Callback} to update the displayed
92
* {@link android.app.Presentation} when a route is selected, unselected or the
93
* presentation display has changed. The provided stub implementation
94
* {@link android.media.MediaRouter.SimpleCallback} is extended and only
95
* {@link android.media.MediaRouter.SimpleCallback#onRouteSelected(android.media.MediaRouter, int, android.media.MediaRouter.RouteInfo)}
96
* ,
97
* {@link android.media.MediaRouter.SimpleCallback#onRouteUnselected(android.media.MediaRouter, int, android.media.MediaRouter.RouteInfo)}
98
* and
99
* {@link android.media.MediaRouter.SimpleCallback#onRoutePresentationDisplayChanged(android.media.MediaRouter, android.media.MediaRouter.RouteInfo)}
100
* are overridden to update the displayed {@link android.app.Presentation} in
101
* {@link #updatePresentation()}. These callbacks enable or disable the
102
* second screen presentation based on the routing provided by the
103
* {@link android.media.MediaRouter} for {@link android.media.MediaRouter#ROUTE_TYPE_LIVE_VIDEO}
104
* streams. @
105
*/
106
private final MediaRouter.SimpleCallback mMediaRouterCallback =
107
new MediaRouter.SimpleCallback() {
108
110
/**
111
* A new route has been selected as active. Disable the current
112
* route and enable the new one.
113
*/
114
@Override
115
public void onRouteSelected(MediaRouter router, int type, RouteInfo info) {
116
updatePresentation();
117
}
118
119
/**
120
* The route has been unselected.
121
*/
122
@Override
123
public void onRouteUnselected(MediaRouter router, int type, RouteInfo info) {
124
updatePresentation();
125
126
}
127
128
/**
129
* The route's presentation display has changed. This callback
130
* is called when the presentation has been activated, removed
131
* or its properties have changed.
132
*/
133
@Override
134
public void onRoutePresentationDisplayChanged(MediaRouter router, RouteInfo info) {
135
updatePresentation();
136
}
138
};
139
140
/**
141
* Updates the displayed presentation to enable a secondary screen if it has
142
* been selected in the {@link android.media.MediaRouter} for the
143
* {@link android.media.MediaRouter#ROUTE_TYPE_LIVE_VIDEO} type. If no screen has been
144
* selected by the {@link android.media.MediaRouter}, the current screen is disabled.
145
* Otherwise a new {@link SamplePresentation} is initialized and shown on
146
* the secondary screen.
147
*/
148
private void updatePresentation() {
149
151
// Get the selected route for live video
152
RouteInfo selectedRoute = mMediaRouter.getSelectedRoute(
153
MediaRouter.ROUTE_TYPE_LIVE_VIDEO);
154
155
// Get its Display if a valid route has been selected
156
Display selectedDisplay = null;
157
if (selectedRoute != null) {
158
selectedDisplay = selectedRoute.getPresentationDisplay();
159
}
161
163
/*
164
* Dismiss the current presentation if the display has changed or no new
165
* route has been selected
166
*/
167
if (mPresentation != null && mPresentation.getDisplay() != selectedDisplay) {
168
mPresentation.dismiss();
169
mPresentation = null;
170
mButton.setEnabled(false);
171
mTextStatus.setText(R.string.secondary_notconnected);
172
}
174
176
/*
177
* Show a new presentation if the previous one has been dismissed and a
178
* route has been selected.
179
*/
180
if (mPresentation == null && selectedDisplay != null) {
181
182
// Initialise a new Presentation for the Display
183
mPresentation = new SamplePresentation(this, selectedDisplay);
184
mPresentation.setOnDismissListener(mOnDismissListener);
185
186
// Try to show the presentation, this might fail if the display has
187
// gone away in the mean time
188
try {
189
mPresentation.show();
190
mTextStatus.setText(getResources().getString(R.string.secondary_connected,
191
selectedRoute.getName(MainActivity.this)));
192
mButton.setEnabled(true);
193
showNextColor();
194
} catch (WindowManager.InvalidDisplayException ex) {
195
// Couldn't show presentation - display was already removed
196
mPresentation = null;
197
}
198
}
200
201
}
202
203
@Override
204
protected void onResume() {
205
super.onResume();
206
208
// Register a callback for all events related to live video devices
209
mMediaRouter.addCallback(MediaRouter.ROUTE_TYPE_LIVE_VIDEO, mMediaRouterCallback);
211
212
// Show the 'Not connected' status message
213
mButton.setEnabled(false);
214
mTextStatus.setText(R.string.secondary_notconnected);
215
216
// Update the displays based on the currently active routes
217
updatePresentation();
218
}
219
220
@Override
221
protected void onPause() {
222
super.onPause();
223
225
// Stop listening for changes to media routes.
226
mMediaRouter.removeCallback(mMediaRouterCallback);
228
}
229
230
@Override
231
protected void onStop() {
232
super.onStop();
233
235
// Dismiss the presentation when the activity is not visible.
236
if (mPresentation != null) {
237
mPresentation.dismiss();
238
mPresentation = null;
239
}
241
}
242
243
/**
244
* Inflates the ActionBar or options menu. The menu file defines an item for
245
* the {@link android.app.MediaRouteActionProvider}, which is registered here for all
246
* live video devices using {@link android.media.MediaRouter#ROUTE_TYPE_LIVE_VIDEO}.
247
*/
248
@Override
249
public boolean onCreateOptionsMenu(Menu menu) {
250
super.onCreateOptionsMenu(menu);
251
252
getMenuInflater().inflate(R.menu.main, menu);
253
255
// Configure the media router action provider
256
MenuItem mediaRouteMenuItem = menu.findItem(R.id.menu_media_route);
257
MediaRouteActionProvider mediaRouteActionProvider =
258
(MediaRouteActionProvider) mediaRouteMenuItem.getActionProvider();
259
mediaRouteActionProvider.setRouteTypes(MediaRouter.ROUTE_TYPE_LIVE_VIDEO);
261
262
return true;
263
}
264
265
/**
266
* Listens for dismissal of the {@link SamplePresentation} and removes its
267
* reference.
268
*/
269
private final DialogInterface.OnDismissListener mOnDismissListener =
270
new DialogInterface.OnDismissListener() {
271
@Override
272
public void onDismiss(DialogInterface dialog) {
273
if (dialog == mPresentation) {
274
mPresentation = null;
275
}
276
}
277
};
278
279
// Views used to display status information on the primary screen
280
private TextView mTextStatus;
281
private Button mButton;
282
283
// selected color index
284
private int mColor = 0;
285
286
// background colors
287
public int[] mColors;
288
289
/**
290
* Displays the next color on the secondary screen if it is activate.
291
*/
292
private void showNextColor() {
293
if (mPresentation != null) {
294
// a second screen is active and initialized, show the next color
295
mPresentation.setColor(mColors[mColor]);
296
mColor = (mColor + 1) % mColors.length;
297
}
298
}
299
300
}