1 package com.cooliris.media;
3 import java.io.IOException;
4 import java.net.URISyntaxException;
5 import java.util.TimeZone;
7 import android.app.Activity;
8 import android.app.ProgressDialog;
9 import android.content.Context;
10 import android.content.Intent;
11 import android.content.res.Configuration;
12 import android.graphics.Bitmap;
13 import android.net.Uri;
14 import android.os.Bundle;
15 import android.os.Handler;
16 import android.os.PowerManager;
17 import android.os.PowerManager.WakeLock;
18 import android.provider.MediaStore.Images;
19 import android.util.DisplayMetrics;
20 import android.util.Log;
21 import android.view.KeyEvent;
22 import android.widget.Toast;
23 import android.media.MediaScannerConnection;
25 import com.cooliris.cache.CacheService;
26 import com.cooliris.wallpaper.RandomDataSource;
27 import com.cooliris.wallpaper.Slideshow;
29 public final class Gallery extends Activity {
30 public static final TimeZone CURRENT_TIME_ZONE = TimeZone.getDefault();
31 public static float PIXEL_DENSITY = 0.0f;
32 public static boolean NEEDS_REFRESH = true;
34 private static final String TAG = "Gallery";
35 public static final int CROP_MSG_INTERNAL = 100;
36 private static final int CROP_MSG = 10;
37 private RenderView mRenderView = null;
38 private GridLayer mGridLayer;
39 private final Handler mHandler = new Handler();
40 private ReverseGeocoder mReverseGeocoder;
41 private boolean mPause;
42 private MediaScannerConnection mConnection;
43 private WakeLock mWakeLock;
44 private static final boolean TEST_WALLPAPER = false;
47 public void onCreate(Bundle savedInstanceState) {
48 super.onCreate(savedInstanceState);
49 final boolean imageManagerHasStorage = ImageManager.quickHasStorage();
50 if (TEST_WALLPAPER || (isViewIntent() && getIntent().getData().equals(Images.Media.EXTERNAL_CONTENT_URI))) {
51 if (!imageManagerHasStorage) {
52 Toast.makeText(this, getResources().getString(R.string.no_sd_card), Toast.LENGTH_LONG).show();
55 PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
56 mWakeLock = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK, "GridView.Slideshow.All");
58 Slideshow slideshow = new Slideshow(this);
59 slideshow.setDataSource(new RandomDataSource());
60 setContentView(slideshow);
64 boolean isCacheReady = CacheService.isCacheReady(false);
65 CacheService.startCache(this, false);
66 if (PIXEL_DENSITY == 0.0f) {
67 DisplayMetrics metrics = new DisplayMetrics();
68 getWindowManager().getDefaultDisplay().getMetrics(metrics);
69 PIXEL_DENSITY = metrics.density;
71 mReverseGeocoder = new ReverseGeocoder(this);
72 mRenderView = new RenderView(this);
73 mGridLayer = new GridLayer(this, (int) (96.0f * PIXEL_DENSITY), (int) (72.0f * PIXEL_DENSITY), new GridLayoutInterface(4),
75 mRenderView.setRootLayer(mGridLayer);
76 setContentView(mRenderView);
77 if (!isPickIntent() && !isViewIntent()) {
78 PicasaDataSource picasaDataSource = new PicasaDataSource(this);
79 if (imageManagerHasStorage) {
80 LocalDataSource localDataSource = new LocalDataSource(this);
81 ConcatenatedDataSource combinedDataSource = new ConcatenatedDataSource(localDataSource, picasaDataSource);
82 mGridLayer.setDataSource(combinedDataSource);
84 mGridLayer.setDataSource(picasaDataSource);
86 if (!imageManagerHasStorage) {
87 Toast.makeText(this, getResources().getString(R.string.no_sd_card), Toast.LENGTH_LONG).show();
90 Toast.makeText(this, getResources().getString(R.string.loading_new), Toast.LENGTH_LONG).show();
92 // Toast.makeText(this, getResources().getString(R.string.initializing), Toast.LENGTH_SHORT).show();
95 } else if (!isViewIntent()) {
96 Intent intent = getIntent();
98 String type = intent.resolveType(this);
99 boolean includeImages = isImageType(type);
100 boolean includeVideos = isVideoType(type);
101 LocalDataSource localDataSource = new LocalDataSource(this);
102 ((LocalDataSource) localDataSource).setMimeFilter(!includeImages, !includeVideos);
104 PicasaDataSource picasaDataSource = new PicasaDataSource(this);
105 if (imageManagerHasStorage) {
106 ConcatenatedDataSource combinedDataSource = new ConcatenatedDataSource(localDataSource, picasaDataSource);
107 mGridLayer.setDataSource(combinedDataSource);
109 mGridLayer.setDataSource(picasaDataSource);
112 mGridLayer.setDataSource(localDataSource);
114 mGridLayer.setPickIntent(true);
115 if (!imageManagerHasStorage) {
116 Toast.makeText(this, getResources().getString(R.string.no_sd_card), Toast.LENGTH_LONG).show();
118 Toast.makeText(this, getResources().getString(R.string.pick_prompt), Toast.LENGTH_LONG).show();
122 // View intent for images.
123 Uri uri = getIntent().getData();
124 boolean slideshow = getIntent().getBooleanExtra("slideshow", false);
125 SingleDataSource localDataSource = new SingleDataSource(this, uri.toString(), slideshow);
126 PicasaDataSource picasaDataSource = new PicasaDataSource(this);
127 ConcatenatedDataSource combinedDataSource = new ConcatenatedDataSource(localDataSource, picasaDataSource);
128 mGridLayer.setDataSource(combinedDataSource);
129 mGridLayer.setViewIntent(true, Utils.getBucketNameFromUri(uri));
130 if (SingleDataSource.isSingleImageMode(uri.toString())) {
131 mGridLayer.setSingleImage(false);
132 } else if (slideshow) {
133 mGridLayer.setSingleImage(true);
134 mGridLayer.startSlideshow();
136 // Toast.makeText(this, getResources().getString(R.string.initializing), Toast.LENGTH_SHORT).show();
138 Log.i(TAG, "onCreate");
141 public ReverseGeocoder getReverseGeocoder() {
142 return mReverseGeocoder;
145 public Handler getHandler() {
150 public void onRestart() {
155 public void onStart() {
160 public void onResume() {
162 if (mRenderView != null)
163 mRenderView.onResume();
165 NEEDS_REFRESH = false;
166 CacheService.markDirtyImmediate(LocalDataSource.CAMERA_BUCKET_ID);
167 CacheService.markDirtyImmediate(LocalDataSource.DOWNLOAD_BUCKET_ID);
168 CacheService.startCache(this, false);
174 public void onPause() {
176 if (mRenderView != null)
177 mRenderView.onPause();
181 public boolean isPaused() {
186 public void onStop() {
188 if (mGridLayer != null)
190 if (mReverseGeocoder != null) {
191 mReverseGeocoder.flushCache();
193 LocalDataSource.sThumbnailCache.flush();
194 LocalDataSource.sThumbnailCacheVideo.flush();
195 PicasaDataSource.sThumbnailCache.flush();
196 CacheService.startCache(this, true);
200 public void onDestroy() {
201 // Force GLThread to exit.
202 setContentView(R.layout.main);
203 if (mGridLayer != null) {
204 DataSource dataSource = mGridLayer.getDataSource();
205 if (dataSource != null) {
206 dataSource.shutdown();
208 mGridLayer.shutdown();
210 if (mWakeLock != null) {
211 if (mWakeLock.isHeld()) {
216 if (mReverseGeocoder != null)
217 mReverseGeocoder.shutdown();
218 if (mRenderView != null) {
219 mRenderView.shutdown();
224 Log.i(TAG, "onDestroy");
228 public void onConfigurationChanged(Configuration newConfig) {
229 super.onConfigurationChanged(newConfig);
230 if (mGridLayer != null) {
231 mGridLayer.markDirty(30);
233 if (mRenderView != null)
234 mRenderView.requestRender();
235 Log.i(TAG, "onConfigurationChanged");
239 public boolean onKeyDown(int keyCode, KeyEvent event) {
240 if (mRenderView != null) {
241 return mRenderView.onKeyDown(keyCode, event) || super.onKeyDown(keyCode, event);
243 return super.onKeyDown(keyCode, event);
247 private boolean isPickIntent() {
248 String action = getIntent().getAction();
249 return (Intent.ACTION_PICK.equals(action) || Intent.ACTION_GET_CONTENT.equals(action));
252 private boolean isViewIntent() {
253 String action = getIntent().getAction();
254 return Intent.ACTION_VIEW.equals(action);
257 private boolean isImageType(String type) {
258 return type.equals("vnd.android.cursor.dir/image") || type.equals("image/*");
261 private boolean isVideoType(String type) {
262 return type.equals("vnd.android.cursor.dir/video") || type.equals("video/*");
266 protected void onActivityResult(int requestCode, int resultCode, Intent data) {
267 switch (requestCode) {
269 if (resultCode == RESULT_OK) {
270 setResult(resultCode, data);
275 case CROP_MSG_INTERNAL: {
276 // We cropped an image, we must try to set the focus of the camera to that image.
277 if (resultCode == RESULT_OK) {
278 String contentUri = data.getAction();
279 if (mGridLayer != null) {
280 mGridLayer.focusItem(contentUri);
289 public void onLowMemory() {
290 if (mRenderView != null) {
291 mRenderView.handleLowMemory();
295 public void launchCropperOrFinish(final MediaItem item) {
296 final Bundle myExtras = getIntent().getExtras();
297 String cropValue = myExtras != null ? myExtras.getString("crop") : null;
298 final String contentUri = item.mContentUri;
299 if (cropValue != null) {
300 Bundle newExtras = new Bundle();
301 if (cropValue.equals("circle")) {
302 newExtras.putString("circleCrop", "true");
304 Intent cropIntent = new Intent();
305 cropIntent.setData(Uri.parse(contentUri));
306 cropIntent.setClass(this, CropImage.class);
307 cropIntent.putExtras(newExtras);
308 // Pass through any extras that were passed in.
309 cropIntent.putExtras(myExtras);
310 startActivityForResult(cropIntent, CROP_MSG);
312 if (contentUri.startsWith("http://")) {
313 // This is a http uri, we must save it locally first and generate a content uri from it.
314 final ProgressDialog dialog = ProgressDialog.show(this, this.getResources().getString(R.string.initializing),
315 getResources().getString(R.string.running_face_detection), true, false);
316 if (contentUri != null) {
317 MediaScannerConnection.MediaScannerConnectionClient client = new MediaScannerConnection.MediaScannerConnectionClient() {
318 public void onMediaScannerConnected() {
319 if (mConnection != null) {
321 final String path = UriTexture.writeHttpDataInDirectory(Gallery.this, contentUri,
322 LocalDataSource.DOWNLOAD_BUCKET_NAME);
324 mConnection.scanFile(path, item.mMimeType);
328 } catch (Exception e) {
334 public void onScanCompleted(String path, Uri uri) {
335 shutdown(uri.toString());
338 public void shutdown(String uri) {
340 performReturn(myExtras, uri.toString());
341 if (mConnection != null) {
342 mConnection.disconnect();
346 MediaScannerConnection connection = new MediaScannerConnection(Gallery.this, client);
347 connection.connect();
348 mConnection = connection;
351 performReturn(myExtras, contentUri);
356 private void performReturn(Bundle myExtras, String contentUri) {
357 Intent result = new Intent(null, Uri.parse(contentUri));
358 if (myExtras != null && myExtras.getBoolean("return-data")) {
359 // The size of a transaction should be below 100K.
360 Bitmap bitmap = null;
362 bitmap = UriTexture.createFromUri(this, contentUri, 1024, 1024, 0, null);
363 } catch (IOException e) {
365 } catch (URISyntaxException e) {
368 if (bitmap != null) {
369 result.putExtra("data", bitmap);
372 setResult(RESULT_OK, result);