Home | History | Annotate | Download | only in app
      1 /*
      2  * Copyright (C) 2010 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.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;
     38 
     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.gallery3d.ui.GLRoot;
     44 import com.android.gallery3d.ui.GLRootView;
     45 import com.android.gallery3d.util.LightCycleHelper.PanoramaViewHelper;
     46 import com.android.gallery3d.util.ThreadPool;
     47 import com.android.photos.data.GalleryBitmapPool;
     48 
     49 public class AbstractGalleryActivity extends Activity implements GalleryContext {
     50     @SuppressWarnings("unused")
     51     private static final String TAG = "AbstractGalleryActivity";
     52     private GLRootView mGLRootView;
     53     private StateManager mStateManager;
     54     private GalleryActionBar mActionBar;
     55     private OrientationManager mOrientationManager;
     56     private TransitionStore mTransitionStore = new TransitionStore();
     57     private boolean mDisableToggleStatusBar;
     58     private PanoramaViewHelper mPanoramaViewHelper;
     59 
     60     private AlertDialog mAlertDialog = null;
     61     private BroadcastReceiver mMountReceiver = new BroadcastReceiver() {
     62         @Override
     63         public void onReceive(Context context, Intent intent) {
     64             if (getExternalCacheDir() != null) onStorageReady();
     65         }
     66     };
     67     private IntentFilter mMountFilter = new IntentFilter(Intent.ACTION_MEDIA_MOUNTED);
     68 
     69     @Override
     70     protected void onCreate(Bundle savedInstanceState) {
     71         super.onCreate(savedInstanceState);
     72         mOrientationManager = new OrientationManager(this);
     73         toggleStatusBarByOrientation();
     74         getWindow().setBackgroundDrawable(null);
     75         mPanoramaViewHelper = new PanoramaViewHelper(this);
     76         mPanoramaViewHelper.onCreate();
     77         doBindBatchService();
     78     }
     79 
     80     @Override
     81     protected void onSaveInstanceState(Bundle outState) {
     82         mGLRootView.lockRenderThread();
     83         try {
     84             super.onSaveInstanceState(outState);
     85             getStateManager().saveState(outState);
     86         } finally {
     87             mGLRootView.unlockRenderThread();
     88         }
     89     }
     90 
     91     @Override
     92     public void onConfigurationChanged(Configuration config) {
     93         super.onConfigurationChanged(config);
     94         mStateManager.onConfigurationChange(config);
     95         getGalleryActionBar().onConfigurationChanged();
     96         invalidateOptionsMenu();
     97         toggleStatusBarByOrientation();
     98     }
     99 
    100     @Override
    101     public boolean onCreateOptionsMenu(Menu menu) {
    102         super.onCreateOptionsMenu(menu);
    103         return getStateManager().createOptionsMenu(menu);
    104     }
    105 
    106     @Override
    107     public Context getAndroidContext() {
    108         return this;
    109     }
    110 
    111     @Override
    112     public DataManager getDataManager() {
    113         return ((GalleryApp) getApplication()).getDataManager();
    114     }
    115 
    116     @Override
    117     public ThreadPool getThreadPool() {
    118         return ((GalleryApp) getApplication()).getThreadPool();
    119     }
    120 
    121     public synchronized StateManager getStateManager() {
    122         if (mStateManager == null) {
    123             mStateManager = new StateManager(this);
    124         }
    125         return mStateManager;
    126     }
    127 
    128     public GLRoot getGLRoot() {
    129         return mGLRootView;
    130     }
    131 
    132     public OrientationManager getOrientationManager() {
    133         return mOrientationManager;
    134     }
    135 
    136     @Override
    137     public void setContentView(int resId) {
    138         super.setContentView(resId);
    139         mGLRootView = (GLRootView) findViewById(R.id.gl_root_view);
    140     }
    141 
    142     protected void onStorageReady() {
    143         if (mAlertDialog != null) {
    144             mAlertDialog.dismiss();
    145             mAlertDialog = null;
    146             unregisterReceiver(mMountReceiver);
    147         }
    148     }
    149 
    150     @Override
    151     protected void onStart() {
    152         super.onStart();
    153         if (getExternalCacheDir() == null) {
    154             OnCancelListener onCancel = new OnCancelListener() {
    155                 @Override
    156                 public void onCancel(DialogInterface dialog) {
    157                     finish();
    158                 }
    159             };
    160             OnClickListener onClick = new OnClickListener() {
    161                 @Override
    162                 public void onClick(DialogInterface dialog, int which) {
    163                     dialog.cancel();
    164                 }
    165             };
    166             AlertDialog.Builder builder = new AlertDialog.Builder(this)
    167                     .setTitle(R.string.no_external_storage_title)
    168                     .setMessage(R.string.no_external_storage)
    169                     .setNegativeButton(android.R.string.cancel, onClick)
    170                     .setOnCancelListener(onCancel);
    171             if (ApiHelper.HAS_SET_ICON_ATTRIBUTE) {
    172                 setAlertDialogIconAttribute(builder);
    173             } else {
    174                 builder.setIcon(android.R.drawable.ic_dialog_alert);
    175             }
    176             mAlertDialog = builder.show();
    177             registerReceiver(mMountReceiver, mMountFilter);
    178         }
    179         mPanoramaViewHelper.onStart();
    180     }
    181 
    182     @TargetApi(ApiHelper.VERSION_CODES.HONEYCOMB)
    183     private static void setAlertDialogIconAttribute(
    184             AlertDialog.Builder builder) {
    185         builder.setIconAttribute(android.R.attr.alertDialogIcon);
    186     }
    187 
    188     @Override
    189     protected void onStop() {
    190         super.onStop();
    191         if (mAlertDialog != null) {
    192             unregisterReceiver(mMountReceiver);
    193             mAlertDialog.dismiss();
    194             mAlertDialog = null;
    195         }
    196         mPanoramaViewHelper.onStop();
    197     }
    198 
    199     @Override
    200     protected void onResume() {
    201         super.onResume();
    202         mGLRootView.lockRenderThread();
    203         try {
    204             getStateManager().resume();
    205             getDataManager().resume();
    206         } finally {
    207             mGLRootView.unlockRenderThread();
    208         }
    209         mGLRootView.onResume();
    210         mOrientationManager.resume();
    211     }
    212 
    213     @Override
    214     protected void onPause() {
    215         super.onPause();
    216         mOrientationManager.pause();
    217         mGLRootView.onPause();
    218         mGLRootView.lockRenderThread();
    219         try {
    220             getStateManager().pause();
    221             getDataManager().pause();
    222         } finally {
    223             mGLRootView.unlockRenderThread();
    224         }
    225         GalleryBitmapPool.getInstance().clear();
    226         MediaItem.getBytesBufferPool().clear();
    227     }
    228 
    229     @Override
    230     protected void onDestroy() {
    231         super.onDestroy();
    232         mGLRootView.lockRenderThread();
    233         try {
    234             getStateManager().destroy();
    235         } finally {
    236             mGLRootView.unlockRenderThread();
    237         }
    238         doUnbindBatchService();
    239     }
    240 
    241     @Override
    242     protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    243         mGLRootView.lockRenderThread();
    244         try {
    245             getStateManager().notifyActivityResult(
    246                     requestCode, resultCode, data);
    247         } finally {
    248             mGLRootView.unlockRenderThread();
    249         }
    250     }
    251 
    252     @Override
    253     public void onBackPressed() {
    254         // send the back event to the top sub-state
    255         GLRoot root = getGLRoot();
    256         root.lockRenderThread();
    257         try {
    258             getStateManager().onBackPressed();
    259         } finally {
    260             root.unlockRenderThread();
    261         }
    262     }
    263 
    264     public GalleryActionBar getGalleryActionBar() {
    265         if (mActionBar == null) {
    266             mActionBar = new GalleryActionBar(this);
    267         }
    268         return mActionBar;
    269     }
    270 
    271     @Override
    272     public boolean onOptionsItemSelected(MenuItem item) {
    273         GLRoot root = getGLRoot();
    274         root.lockRenderThread();
    275         try {
    276             return getStateManager().itemSelected(item);
    277         } finally {
    278             root.unlockRenderThread();
    279         }
    280     }
    281 
    282     protected void disableToggleStatusBar() {
    283         mDisableToggleStatusBar = true;
    284     }
    285 
    286     // Shows status bar in portrait view, hide in landscape view
    287     private void toggleStatusBarByOrientation() {
    288         if (mDisableToggleStatusBar) return;
    289 
    290         Window win = getWindow();
    291         if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
    292             win.clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
    293         } else {
    294             win.addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
    295         }
    296     }
    297 
    298     public TransitionStore getTransitionStore() {
    299         return mTransitionStore;
    300     }
    301 
    302     public PanoramaViewHelper getPanoramaViewHelper() {
    303         return mPanoramaViewHelper;
    304     }
    305 
    306     protected boolean isFullscreen() {
    307         return (getWindow().getAttributes().flags
    308                 & WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0;
    309     }
    310 
    311     private BatchService mBatchService;
    312     private boolean mBatchServiceIsBound = false;
    313     private ServiceConnection mBatchServiceConnection = new ServiceConnection() {
    314         public void onServiceConnected(ComponentName className, IBinder service) {
    315             mBatchService = ((BatchService.LocalBinder)service).getService();
    316         }
    317 
    318         public void onServiceDisconnected(ComponentName className) {
    319             mBatchService = null;
    320         }
    321     };
    322 
    323     private void doBindBatchService() {
    324         bindService(new Intent(this, BatchService.class), mBatchServiceConnection, Context.BIND_AUTO_CREATE);
    325         mBatchServiceIsBound = true;
    326     }
    327 
    328     private void doUnbindBatchService() {
    329         if (mBatchServiceIsBound) {
    330             // Detach our existing connection.
    331             unbindService(mBatchServiceConnection);
    332             mBatchServiceIsBound = false;
    333         }
    334     }
    335 
    336     public ThreadPool getBatchServiceThreadPoolIfAvailable() {
    337         if (mBatchServiceIsBound && mBatchService != null) {
    338             return mBatchService.getThreadPool();
    339         } else {
    340             throw new RuntimeException("Batch service unavailable");
    341         }
    342     }
    343 }
    344