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