| package com.cooliris.media; |
| |
| import java.io.IOException; |
| import java.net.URISyntaxException; |
| import java.util.HashMap; |
| import java.util.TimeZone; |
| |
| import android.app.Activity; |
| import android.app.ProgressDialog; |
| import android.content.Context; |
| import android.content.Intent; |
| import android.content.res.Configuration; |
| import android.graphics.Bitmap; |
| import android.net.Uri; |
| import android.os.Bundle; |
| import android.os.Handler; |
| import android.os.PowerManager; |
| import android.os.PowerManager.WakeLock; |
| import android.provider.MediaStore.Images; |
| import android.util.DisplayMetrics; |
| import android.util.Log; |
| import android.view.KeyEvent; |
| import android.widget.Toast; |
| import android.media.MediaScannerConnection; |
| |
| import com.cooliris.cache.CacheService; |
| import com.cooliris.wallpaper.RandomDataSource; |
| import com.cooliris.wallpaper.Slideshow; |
| |
| public final class Gallery extends Activity { |
| public static final TimeZone CURRENT_TIME_ZONE = TimeZone.getDefault(); |
| public static float PIXEL_DENSITY = 0.0f; |
| public static final int CROP_MSG_INTERNAL = 100; |
| |
| private static final String TAG = "Gallery"; |
| private static final int CROP_MSG = 10; |
| private RenderView mRenderView = null; |
| private GridLayer mGridLayer; |
| private final Handler mHandler = new Handler(); |
| private ReverseGeocoder mReverseGeocoder; |
| private boolean mPause; |
| private MediaScannerConnection mConnection; |
| private WakeLock mWakeLock; |
| private HashMap<String, Boolean> mAccountsEnabled = new HashMap<String, Boolean>(); |
| |
| @Override |
| public void onCreate(Bundle savedInstanceState) { |
| super.onCreate(savedInstanceState); |
| final boolean imageManagerHasStorage = ImageManager.quickHasStorage(); |
| boolean slideshowIntent = false; |
| if (isViewIntent()) { |
| Bundle extras = getIntent().getExtras(); |
| if (extras != null) { |
| slideshowIntent = extras.getBoolean("slideshow", false); |
| } |
| } |
| if (isViewIntent() && getIntent().getData().equals(Images.Media.EXTERNAL_CONTENT_URI) |
| && slideshowIntent) { |
| if (!imageManagerHasStorage) { |
| Toast.makeText(this, getResources().getString(R.string.no_sd_card), Toast.LENGTH_LONG).show(); |
| finish(); |
| } else { |
| PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE); |
| mWakeLock = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK, "GridView.Slideshow.All"); |
| mWakeLock.acquire(); |
| Slideshow slideshow = new Slideshow(this); |
| slideshow.setDataSource(new RandomDataSource()); |
| setContentView(slideshow); |
| } |
| return; |
| } |
| CacheService.computeDirtySets(this); |
| final boolean isCacheReady = CacheService.isCacheReady(false); |
| if (PIXEL_DENSITY == 0.0f) { |
| DisplayMetrics metrics = new DisplayMetrics(); |
| getWindowManager().getDefaultDisplay().getMetrics(metrics); |
| PIXEL_DENSITY = metrics.density; |
| } |
| mReverseGeocoder = new ReverseGeocoder(this); |
| mRenderView = new RenderView(this); |
| mGridLayer = new GridLayer(this, (int) (96.0f * PIXEL_DENSITY), (int) (72.0f * PIXEL_DENSITY), new GridLayoutInterface(4), |
| mRenderView); |
| mRenderView.setRootLayer(mGridLayer); |
| setContentView(mRenderView); |
| |
| // Creating the DataSource objects. |
| final PicasaDataSource picasaDataSource = new PicasaDataSource(this); |
| final LocalDataSource localDataSource = new LocalDataSource(this); |
| final ConcatenatedDataSource combinedDataSource = new ConcatenatedDataSource(localDataSource, picasaDataSource); |
| |
| // Depending upon the intent, we assign the right dataSource. |
| if (!isPickIntent() && !isViewIntent()) { |
| if (imageManagerHasStorage) { |
| mGridLayer.setDataSource(combinedDataSource); |
| } else { |
| mGridLayer.setDataSource(picasaDataSource); |
| } |
| if (!imageManagerHasStorage) { |
| Toast.makeText(this, getResources().getString(R.string.no_sd_card), Toast.LENGTH_LONG).show(); |
| } else if (!isCacheReady) { |
| Toast.makeText(this, getResources().getString(R.string.loading_new), Toast.LENGTH_LONG).show(); |
| } |
| } else if (!isViewIntent()) { |
| final Intent intent = getIntent(); |
| if (intent != null) { |
| final String type = intent.resolveType(this); |
| boolean includeImages = isImageType(type); |
| boolean includeVideos = isVideoType(type); |
| ((LocalDataSource) localDataSource).setMimeFilter(!includeImages, !includeVideos); |
| if (includeImages) { |
| if (imageManagerHasStorage) { |
| mGridLayer.setDataSource(combinedDataSource); |
| } else { |
| mGridLayer.setDataSource(picasaDataSource); |
| } |
| } else { |
| mGridLayer.setDataSource(localDataSource); |
| } |
| mGridLayer.setPickIntent(true); |
| if (!imageManagerHasStorage) { |
| Toast.makeText(this, getResources().getString(R.string.no_sd_card), Toast.LENGTH_LONG).show(); |
| } else { |
| Toast.makeText(this, getResources().getString(R.string.pick_prompt), Toast.LENGTH_LONG).show(); |
| } |
| } |
| } else { |
| // View intent for images. |
| Uri uri = getIntent().getData(); |
| boolean slideshow = getIntent().getBooleanExtra("slideshow", false); |
| final SingleDataSource singleDataSource = new SingleDataSource(this, uri.toString(), slideshow); |
| final ConcatenatedDataSource singleCombinedDataSource = new ConcatenatedDataSource(singleDataSource, picasaDataSource); |
| mGridLayer.setDataSource(singleCombinedDataSource); |
| mGridLayer.setViewIntent(true, Utils.getBucketNameFromUri(uri)); |
| if (singleDataSource.isSingleImage()) { |
| mGridLayer.setSingleImage(false); |
| } else if (slideshow) { |
| mGridLayer.setSingleImage(true); |
| mGridLayer.startSlideshow(); |
| } |
| } |
| // We record the set of enabled accounts for picasa. |
| mAccountsEnabled = PicasaDataSource.getAccountStatus(this); |
| Log.i(TAG, "onCreate"); |
| } |
| |
| public ReverseGeocoder getReverseGeocoder() { |
| return mReverseGeocoder; |
| } |
| |
| public Handler getHandler() { |
| return mHandler; |
| } |
| |
| @Override |
| public void onRestart() { |
| super.onRestart(); |
| } |
| |
| @Override |
| public void onStart() { |
| super.onStart(); |
| } |
| |
| @Override |
| public void onResume() { |
| super.onResume(); |
| CacheService.computeDirtySets(this); |
| CacheService.startCache(this, false); |
| if (mRenderView != null) { |
| mRenderView.onResume(); |
| } |
| if (mPause) { |
| // We check to see if the authenticated accounts have changed, and |
| // if so, reload the datasource. |
| HashMap<String, Boolean> accountsEnabled = PicasaDataSource.getAccountStatus(this); |
| String[] keys = new String[accountsEnabled.size()]; |
| keys = accountsEnabled.keySet().toArray(keys); |
| int numKeys = keys.length; |
| for (int i = 0; i < numKeys; ++i) { |
| String key = keys[i]; |
| boolean newValue = accountsEnabled.get(key).booleanValue(); |
| boolean oldValue = false; |
| Boolean oldValObj = mAccountsEnabled.get(key); |
| if (oldValObj != null) { |
| oldValue = oldValObj.booleanValue(); |
| } |
| if (oldValue != newValue) { |
| // Reload the datasource. |
| if (mGridLayer != null) |
| mGridLayer.setDataSource(mGridLayer.getDataSource()); |
| break; |
| } |
| } |
| mAccountsEnabled = accountsEnabled; |
| mPause = false; |
| } |
| } |
| |
| @Override |
| public void onPause() { |
| super.onPause(); |
| if (mRenderView != null) |
| mRenderView.onPause(); |
| mPause = true; |
| } |
| |
| public boolean isPaused() { |
| return mPause; |
| } |
| |
| @Override |
| public void onStop() { |
| super.onStop(); |
| if (mGridLayer != null) |
| mGridLayer.stop(); |
| if (mReverseGeocoder != null) { |
| mReverseGeocoder.flushCache(); |
| } |
| LocalDataSource.sThumbnailCache.flush(); |
| LocalDataSource.sThumbnailCacheVideo.flush(); |
| PicasaDataSource.sThumbnailCache.flush(); |
| CacheService.startCache(this, true); |
| } |
| |
| @Override |
| public void onDestroy() { |
| // Force GLThread to exit. |
| setContentView(R.layout.main); |
| if (mGridLayer != null) { |
| DataSource dataSource = mGridLayer.getDataSource(); |
| if (dataSource != null) { |
| dataSource.shutdown(); |
| } |
| mGridLayer.shutdown(); |
| } |
| if (mWakeLock != null) { |
| if (mWakeLock.isHeld()) { |
| mWakeLock.release(); |
| } |
| mWakeLock = null; |
| } |
| if (mReverseGeocoder != null) |
| mReverseGeocoder.shutdown(); |
| if (mRenderView != null) { |
| mRenderView.shutdown(); |
| mRenderView = null; |
| } |
| mGridLayer = null; |
| super.onDestroy(); |
| Log.i(TAG, "onDestroy"); |
| } |
| |
| @Override |
| public void onConfigurationChanged(Configuration newConfig) { |
| super.onConfigurationChanged(newConfig); |
| if (mGridLayer != null) { |
| mGridLayer.markDirty(30); |
| } |
| if (mRenderView != null) |
| mRenderView.requestRender(); |
| Log.i(TAG, "onConfigurationChanged"); |
| } |
| |
| @Override |
| public boolean onKeyDown(int keyCode, KeyEvent event) { |
| if (mRenderView != null) { |
| return mRenderView.onKeyDown(keyCode, event) || super.onKeyDown(keyCode, event); |
| } else { |
| return super.onKeyDown(keyCode, event); |
| } |
| } |
| |
| private boolean isPickIntent() { |
| String action = getIntent().getAction(); |
| return (Intent.ACTION_PICK.equals(action) || Intent.ACTION_GET_CONTENT.equals(action)); |
| } |
| |
| private boolean isViewIntent() { |
| String action = getIntent().getAction(); |
| return Intent.ACTION_VIEW.equals(action); |
| } |
| |
| private boolean isImageType(String type) { |
| return type.equals("vnd.android.cursor.dir/image") || type.equals("image/*"); |
| } |
| |
| private boolean isVideoType(String type) { |
| return type.equals("vnd.android.cursor.dir/video") || type.equals("video/*"); |
| } |
| |
| @Override |
| protected void onActivityResult(int requestCode, int resultCode, Intent data) { |
| switch (requestCode) { |
| case CROP_MSG: { |
| if (resultCode == RESULT_OK) { |
| setResult(resultCode, data); |
| finish(); |
| } |
| break; |
| } |
| case CROP_MSG_INTERNAL: { |
| // We cropped an image, we must try to set the focus of the camera |
| // to that image. |
| if (resultCode == RESULT_OK) { |
| String contentUri = data.getAction(); |
| if (mGridLayer != null) { |
| mGridLayer.focusItem(contentUri); |
| } |
| } |
| break; |
| } |
| } |
| } |
| |
| @Override |
| public void onLowMemory() { |
| if (mRenderView != null) { |
| mRenderView.handleLowMemory(); |
| } |
| } |
| |
| public void launchCropperOrFinish(final MediaItem item) { |
| final Bundle myExtras = getIntent().getExtras(); |
| String cropValue = myExtras != null ? myExtras.getString("crop") : null; |
| final String contentUri = item.mContentUri; |
| if (cropValue != null) { |
| Bundle newExtras = new Bundle(); |
| if (cropValue.equals("circle")) { |
| newExtras.putString("circleCrop", "true"); |
| } |
| Intent cropIntent = new Intent(); |
| cropIntent.setData(Uri.parse(contentUri)); |
| cropIntent.setClass(this, CropImage.class); |
| cropIntent.putExtras(newExtras); |
| // Pass through any extras that were passed in. |
| cropIntent.putExtras(myExtras); |
| startActivityForResult(cropIntent, CROP_MSG); |
| } else { |
| if (contentUri.startsWith("http://")) { |
| // This is a http uri, we must save it locally first and |
| // generate a content uri from it. |
| final ProgressDialog dialog = ProgressDialog.show(this, this.getResources().getString(R.string.initializing), |
| getResources().getString(R.string.running_face_detection), true, false); |
| if (contentUri != null) { |
| MediaScannerConnection.MediaScannerConnectionClient client = new MediaScannerConnection.MediaScannerConnectionClient() { |
| public void onMediaScannerConnected() { |
| if (mConnection != null) { |
| try { |
| final String path = UriTexture.writeHttpDataInDirectory(Gallery.this, contentUri, |
| LocalDataSource.DOWNLOAD_BUCKET_NAME); |
| if (path != null) { |
| mConnection.scanFile(path, item.mMimeType); |
| } else { |
| shutdown(""); |
| } |
| } catch (Exception e) { |
| shutdown(""); |
| } |
| } |
| } |
| |
| public void onScanCompleted(String path, Uri uri) { |
| shutdown(uri.toString()); |
| } |
| |
| public void shutdown(String uri) { |
| dialog.dismiss(); |
| performReturn(myExtras, uri.toString()); |
| if (mConnection != null) { |
| mConnection.disconnect(); |
| } |
| } |
| }; |
| MediaScannerConnection connection = new MediaScannerConnection(Gallery.this, client); |
| connection.connect(); |
| mConnection = connection; |
| } |
| } else { |
| performReturn(myExtras, contentUri); |
| } |
| } |
| } |
| |
| private void performReturn(Bundle myExtras, String contentUri) { |
| Intent result = new Intent(null, Uri.parse(contentUri)); |
| if (myExtras != null && myExtras.getBoolean("return-data")) { |
| // The size of a transaction should be below 100K. |
| Bitmap bitmap = null; |
| try { |
| bitmap = UriTexture.createFromUri(this, contentUri, 1024, 1024, 0, null); |
| } catch (IOException e) { |
| ; |
| } catch (URISyntaxException e) { |
| ; |
| } |
| if (bitmap != null) { |
| result.putExtra("data", bitmap); |
| } |
| } |
| setResult(RESULT_OK, result); |
| finish(); |
| } |
| } |