2 * Copyright (C) 2010 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 package com.android.gallery3d.app;
19 import android.annotation.TargetApi;
20 import android.app.Activity;
21 import android.app.AlertDialog;
22 import android.content.BroadcastReceiver;
23 import android.content.ComponentName;
24 import android.content.Context;
25 import android.content.DialogInterface;
26 import android.content.DialogInterface.OnCancelListener;
27 import android.content.DialogInterface.OnClickListener;
28 import android.content.Intent;
29 import android.content.IntentFilter;
30 import android.content.ServiceConnection;
31 import android.content.res.Configuration;
32 import android.os.Bundle;
33 import android.os.IBinder;
34 import android.view.Menu;
35 import android.view.MenuItem;
36 import android.view.Window;
37 import android.view.WindowManager;
39 import com.android.gallery3d.R;
40 import com.android.gallery3d.common.ApiHelper;
41 import com.android.gallery3d.data.DataManager;
42 import com.android.gallery3d.data.MediaItem;
43 import com.android.photos.data.GalleryBitmapPool;
44 import com.android.gallery3d.ui.GLRoot;
45 import com.android.gallery3d.ui.GLRootView;
46 import com.android.gallery3d.util.LightCycleHelper.PanoramaViewHelper;
47 import com.android.gallery3d.util.ThreadPool;
48 import com.android.gallery3d.util.UsageStatistics;
50 public class AbstractGalleryActivity extends Activity implements GalleryContext {
51 @SuppressWarnings("unused")
52 private static final String TAG = "AbstractGalleryActivity";
53 private GLRootView mGLRootView;
54 private StateManager mStateManager;
55 private GalleryActionBar mActionBar;
56 private OrientationManager mOrientationManager;
57 private TransitionStore mTransitionStore = new TransitionStore();
58 private boolean mDisableToggleStatusBar;
59 private PanoramaViewHelper mPanoramaViewHelper;
61 private AlertDialog mAlertDialog = null;
62 private BroadcastReceiver mMountReceiver = new BroadcastReceiver() {
64 public void onReceive(Context context, Intent intent) {
65 if (getExternalCacheDir() != null) onStorageReady();
68 private IntentFilter mMountFilter = new IntentFilter(Intent.ACTION_MEDIA_MOUNTED);
71 protected void onCreate(Bundle savedInstanceState) {
72 super.onCreate(savedInstanceState);
73 mOrientationManager = new OrientationManager(this);
74 toggleStatusBarByOrientation();
75 getWindow().setBackgroundDrawable(null);
76 mPanoramaViewHelper = new PanoramaViewHelper(this);
77 mPanoramaViewHelper.onCreate();
79 UsageStatistics.showOptInDialogIfNeeded(this);
83 protected void onSaveInstanceState(Bundle outState) {
84 mGLRootView.lockRenderThread();
86 super.onSaveInstanceState(outState);
87 getStateManager().saveState(outState);
89 mGLRootView.unlockRenderThread();
94 public void onConfigurationChanged(Configuration config) {
95 super.onConfigurationChanged(config);
96 mStateManager.onConfigurationChange(config);
97 getGalleryActionBar().onConfigurationChanged();
98 invalidateOptionsMenu();
99 toggleStatusBarByOrientation();
103 public boolean onCreateOptionsMenu(Menu menu) {
104 super.onCreateOptionsMenu(menu);
105 return getStateManager().createOptionsMenu(menu);
109 public Context getAndroidContext() {
114 public DataManager getDataManager() {
115 return ((GalleryApp) getApplication()).getDataManager();
119 public ThreadPool getThreadPool() {
120 return ((GalleryApp) getApplication()).getThreadPool();
123 public synchronized StateManager getStateManager() {
124 if (mStateManager == null) {
125 mStateManager = new StateManager(this);
127 return mStateManager;
130 public GLRoot getGLRoot() {
134 public OrientationManager getOrientationManager() {
135 return mOrientationManager;
139 public void setContentView(int resId) {
140 super.setContentView(resId);
141 mGLRootView = (GLRootView) findViewById(R.id.gl_root_view);
144 protected void onStorageReady() {
145 if (mAlertDialog != null) {
146 mAlertDialog.dismiss();
148 unregisterReceiver(mMountReceiver);
153 protected void onStart() {
155 if (getExternalCacheDir() == null) {
156 OnCancelListener onCancel = new OnCancelListener() {
158 public void onCancel(DialogInterface dialog) {
162 OnClickListener onClick = new OnClickListener() {
164 public void onClick(DialogInterface dialog, int which) {
168 AlertDialog.Builder builder = new AlertDialog.Builder(this)
169 .setTitle(R.string.no_external_storage_title)
170 .setMessage(R.string.no_external_storage)
171 .setNegativeButton(android.R.string.cancel, onClick)
172 .setOnCancelListener(onCancel);
173 if (ApiHelper.HAS_SET_ICON_ATTRIBUTE) {
174 setAlertDialogIconAttribute(builder);
176 builder.setIcon(android.R.drawable.ic_dialog_alert);
178 mAlertDialog = builder.show();
179 registerReceiver(mMountReceiver, mMountFilter);
181 mPanoramaViewHelper.onStart();
184 @TargetApi(ApiHelper.VERSION_CODES.HONEYCOMB)
185 private static void setAlertDialogIconAttribute(
186 AlertDialog.Builder builder) {
187 builder.setIconAttribute(android.R.attr.alertDialogIcon);
191 protected void onStop() {
193 if (mAlertDialog != null) {
194 unregisterReceiver(mMountReceiver);
195 mAlertDialog.dismiss();
198 mPanoramaViewHelper.onStop();
202 protected void onResume() {
204 mGLRootView.lockRenderThread();
206 getStateManager().resume();
207 getDataManager().resume();
209 mGLRootView.unlockRenderThread();
211 mGLRootView.onResume();
212 mOrientationManager.resume();
216 protected void onPause() {
218 mOrientationManager.pause();
219 mGLRootView.onPause();
220 mGLRootView.lockRenderThread();
222 getStateManager().pause();
223 getDataManager().pause();
225 mGLRootView.unlockRenderThread();
227 GalleryBitmapPool.getInstance().clear();
228 MediaItem.getBytesBufferPool().clear();
232 protected void onDestroy() {
234 mGLRootView.lockRenderThread();
236 getStateManager().destroy();
238 mGLRootView.unlockRenderThread();
240 doUnbindBatchService();
244 protected void onActivityResult(int requestCode, int resultCode, Intent data) {
245 mGLRootView.lockRenderThread();
247 getStateManager().notifyActivityResult(
248 requestCode, resultCode, data);
250 mGLRootView.unlockRenderThread();
255 public void onBackPressed() {
256 // send the back event to the top sub-state
257 GLRoot root = getGLRoot();
258 root.lockRenderThread();
260 getStateManager().onBackPressed();
262 root.unlockRenderThread();
266 public GalleryActionBar getGalleryActionBar() {
267 if (mActionBar == null) {
268 mActionBar = new GalleryActionBar(this);
274 public boolean onOptionsItemSelected(MenuItem item) {
275 GLRoot root = getGLRoot();
276 root.lockRenderThread();
278 return getStateManager().itemSelected(item);
280 root.unlockRenderThread();
284 protected void disableToggleStatusBar() {
285 mDisableToggleStatusBar = true;
288 // Shows status bar in portrait view, hide in landscape view
289 private void toggleStatusBarByOrientation() {
290 if (mDisableToggleStatusBar) return;
292 Window win = getWindow();
293 if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
294 win.clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
296 win.addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
300 public TransitionStore getTransitionStore() {
301 return mTransitionStore;
304 public PanoramaViewHelper getPanoramaViewHelper() {
305 return mPanoramaViewHelper;
308 protected boolean isFullscreen() {
309 return (getWindow().getAttributes().flags
310 & WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0;
313 private BatchService mBatchService;
314 private boolean mBatchServiceIsBound = false;
315 private ServiceConnection mBatchServiceConnection = new ServiceConnection() {
316 public void onServiceConnected(ComponentName className, IBinder service) {
317 mBatchService = ((BatchService.LocalBinder)service).getService();
320 public void onServiceDisconnected(ComponentName className) {
321 mBatchService = null;
325 private void doBindBatchService() {
326 bindService(new Intent(this, BatchService.class), mBatchServiceConnection, Context.BIND_AUTO_CREATE);
327 mBatchServiceIsBound = true;
330 private void doUnbindBatchService() {
331 if (mBatchServiceIsBound) {
332 // Detach our existing connection.
333 unbindService(mBatchServiceConnection);
334 mBatchServiceIsBound = false;
338 public ThreadPool getBatchServiceThreadPoolIfAvailable() {
339 if (mBatchServiceIsBound && mBatchService != null) {
340 return mBatchService.getThreadPool();
342 throw new RuntimeException("Batch service unavailable");