OSDN Git Service

Patch to fix NPE for view intent on all pictures
[android-x86/packages-apps-Gallery2.git] / src / com / cooliris / media / Gallery.java
1 package com.cooliris.media;
2
3 import java.io.IOException;
4 import java.net.URISyntaxException;
5 import java.util.HashMap;
6 import java.util.TimeZone;
7
8 import android.app.Activity;
9 import android.app.ProgressDialog;
10 import android.content.Context;
11 import android.content.Intent;
12 import android.content.res.Configuration;
13 import android.graphics.Bitmap;
14 import android.net.Uri;
15 import android.os.Bundle;
16 import android.os.Handler;
17 import android.os.PowerManager;
18 import android.os.PowerManager.WakeLock;
19 import android.provider.MediaStore.Images;
20 import android.util.DisplayMetrics;
21 import android.util.Log;
22 import android.view.KeyEvent;
23 import android.widget.Toast;
24 import android.media.MediaScannerConnection;
25
26 import com.cooliris.cache.CacheService;
27 import com.cooliris.wallpaper.RandomDataSource;
28 import com.cooliris.wallpaper.Slideshow;
29
30 public final class Gallery extends Activity {
31     public static final TimeZone CURRENT_TIME_ZONE = TimeZone.getDefault();
32     public static float PIXEL_DENSITY = 0.0f;
33     public static final int CROP_MSG_INTERNAL = 100;
34
35     private static final String TAG = "Gallery";
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 HashMap<String, Boolean> mAccountsEnabled = new HashMap<String, Boolean>();
45
46     @Override
47     public void onCreate(Bundle savedInstanceState) {
48         super.onCreate(savedInstanceState);
49         final boolean imageManagerHasStorage = ImageManager.quickHasStorage();
50         boolean slideshowIntent = false;
51         if (isViewIntent()) {
52             Bundle extras = getIntent().getExtras();
53             if (extras != null) {
54                 slideshowIntent = extras.getBoolean("slideshow", false);
55             }
56         }
57         if (isViewIntent() && getIntent().getData().equals(Images.Media.EXTERNAL_CONTENT_URI)
58                 && slideshowIntent) {
59             if (!imageManagerHasStorage) {
60                 Toast.makeText(this, getResources().getString(R.string.no_sd_card), Toast.LENGTH_LONG).show();
61                 finish();
62             } else {
63                 PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
64                 mWakeLock = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK, "GridView.Slideshow.All");
65                 mWakeLock.acquire();
66                 Slideshow slideshow = new Slideshow(this);
67                 slideshow.setDataSource(new RandomDataSource());
68                 setContentView(slideshow);
69             }
70             return;
71         }
72         CacheService.computeDirtySets(this);
73         final boolean isCacheReady = CacheService.isCacheReady(false);
74         if (PIXEL_DENSITY == 0.0f) {
75             DisplayMetrics metrics = new DisplayMetrics();
76             getWindowManager().getDefaultDisplay().getMetrics(metrics);
77             PIXEL_DENSITY = metrics.density;
78         }
79         mReverseGeocoder = new ReverseGeocoder(this);
80         mRenderView = new RenderView(this);
81         mGridLayer = new GridLayer(this, (int) (96.0f * PIXEL_DENSITY), (int) (72.0f * PIXEL_DENSITY), new GridLayoutInterface(4),
82                 mRenderView);
83         mRenderView.setRootLayer(mGridLayer);
84         setContentView(mRenderView);
85
86         // Creating the DataSource objects.
87         final PicasaDataSource picasaDataSource = new PicasaDataSource(this);
88         final LocalDataSource localDataSource = new LocalDataSource(this);
89         final ConcatenatedDataSource combinedDataSource = new ConcatenatedDataSource(localDataSource, picasaDataSource);
90
91         // Depending upon the intent, we assign the right dataSource.
92         if (!isPickIntent() && !isViewIntent()) {
93             if (imageManagerHasStorage) {
94                 mGridLayer.setDataSource(combinedDataSource);
95             } else {
96                 mGridLayer.setDataSource(picasaDataSource);
97             }
98             if (!imageManagerHasStorage) {
99                 Toast.makeText(this, getResources().getString(R.string.no_sd_card), Toast.LENGTH_LONG).show();
100             } else if (!isCacheReady) {
101                 Toast.makeText(this, getResources().getString(R.string.loading_new), Toast.LENGTH_LONG).show();
102             }
103         } else if (!isViewIntent()) {
104             final Intent intent = getIntent();
105             if (intent != null) {
106                 final String type = intent.resolveType(this);
107                 boolean includeImages = isImageType(type);
108                 boolean includeVideos = isVideoType(type);
109                 ((LocalDataSource) localDataSource).setMimeFilter(!includeImages, !includeVideos);
110                 if (includeImages) {
111                     if (imageManagerHasStorage) {
112                         mGridLayer.setDataSource(combinedDataSource);
113                     } else {
114                         mGridLayer.setDataSource(picasaDataSource);
115                     }
116                 } else {
117                     mGridLayer.setDataSource(localDataSource);
118                 }
119                 mGridLayer.setPickIntent(true);
120                 if (!imageManagerHasStorage) {
121                     Toast.makeText(this, getResources().getString(R.string.no_sd_card), Toast.LENGTH_LONG).show();
122                 } else {
123                     Toast.makeText(this, getResources().getString(R.string.pick_prompt), Toast.LENGTH_LONG).show();
124                 }
125             }
126         } else {
127             // View intent for images.
128             Uri uri = getIntent().getData();
129             boolean slideshow = getIntent().getBooleanExtra("slideshow", false);
130             final SingleDataSource singleDataSource = new SingleDataSource(this, uri.toString(), slideshow);
131             final ConcatenatedDataSource singleCombinedDataSource = new ConcatenatedDataSource(singleDataSource, picasaDataSource);
132             mGridLayer.setDataSource(singleCombinedDataSource);
133             mGridLayer.setViewIntent(true, Utils.getBucketNameFromUri(uri));
134             if (singleDataSource.isSingleImage()) {
135                 mGridLayer.setSingleImage(false);
136             } else if (slideshow) {
137                 mGridLayer.setSingleImage(true);
138                 mGridLayer.startSlideshow();
139             }
140         }
141         // We record the set of enabled accounts for picasa.
142         mAccountsEnabled = PicasaDataSource.getAccountStatus(this);
143         Log.i(TAG, "onCreate");
144     }
145
146     public ReverseGeocoder getReverseGeocoder() {
147         return mReverseGeocoder;
148     }
149
150     public Handler getHandler() {
151         return mHandler;
152     }
153
154     @Override
155     public void onRestart() {
156         super.onRestart();
157     }
158
159     @Override
160     public void onStart() {
161         super.onStart();
162     }
163
164     @Override
165     public void onResume() {
166         super.onResume();
167         CacheService.computeDirtySets(this);
168         CacheService.startCache(this, false);
169         if (mRenderView != null) {
170             mRenderView.onResume();
171         }
172         if (mPause) {
173             // We check to see if the authenticated accounts have changed, and
174             // if so, reload the datasource.
175             HashMap<String, Boolean> accountsEnabled = PicasaDataSource.getAccountStatus(this);
176             String[] keys = new String[accountsEnabled.size()];
177             keys = accountsEnabled.keySet().toArray(keys);
178             int numKeys = keys.length;
179             for (int i = 0; i < numKeys; ++i) {
180                 String key = keys[i];
181                 boolean newValue = accountsEnabled.get(key).booleanValue();
182                 boolean oldValue = false;
183                 Boolean oldValObj = mAccountsEnabled.get(key);
184                 if (oldValObj != null) {
185                     oldValue = oldValObj.booleanValue();
186                 }
187                 if (oldValue != newValue) {
188                     // Reload the datasource.
189                     if (mGridLayer != null)
190                         mGridLayer.setDataSource(mGridLayer.getDataSource());
191                     break;
192                 }
193             }
194             mAccountsEnabled = accountsEnabled;
195             mPause = false;
196         }
197     }
198
199     @Override
200     public void onPause() {
201         super.onPause();
202         if (mRenderView != null)
203             mRenderView.onPause();
204         mPause = true;
205     }
206
207     public boolean isPaused() {
208         return mPause;
209     }
210
211     @Override
212     public void onStop() {
213         super.onStop();
214         if (mGridLayer != null)
215             mGridLayer.stop();
216         if (mReverseGeocoder != null) {
217             mReverseGeocoder.flushCache();
218         }
219         LocalDataSource.sThumbnailCache.flush();
220         LocalDataSource.sThumbnailCacheVideo.flush();
221         PicasaDataSource.sThumbnailCache.flush();
222         CacheService.startCache(this, true);
223     }
224
225     @Override
226     public void onDestroy() {
227         // Force GLThread to exit.
228         setContentView(R.layout.main);
229         if (mGridLayer != null) {
230             DataSource dataSource = mGridLayer.getDataSource();
231             if (dataSource != null) {
232                 dataSource.shutdown();
233             }
234             mGridLayer.shutdown();
235         }
236         if (mWakeLock != null) {
237             if (mWakeLock.isHeld()) {
238                 mWakeLock.release();
239             }
240             mWakeLock = null;
241         }
242         if (mReverseGeocoder != null)
243             mReverseGeocoder.shutdown();
244         if (mRenderView != null) {
245             mRenderView.shutdown();
246             mRenderView = null;
247         }
248         mGridLayer = null;
249         super.onDestroy();
250         Log.i(TAG, "onDestroy");
251     }
252
253     @Override
254     public void onConfigurationChanged(Configuration newConfig) {
255         super.onConfigurationChanged(newConfig);
256         if (mGridLayer != null) {
257             mGridLayer.markDirty(30);
258         }
259         if (mRenderView != null)
260             mRenderView.requestRender();
261         Log.i(TAG, "onConfigurationChanged");
262     }
263
264     @Override
265     public boolean onKeyDown(int keyCode, KeyEvent event) {
266         if (mRenderView != null) {
267             return mRenderView.onKeyDown(keyCode, event) || super.onKeyDown(keyCode, event);
268         } else {
269             return super.onKeyDown(keyCode, event);
270         }
271     }
272
273     private boolean isPickIntent() {
274         String action = getIntent().getAction();
275         return (Intent.ACTION_PICK.equals(action) || Intent.ACTION_GET_CONTENT.equals(action));
276     }
277
278     private boolean isViewIntent() {
279         String action = getIntent().getAction();
280         return Intent.ACTION_VIEW.equals(action);
281     }
282
283     private boolean isImageType(String type) {
284         return type.equals("vnd.android.cursor.dir/image") || type.equals("image/*");
285     }
286
287     private boolean isVideoType(String type) {
288         return type.equals("vnd.android.cursor.dir/video") || type.equals("video/*");
289     }
290
291     @Override
292     protected void onActivityResult(int requestCode, int resultCode, Intent data) {
293         switch (requestCode) {
294         case CROP_MSG: {
295             if (resultCode == RESULT_OK) {
296                 setResult(resultCode, data);
297                 finish();
298             }
299             break;
300         }
301         case CROP_MSG_INTERNAL: {
302             // We cropped an image, we must try to set the focus of the camera
303             // to that image.
304             if (resultCode == RESULT_OK) {
305                 String contentUri = data.getAction();
306                 if (mGridLayer != null) {
307                     mGridLayer.focusItem(contentUri);
308                 }
309             }
310             break;
311         }
312         }
313     }
314
315     @Override
316     public void onLowMemory() {
317         if (mRenderView != null) {
318             mRenderView.handleLowMemory();
319         }
320     }
321
322     public void launchCropperOrFinish(final MediaItem item) {
323         final Bundle myExtras = getIntent().getExtras();
324         String cropValue = myExtras != null ? myExtras.getString("crop") : null;
325         final String contentUri = item.mContentUri;
326         if (cropValue != null) {
327             Bundle newExtras = new Bundle();
328             if (cropValue.equals("circle")) {
329                 newExtras.putString("circleCrop", "true");
330             }
331             Intent cropIntent = new Intent();
332             cropIntent.setData(Uri.parse(contentUri));
333             cropIntent.setClass(this, CropImage.class);
334             cropIntent.putExtras(newExtras);
335             // Pass through any extras that were passed in.
336             cropIntent.putExtras(myExtras);
337             startActivityForResult(cropIntent, CROP_MSG);
338         } else {
339             if (contentUri.startsWith("http://")) {
340                 // This is a http uri, we must save it locally first and
341                 // generate a content uri from it.
342                 final ProgressDialog dialog = ProgressDialog.show(this, this.getResources().getString(R.string.initializing),
343                         getResources().getString(R.string.running_face_detection), true, false);
344                 if (contentUri != null) {
345                     MediaScannerConnection.MediaScannerConnectionClient client = new MediaScannerConnection.MediaScannerConnectionClient() {
346                         public void onMediaScannerConnected() {
347                             if (mConnection != null) {
348                                 try {
349                                     final String path = UriTexture.writeHttpDataInDirectory(Gallery.this, contentUri,
350                                             LocalDataSource.DOWNLOAD_BUCKET_NAME);
351                                     if (path != null) {
352                                         mConnection.scanFile(path, item.mMimeType);
353                                     } else {
354                                         shutdown("");
355                                     }
356                                 } catch (Exception e) {
357                                     shutdown("");
358                                 }
359                             }
360                         }
361
362                         public void onScanCompleted(String path, Uri uri) {
363                             shutdown(uri.toString());
364                         }
365
366                         public void shutdown(String uri) {
367                             dialog.dismiss();
368                             performReturn(myExtras, uri.toString());
369                             if (mConnection != null) {
370                                 mConnection.disconnect();
371                             }
372                         }
373                     };
374                     MediaScannerConnection connection = new MediaScannerConnection(Gallery.this, client);
375                     connection.connect();
376                     mConnection = connection;
377                 }
378             } else {
379                 performReturn(myExtras, contentUri);
380             }
381         }
382     }
383
384     private void performReturn(Bundle myExtras, String contentUri) {
385         Intent result = new Intent(null, Uri.parse(contentUri));
386         if (myExtras != null && myExtras.getBoolean("return-data")) {
387             // The size of a transaction should be below 100K.
388             Bitmap bitmap = null;
389             try {
390                 bitmap = UriTexture.createFromUri(this, contentUri, 1024, 1024, 0, null);
391             } catch (IOException e) {
392                 ;
393             } catch (URISyntaxException e) {
394                 ;
395             }
396             if (bitmap != null) {
397                 result.putExtra("data", bitmap);
398             }
399         }
400         setResult(RESULT_OK, result);
401         finish();
402     }
403 }