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

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

Powered by Google App Engine
This is Rietveld 408576698