/* * Copyright (C) 2010 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.gallery3d.app; import android.annotation.TargetApi; import android.app.Activity; import android.app.AlertDialog; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; import android.content.DialogInterface; import android.content.DialogInterface.OnCancelListener; import android.content.DialogInterface.OnClickListener; import android.content.Intent; import android.content.IntentFilter; import android.content.ServiceConnection; import android.content.res.Configuration; import android.os.Bundle; import android.os.IBinder; import android.view.Menu; import android.view.MenuItem; import android.view.Window; import android.view.WindowManager; import com.android.gallery3d.R; import com.android.gallery3d.common.ApiHelper; import com.android.gallery3d.data.DataManager; import com.android.gallery3d.data.MediaItem; import com.android.gallery3d.ui.GLRoot; import com.android.gallery3d.ui.GLRootView; import com.android.gallery3d.util.LightCycleHelper.PanoramaViewHelper; import com.android.gallery3d.util.ThreadPool; import com.android.photos.data.GalleryBitmapPool; public class AbstractGalleryActivity extends Activity implements GalleryContext { @SuppressWarnings("unused") private static final String TAG = "AbstractGalleryActivity"; private GLRootView mGLRootView; private StateManager mStateManager; private GalleryActionBar mActionBar; private OrientationManager mOrientationManager; private TransitionStore mTransitionStore = new TransitionStore(); private boolean mDisableToggleStatusBar; private PanoramaViewHelper mPanoramaViewHelper; private AlertDialog mAlertDialog = null; private BroadcastReceiver mMountReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { if (getExternalCacheDir() != null) onStorageReady(); } }; private IntentFilter mMountFilter = new IntentFilter(Intent.ACTION_MEDIA_MOUNTED); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mOrientationManager = new OrientationManager(this); toggleStatusBarByOrientation(); getWindow().setBackgroundDrawable(null); mPanoramaViewHelper = new PanoramaViewHelper(this); mPanoramaViewHelper.onCreate(); doBindBatchService(); } @Override protected void onSaveInstanceState(Bundle outState) { mGLRootView.lockRenderThread(); try { super.onSaveInstanceState(outState); getStateManager().saveState(outState); } finally { mGLRootView.unlockRenderThread(); } } @Override public void onConfigurationChanged(Configuration config) { super.onConfigurationChanged(config); mStateManager.onConfigurationChange(config); getGalleryActionBar().onConfigurationChanged(); invalidateOptionsMenu(); toggleStatusBarByOrientation(); } @Override public boolean onCreateOptionsMenu(Menu menu) { super.onCreateOptionsMenu(menu); return getStateManager().createOptionsMenu(menu); } @Override public Context getAndroidContext() { return this; } @Override public DataManager getDataManager() { return ((GalleryApp) getApplication()).getDataManager(); } @Override public ThreadPool getThreadPool() { return ((GalleryApp) getApplication()).getThreadPool(); } public synchronized StateManager getStateManager() { if (mStateManager == null) { mStateManager = new StateManager(this); } return mStateManager; } public GLRoot getGLRoot() { return mGLRootView; } public OrientationManager getOrientationManager() { return mOrientationManager; } @Override public void setContentView(int resId) { super.setContentView(resId); mGLRootView = (GLRootView) findViewById(R.id.gl_root_view); } protected void onStorageReady() { if (mAlertDialog != null) { mAlertDialog.dismiss(); mAlertDialog = null; unregisterReceiver(mMountReceiver); } } @Override protected void onStart() { super.onStart(); if (getExternalCacheDir() == null) { OnCancelListener onCancel = new OnCancelListener() { @Override public void onCancel(DialogInterface dialog) { finish(); } }; OnClickListener onClick = new OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.cancel(); } }; AlertDialog.Builder builder = new AlertDialog.Builder(this) .setTitle(R.string.no_external_storage_title) .setMessage(R.string.no_external_storage) .setNegativeButton(android.R.string.cancel, onClick) .setOnCancelListener(onCancel); if (ApiHelper.HAS_SET_ICON_ATTRIBUTE) { setAlertDialogIconAttribute(builder); } else { builder.setIcon(android.R.drawable.ic_dialog_alert); } mAlertDialog = builder.show(); registerReceiver(mMountReceiver, mMountFilter); } mPanoramaViewHelper.onStart(); } @TargetApi(ApiHelper.VERSION_CODES.HONEYCOMB) private static void setAlertDialogIconAttribute( AlertDialog.Builder builder) { builder.setIconAttribute(android.R.attr.alertDialogIcon); } @Override protected void onStop() { super.onStop(); if (mAlertDialog != null) { unregisterReceiver(mMountReceiver); mAlertDialog.dismiss(); mAlertDialog = null; } mPanoramaViewHelper.onStop(); } @Override protected void onResume() { super.onResume(); mGLRootView.lockRenderThread(); try { getStateManager().resume(); getDataManager().resume(); } finally { mGLRootView.unlockRenderThread(); } mGLRootView.onResume(); mOrientationManager.resume(); } @Override protected void onPause() { super.onPause(); mOrientationManager.pause(); mGLRootView.onPause(); mGLRootView.lockRenderThread(); try { getStateManager().pause(); getDataManager().pause(); } finally { mGLRootView.unlockRenderThread(); } GalleryBitmapPool.getInstance().clear(); MediaItem.getBytesBufferPool().clear(); } @Override protected void onDestroy() { super.onDestroy(); mGLRootView.lockRenderThread(); try { getStateManager().destroy(); } finally { mGLRootView.unlockRenderThread(); } doUnbindBatchService(); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { mGLRootView.lockRenderThread(); try { getStateManager().notifyActivityResult( requestCode, resultCode, data); } finally { mGLRootView.unlockRenderThread(); } } @Override public void onBackPressed() { // send the back event to the top sub-state GLRoot root = getGLRoot(); root.lockRenderThread(); try { getStateManager().onBackPressed(); } finally { root.unlockRenderThread(); } } public GalleryActionBar getGalleryActionBar() { if (mActionBar == null) { mActionBar = new GalleryActionBar(this); } return mActionBar; } @Override public boolean onOptionsItemSelected(MenuItem item) { GLRoot root = getGLRoot(); root.lockRenderThread(); try { return getStateManager().itemSelected(item); } finally { root.unlockRenderThread(); } } protected void disableToggleStatusBar() { mDisableToggleStatusBar = true; } // Shows status bar in portrait view, hide in landscape view private void toggleStatusBarByOrientation() { if (mDisableToggleStatusBar) return; Window win = getWindow(); if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) { win.clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); } else { win.addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); } } public TransitionStore getTransitionStore() { return mTransitionStore; } public PanoramaViewHelper getPanoramaViewHelper() { return mPanoramaViewHelper; } protected boolean isFullscreen() { return (getWindow().getAttributes().flags & WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0; } private BatchService mBatchService; private boolean mBatchServiceIsBound = false; private ServiceConnection mBatchServiceConnection = new ServiceConnection() { public void onServiceConnected(ComponentName className, IBinder service) { mBatchService = ((BatchService.LocalBinder)service).getService(); } public void onServiceDisconnected(ComponentName className) { mBatchService = null; } }; private void doBindBatchService() { bindService(new Intent(this, BatchService.class), mBatchServiceConnection, Context.BIND_AUTO_CREATE); mBatchServiceIsBound = true; } private void doUnbindBatchService() { if (mBatchServiceIsBound) { // Detach our existing connection. unbindService(mBatchServiceConnection); mBatchServiceIsBound = false; } } public ThreadPool getBatchServiceThreadPoolIfAvailable() { if (mBatchServiceIsBound && mBatchService != null) { return mBatchService.getThreadPool(); } else { throw new RuntimeException("Batch service unavailable"); } } }