1 /*
2  * Copyright (C) 2007 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.android.gallery3d.app;
18 
19 import android.annotation.TargetApi;
20 import android.app.ActionBar;
21 import android.app.Activity;
22 import android.content.AsyncQueryHandler;
23 import android.content.ContentResolver;
24 import android.content.Context;
25 import android.content.Intent;
26 import android.content.pm.ActivityInfo;
27 import android.database.Cursor;
28 import android.graphics.Bitmap;
29 import android.graphics.drawable.BitmapDrawable;
30 import android.media.AudioManager;
31 import android.net.Uri;
32 import android.os.Build;
33 import android.os.Bundle;
34 import android.os.PowerManager;
35 import android.provider.MediaStore;
36 import android.provider.OpenableColumns;
37 import android.view.KeyEvent;
38 import android.view.Menu;
39 import android.view.MenuItem;
40 import android.view.View;
41 import android.view.Window;
42 import android.view.WindowManager;
43 import android.widget.ShareActionProvider;
44 
45 import com.android.gallery3d.R;
46 import com.android.gallery3d.common.ApiHelper;
47 import com.android.gallery3d.common.Utils;
48 
49 /**
50  * This activity plays a video from a specified URI.
51  *
52  * The client of this activity can pass a logo bitmap in the intent (KEY_LOGO_BITMAP)
53  * to set the action bar logo so the playback process looks more seamlessly integrated with
54  * the original activity.
55  */
56 public class MovieActivity extends Activity {
57     @SuppressWarnings("unused")
58     private static final String TAG = "MovieActivity";
59     public static final String KEY_LOGO_BITMAP = "logo-bitmap";
60     public static final String KEY_TREAT_UP_AS_BACK = "treat-up-as-back";
61 
62     private MoviePlayer mPlayer;
63     private boolean mFinishOnCompletion;
64     private Uri mUri;
65     private boolean mTreatUpAsBack;
66     private PowerManager.WakeLock mWakeLock = null;
67 
68     @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
setSystemUiVisibility(View rootView)69     private void setSystemUiVisibility(View rootView) {
70         if (ApiHelper.HAS_VIEW_SYSTEM_UI_FLAG_LAYOUT_STABLE) {
71             rootView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE
72                     | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
73                     | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
74         }
75     }
76 
77     @Override
onCreate(Bundle savedInstanceState)78     public void onCreate(Bundle savedInstanceState) {
79         super.onCreate(savedInstanceState);
80 
81         requestWindowFeature(Window.FEATURE_ACTION_BAR);
82         requestWindowFeature(Window.FEATURE_ACTION_BAR_OVERLAY);
83 
84         setContentView(R.layout.movie_view);
85         View rootView = findViewById(R.id.movie_view_root);
86 
87         setSystemUiVisibility(rootView);
88 
89         Intent intent = getIntent();
90         initializeActionBar(intent);
91         mFinishOnCompletion = intent.getBooleanExtra(
92                 MediaStore.EXTRA_FINISH_ON_COMPLETION, true);
93         mTreatUpAsBack = intent.getBooleanExtra(KEY_TREAT_UP_AS_BACK, false);
94         mPlayer = new MoviePlayer(rootView, this, intent.getData(), savedInstanceState,
95                 !mFinishOnCompletion) {
96             @Override
97             public void onCompletion() {
98                 if (mFinishOnCompletion) {
99                     finish();
100                 }
101             }
102         };
103         if (intent.hasExtra(MediaStore.EXTRA_SCREEN_ORIENTATION)) {
104             int orientation = intent.getIntExtra(
105                     MediaStore.EXTRA_SCREEN_ORIENTATION,
106                     ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
107             if (orientation != getRequestedOrientation()) {
108                 setRequestedOrientation(orientation);
109             }
110         }
111         Window win = getWindow();
112         WindowManager.LayoutParams winParams = win.getAttributes();
113         winParams.buttonBrightness = WindowManager.LayoutParams.BRIGHTNESS_OVERRIDE_OFF;
114         winParams.flags |= WindowManager.LayoutParams.FLAG_FULLSCREEN;
115         win.setAttributes(winParams);
116 
117         // We set the background in the theme to have the launching animation.
118         // But for the performance (and battery), we remove the background here.
119         win.setBackgroundDrawable(null);
120     }
121 
setActionBarLogoFromIntent(Intent intent)122     private void setActionBarLogoFromIntent(Intent intent) {
123         Bitmap logo = intent.getParcelableExtra(KEY_LOGO_BITMAP);
124         if (logo != null) {
125             getActionBar().setLogo(
126                     new BitmapDrawable(getResources(), logo));
127         }
128     }
129 
initializeActionBar(Intent intent)130     private void initializeActionBar(Intent intent) {
131         mUri = intent.getData();
132         final ActionBar actionBar = getActionBar();
133         if (actionBar == null) {
134             return;
135         }
136         setActionBarLogoFromIntent(intent);
137         actionBar.setDisplayOptions(
138                 ActionBar.DISPLAY_HOME_AS_UP,
139                 ActionBar.DISPLAY_HOME_AS_UP);
140 
141         String title = intent.getStringExtra(Intent.EXTRA_TITLE);
142         if (title != null) {
143             actionBar.setTitle(title);
144         } else {
145             // Displays the filename as title, reading the filename from the
146             // interface: {@link android.provider.OpenableColumns#DISPLAY_NAME}.
147             AsyncQueryHandler queryHandler =
148                     new AsyncQueryHandler(getContentResolver()) {
149                 @Override
150                 protected void onQueryComplete(int token, Object cookie,
151                         Cursor cursor) {
152                     try {
153                         if ((cursor != null) && cursor.moveToFirst()) {
154                             String displayName = cursor.getString(0);
155 
156                             // Just show empty title if other apps don't set
157                             // DISPLAY_NAME
158                             actionBar.setTitle((displayName == null) ? "" :
159                                     displayName);
160                         }
161                     } finally {
162                         Utils.closeSilently(cursor);
163                     }
164                 }
165             };
166             queryHandler.startQuery(0, null, mUri,
167                     new String[] {OpenableColumns.DISPLAY_NAME}, null, null,
168                     null);
169         }
170     }
171 
172     @Override
onCreateOptionsMenu(Menu menu)173     public boolean onCreateOptionsMenu(Menu menu) {
174         super.onCreateOptionsMenu(menu);
175         getMenuInflater().inflate(R.menu.movie, menu);
176 
177         // Document says EXTRA_STREAM should be a content: Uri
178         // So, we only share the video if it's "content:".
179         MenuItem shareItem = menu.findItem(R.id.action_share);
180         if (ContentResolver.SCHEME_CONTENT.equals(mUri.getScheme())) {
181             shareItem.setVisible(true);
182             ((ShareActionProvider) shareItem.getActionProvider())
183                     .setShareIntent(createShareIntent());
184         } else {
185             shareItem.setVisible(false);
186         }
187         return true;
188     }
189 
createShareIntent()190     private Intent createShareIntent() {
191         Intent intent = new Intent(Intent.ACTION_SEND);
192         intent.setType("video/*");
193         intent.putExtra(Intent.EXTRA_STREAM, mUri);
194         return intent;
195     }
196 
197     @Override
onOptionsItemSelected(MenuItem item)198     public boolean onOptionsItemSelected(MenuItem item) {
199         int id = item.getItemId();
200         if (id == android.R.id.home) {
201             if (mTreatUpAsBack) {
202                 finish();
203             } else {
204                 startActivity(new Intent(this, GalleryActivity.class));
205                 finish();
206             }
207             return true;
208         } else if (id == R.id.action_share) {
209             startActivity(Intent.createChooser(createShareIntent(),
210                     getString(R.string.share)));
211             return true;
212         }
213         return false;
214     }
215 
216     @Override
onStart()217     public void onStart() {
218         ((AudioManager) getSystemService(AUDIO_SERVICE))
219                 .requestAudioFocus(null, AudioManager.STREAM_MUSIC,
220                 AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);
221         super.onStart();
222 
223         PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
224         mWakeLock = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK,"Gallery_WAKE_LOCK");
225         mWakeLock.acquire();
226 
227     }
228 
229     @Override
onStop()230     protected void onStop() {
231         ((AudioManager) getSystemService(AUDIO_SERVICE))
232                 .abandonAudioFocus(null);
233         super.onStop();
234 
235         mWakeLock.release();
236 
237     }
238 
239     @Override
onPause()240     public void onPause() {
241         mPlayer.onPause();
242         super.onPause();
243     }
244 
245     @Override
onResume()246     public void onResume() {
247         mPlayer.onResume();
248         super.onResume();
249     }
250 
251     @Override
onSaveInstanceState(Bundle outState)252     public void onSaveInstanceState(Bundle outState) {
253         super.onSaveInstanceState(outState);
254         mPlayer.onSaveInstanceState(outState);
255     }
256 
257     @Override
onDestroy()258     public void onDestroy() {
259         mPlayer.onDestroy();
260         super.onDestroy();
261     }
262 
263     @Override
onKeyDown(int keyCode, KeyEvent event)264     public boolean onKeyDown(int keyCode, KeyEvent event) {
265         return mPlayer.onKeyDown(keyCode, event)
266                 || super.onKeyDown(keyCode, event);
267     }
268 
269     @Override
onKeyUp(int keyCode, KeyEvent event)270     public boolean onKeyUp(int keyCode, KeyEvent event) {
271         return mPlayer.onKeyUp(keyCode, event)
272                 || super.onKeyUp(keyCode, event);
273     }
274 }
275