Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(87)

Side by Side Diff: chromecast/shell/android/apk/src/org/chromium/chromecast/shell/CastShellActivity.java

Issue 490603002: Chromecast: initial checkin of Android-based cast shell. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 package org.chromium.chromecast.shell;
6
7 import android.app.Activity;
8 import android.content.BroadcastReceiver;
9 import android.content.Context;
10 import android.content.Intent;
11 import android.content.IntentFilter;
12 import android.media.AudioManager;
13 import android.net.Uri;
14 import android.os.Bundle;
15 import android.support.v4.content.LocalBroadcastManager;
16 import android.util.Log;
17 import android.view.KeyEvent;
18 import android.view.MotionEvent;
19 import android.view.WindowManager;
20
21 import org.chromium.base.CommandLine;
22 import org.chromium.content.browser.ActivityContentVideoViewClient;
23 import org.chromium.content.browser.ContentVideoViewClient;
24 import org.chromium.content.browser.ContentViewClient;
25 import org.chromium.content.browser.ContentViewCore;
26 import org.chromium.ui.base.WindowAndroid;
27
28 /**
29 * Activity for managing the Cast shell.
30 */
31 public class CastShellActivity extends Activity {
32 private static final String TAG = "CastShellActivity";
33
34 private static final String ACTIVE_SHELL_URL_KEY = "activeUrl";
35 private static final int DEFAULT_HEIGHT_PIXELS = 720;
36 public static final String ACTION_EXTRA_RESOLUTION_HEIGHT =
37 "org.chromium.chromecast.shell.intent.extra.RESOLUTION_HEIGHT";
38
39 private CastWindowManager mCastWindowManager;
40 private AudioManager mAudioManager;
41 private BroadcastReceiver mBroadcastReceiver;
42
43 // Native window instance.
44 // TODO(byungchul, gunsch): CastShellActivity, CastWindowAndroid, and native CastWindowAndroid
45 // have a one-to-one relationship. Consider instantiating CastWindow here an d CastWindow having
46 // this native media shell instance.
47 private long mNativeCastWindow;
48
49 /**
50 * Returns whether or not CastShellActivity should launch the browser startu p sequence.
51 * Intended to be overridden.
52 */
53 protected boolean shouldLaunchBrowser() {
54 return true;
55 }
56
57 @Override
58 protected void onCreate(final Bundle savedInstanceState) {
59 super.onCreate(savedInstanceState);
60 exitIfUrlMissing();
61
62 if (shouldLaunchBrowser()) {
63 CastBrowserHelper.initializeBrowser(getApplicationContext());
64 }
65
66 // Whenever our app is visible, volume controls should modify the music stream.
67 // For more information read:
68 // http://developer.android.com/training/managing-audio/volume-playback. html
69 setVolumeControlStream(AudioManager.STREAM_MUSIC);
70
71 // Set flags to both exit sleep mode when this activity starts and
72 // avoid entering sleep mode while playing media. We cannot distinguish
73 // between video and audio so this applies to both.
74 getWindow().addFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
75 getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
76
77 mAudioManager = (AudioManager)getSystemService(Context.AUDIO_SERVICE);
78
79 setContentView(R.layout.cast_shell_activity);
80 mCastWindowManager = (CastWindowManager) findViewById(R.id.shell_contain er);
81 mCastWindowManager.setDelegate(new CastWindowManager.Delegate() {
82 @Override
83 protected void onClosed() {
84 mCastWindowManager.setDelegate(null);
85 finish();
86 }
87 });
88 setResolution();
89 mCastWindowManager.setWindow(new WindowAndroid(this));
90
91 registerBroadcastReceiver();
92
93 String url = getIntent().getDataString();
94 Log.d(TAG, "onCreate startupUrl: " + url);
95 mNativeCastWindow = mCastWindowManager.launchCastWindow(url);
96
97 getActiveContentViewCore().setContentViewClient(new ContentViewClient() {
98 @Override
99 public ContentVideoViewClient getContentVideoViewClient() {
100 return new ActivityContentVideoViewClient(CastShellActivity.this );
101 }
102 });
103 }
104
105 @Override
106 protected void onDestroy() {
107 super.onDestroy();
108
109 unregisterBroadcastReceiver();
110
111 if (mNativeCastWindow != 0) {
112 mCastWindowManager.stopCastWindow(mNativeCastWindow);
113 mNativeCastWindow = 0;
114 }
115 }
116
117 @Override
118 protected void onNewIntent(Intent intent) {
119 // Only handle direct intents (e.g. "fling") if this activity is also ma naging
120 // the browser process.
121 if (!shouldLaunchBrowser()) return;
122
123 String url = intent.getDataString();
124 Log.d(TAG, "onNewIntent: " + url);
125
126 // Reset broadcast intent uri and receiver.
127 setIntent(intent);
128 exitIfUrlMissing();
129 getActiveCastWindow().loadUrl(url);
130 }
131
132 @Override
133 protected void onResume() {
134 super.onResume();
135
136 // Inform ContentView that this activity is being shown.
137 ContentViewCore view = getActiveContentViewCore();
138 if (view != null) view.onShow();
139
140 // Request audio focus so any other audio playback doesn't continue in t he background.
141 if (mAudioManager.requestAudioFocus(
142 null, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN)
143 != AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
144 Log.e(TAG, "Failed to obtain audio focus");
145 }
146 }
147
148 @Override
149 protected void onPause() {
150 // As soon as the cast app is no longer in the foreground, we ought to i mmediately tear
151 // everything down. Apps should not continue running and playing sound i n the background.
152 super.onPause();
153
154 // Release the audio focus. Note that releasing audio focus does not sto p audio playback,
155 // it just notifies the framework that this activity has stopped playing audio.
156 if (mAudioManager.abandonAudioFocus(null) != AudioManager.AUDIOFOCUS_REQ UEST_GRANTED) {
157 Log.e(TAG, "Failed to abandon audio focus");
158 }
159
160 ContentViewCore view = getActiveContentViewCore();
161 if (view != null) view.onHide();
162
163 finishGracefully();
164 }
165
166 protected void finishGracefully() {
167 if (mNativeCastWindow != 0) {
168 mCastWindowManager.stopCastWindow(mNativeCastWindow);
169 mNativeCastWindow = 0;
170 }
171 }
172
173 private void registerBroadcastReceiver() {
174 if (mBroadcastReceiver == null) {
175 mBroadcastReceiver = new BroadcastReceiver() {
176 @Override
177 public void onReceive(Context context, Intent intent) {
178 Log.d(TAG, "Received intent: action=" + intent.getAction());
179 if (CastWindowAndroid.ACTION_ENABLE_DEV_TOOLS.equals(intent. getAction())) {
180 mCastWindowManager.nativeEnableDevTools(true);
181 } else if (CastWindowAndroid.ACTION_DISABLE_DEV_TOOLS.equals (
182 intent.getAction())) {
183 mCastWindowManager.nativeEnableDevTools(false);
184 }
185 }
186 };
187 }
188
189 IntentFilter devtoolsBroadcastIntentFilter = new IntentFilter();
190 devtoolsBroadcastIntentFilter.addAction(CastWindowAndroid.ACTION_ENABLE_ DEV_TOOLS);
191 devtoolsBroadcastIntentFilter.addAction(CastWindowAndroid.ACTION_DISABLE _DEV_TOOLS);
192 LocalBroadcastManager.getInstance(this)
193 .registerReceiver(mBroadcastReceiver, devtoolsBroadcastIntentFil ter);
194 }
195
196 private void unregisterBroadcastReceiver() {
197 LocalBroadcastManager broadcastManager = LocalBroadcastManager.getInstan ce(this);
198 broadcastManager.unregisterReceiver(mBroadcastReceiver);
199 }
200
201 private void setResolution() {
202 int requestedHeight = getIntent().getIntExtra(
203 ACTION_EXTRA_RESOLUTION_HEIGHT, DEFAULT_HEIGHT_PIXELS);
204 int displayHeight = getResources().getDisplayMetrics().heightPixels;
205 // Clamp within [DEFAULT_HEIGHT_PIXELS, displayHeight]
206 int desiredHeight =
207 Math.min(displayHeight, Math.max(DEFAULT_HEIGHT_PIXELS, requeste dHeight));
208 double deviceScaleFactor = ((double)displayHeight) / desiredHeight;
209 Log.d(TAG, "Using scale factor " + deviceScaleFactor + " to set height " + desiredHeight);
210 CommandLine.getInstance().appendSwitchWithValue("force-device-scale-fact or",
211 String.valueOf(deviceScaleFactor));
212 }
213
214 private void exitIfUrlMissing() {
215 Intent intent = getIntent();
216 if (intent != null && intent.getData() != null && !intent.getData().equa ls(Uri.EMPTY)) {
217 return;
218 }
219 // Log an exception so that the exit cause is obvious when reading the l ogs.
220 Log.e(TAG, "Activity will not start",
221 new IllegalArgumentException("Intent did not contain a valid url"));
222 System.exit(-1);
223 }
224
225 /**
226 * @return The currently visible {@link CastWindowAndroid} or null if one is not showing.
227 */
228 public CastWindowAndroid getActiveCastWindow() {
229 return mCastWindowManager.getActiveCastWindow();
230 }
231
232 /**
233 * @return The {@link ContentViewCore} owned by the currently visible {@link CastWindowAndroid},
234 * or null if one is not showing.
235 */
236 public ContentViewCore getActiveContentViewCore() {
237 CastWindowAndroid shell = getActiveCastWindow();
238 return shell != null ? shell.getContentViewCore() : null;
239 }
240
241 @Override
242 public boolean onKeyUp(int keyCode, KeyEvent event) {
243 if (keyCode != KeyEvent.KEYCODE_BACK) {
244 return super.onKeyUp(keyCode, event);
245 }
246
247 // Just finish this activity to go back to the previous activity or laun cher.
248 finishGracefully();
249 return true;
250 }
251
252 @Override
253 public boolean dispatchKeyEvent(KeyEvent event) {
254 int keyCode = event.getKeyCode();
255 if (keyCode == KeyEvent.KEYCODE_BACK) {
256 return super.dispatchKeyEvent(event);
257 }
258 return false;
259 }
260
261 @Override
262 public boolean dispatchGenericMotionEvent(MotionEvent ev) {
263 return false;
264 }
265
266 @Override
267 public boolean dispatchKeyShortcutEvent(KeyEvent event) {
268 return false;
269 }
270
271 @Override
272 public boolean dispatchTouchEvent(MotionEvent ev) {
273 return false;
274 }
275
276 @Override
277 public boolean dispatchTrackballEvent(MotionEvent ev) {
278 return false;
279 }
280 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698