OSDN Git Service

original
[gb-231r1-is01/Gingerbread_2.3.3_r1_IS01.git] / packages / apps / Gallery3D / src / com / cooliris / media / Gallery.java
1 /*
2  * Copyright (C) 2009 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.cooliris.media;
18
19 import com.cooliris.app.App;
20 import com.cooliris.app.Res;
21 import com.cooliris.cache.CacheService;
22 import com.cooliris.wallpaper.RandomDataSource;
23 import com.cooliris.wallpaper.Slideshow;
24
25 import android.app.Activity;
26 import android.content.Context;
27 import android.content.Intent;
28 import android.content.res.Configuration;
29 import android.net.Uri;
30 import android.os.Bundle;
31 import android.os.Environment;
32 import android.os.Handler;
33 import android.os.HandlerThread;
34 import android.os.Message;
35 import android.os.PowerManager;
36 import android.os.PowerManager.WakeLock;
37 import android.provider.MediaStore.Images;
38 import android.util.Log;
39 import android.view.KeyEvent;
40 import android.widget.Toast;
41
42 import java.util.HashMap;
43
44 public final class Gallery extends Activity {
45     public static final String REVIEW_ACTION = "com.cooliris.media.action.REVIEW";
46     private static final String TAG = "Gallery";
47
48     private App mApp = null;
49     private RenderView mRenderView = null;
50     private GridLayer mGridLayer;
51     private WakeLock mWakeLock;
52     private HashMap<String, Boolean> mAccountsEnabled = new HashMap<String, Boolean>();
53     private boolean mDockSlideshow = false;
54     private int mNumRetries;
55     private boolean mImageManagerHasStorageAfterDelay = false;
56     private HandlerThread mPicasaAccountThread = new HandlerThread("PicasaAccountMonitor");
57     private Handler mPicasaHandler = null;
58
59     private static final int GET_PICASA_ACCOUNT_STATUS = 1;
60     private static final int UPDATE_PICASA_ACCOUNT_STATUS = 2;
61
62     private static final int CHECK_STORAGE = 0;
63     private static final int HANDLE_INTENT = 1;
64     private static final int NUM_STORAGE_CHECKS = 25;
65
66     private final Handler handler = new Handler() {
67         @Override
68         public void handleMessage(Message msg) {
69             switch (msg.what) {
70                 case CHECK_STORAGE:
71                     checkStorage();
72                     break;
73                 case HANDLE_INTENT:
74                     initializeDataSource();
75                     break;
76             }
77         }
78     };
79
80     private void checkStorage() {
81         mNumRetries++;
82         mImageManagerHasStorageAfterDelay = ImageManager.hasStorage();
83         if (!mImageManagerHasStorageAfterDelay && mNumRetries < NUM_STORAGE_CHECKS) {
84             if (mNumRetries == 1) {
85                 int res;
86
87                 if (Environment.isExternalStorageRemovable()) {
88                     res = Res.string.no_sd_card;
89                 } else {
90                     res = Res.string.no_usb_storage;
91                 }
92
93                 mApp.showToast(getResources().getString(res), Toast.LENGTH_LONG);
94             }
95             handler.sendEmptyMessageDelayed(CHECK_STORAGE, 200);
96         } else {
97             handler.sendEmptyMessage(HANDLE_INTENT);
98         }
99     }
100
101     @Override
102     public void onCreate(Bundle savedInstanceState) {
103         super.onCreate(savedInstanceState);
104         mApp = new App(Gallery.this);
105         final boolean imageManagerHasStorage = ImageManager.hasStorage();
106         boolean slideshowIntent = false;
107         if (isViewIntent()) {
108             Bundle extras = getIntent().getExtras();
109             if (extras != null) {
110                 slideshowIntent = extras.getBoolean("slideshow", false);
111             }
112         }
113         if (isViewIntent() && getIntent().getData().equals(Images.Media.EXTERNAL_CONTENT_URI) && slideshowIntent) {
114             if (!imageManagerHasStorage) {
115                 int res;
116
117                 if (Environment.isExternalStorageRemovable()) {
118                     res = Res.string.no_sd_card;
119                 } else {
120                     res = Res.string.no_usb_storage;
121                 }
122
123                 Toast.makeText(this, getResources().getString(res), Toast.LENGTH_LONG).show();
124                 finish();
125             } else {
126                 Slideshow slideshow = new Slideshow(this);
127                 slideshow.setDataSource(new RandomDataSource());
128                 setContentView(slideshow);
129                 mDockSlideshow = true;
130             }
131             return;
132         }
133         mRenderView = new RenderView(this);
134         mGridLayer = new GridLayer(this, (int) (96.0f * App.PIXEL_DENSITY), (int) (72.0f * App.PIXEL_DENSITY), new GridLayoutInterface(4),
135                 mRenderView);
136         mRenderView.setRootLayer(mGridLayer);
137         setContentView(mRenderView);
138
139         mPicasaAccountThread.start();
140         mPicasaHandler = new Handler(mPicasaAccountThread.getLooper()) {
141
142             @Override
143             public void handleMessage(Message msg) {
144                 switch (msg.what) {
145                     case GET_PICASA_ACCOUNT_STATUS:
146                         mAccountsEnabled = PicasaDataSource.getAccountStatus(Gallery.this);
147                         break;
148                     case UPDATE_PICASA_ACCOUNT_STATUS:
149                         updatePicasaAccountStatus();
150                         break;
151                 }
152             }
153         };
154
155         sendInitialMessage();
156
157         Log.i(TAG, "onCreate");
158     }
159
160     private void sendInitialMessage() {
161         mNumRetries = 0;
162         Message checkStorage = new Message();
163         checkStorage.what = CHECK_STORAGE;
164         handler.sendMessage(checkStorage);
165     }
166
167     @Override
168     protected void onNewIntent(Intent intent) {
169         setIntent(intent);
170         handler.removeMessages(CHECK_STORAGE);
171         handler.removeMessages(HANDLE_INTENT);
172
173         sendInitialMessage();
174     }
175
176     @Override
177     public void onRestart() {
178         super.onRestart();
179     }
180
181     @Override
182     public void onStart() {
183         super.onStart();
184     }
185
186     @Override
187     public void onResume() {
188         super.onResume();
189         if (mDockSlideshow) {
190             if (mWakeLock != null) {
191                 if (mWakeLock.isHeld()) {
192                     mWakeLock.release();
193                 }
194             }
195             PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
196             mWakeLock = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK, "GridView.Slideshow.All");
197             mWakeLock.acquire();
198             return;
199         }
200         if (mRenderView != null) {
201             mRenderView.onResume();
202         }
203         if (mApp.isPaused()) {
204             if (mPicasaHandler != null) {
205                 mPicasaHandler.removeMessages(GET_PICASA_ACCOUNT_STATUS);
206                 mPicasaHandler.sendEmptyMessage(UPDATE_PICASA_ACCOUNT_STATUS);
207             }
208                 mApp.onResume();
209         }
210     }
211
212     void updatePicasaAccountStatus() {
213         // We check to see if the authenticated accounts have
214         // changed, if so, reload the datasource.
215
216         // TODO: This should be done in PicasaDataFeed
217         if (mGridLayer != null) {
218             HashMap<String, Boolean> accountsEnabled = PicasaDataSource.getAccountStatus(this);
219             if (!accountsEnabled.equals(mAccountsEnabled)) {
220                 mGridLayer.setDataSource(mGridLayer.getDataSource());
221                 mAccountsEnabled = accountsEnabled;
222             }
223         }
224     }
225
226     @Override
227     public void onPause() {
228         super.onPause();
229         if (mRenderView != null)
230             mRenderView.onPause();
231         if (mWakeLock != null) {
232             if (mWakeLock.isHeld()) {
233                 mWakeLock.release();
234             }
235             mWakeLock = null;
236         }
237
238         LocalDataSource.sThumbnailCache.flush();
239         LocalDataSource.sThumbnailCacheVideo.flush();
240         PicasaDataSource.sThumbnailCache.flush();
241
242         if (mPicasaHandler != null) {
243             mPicasaHandler.removeMessages(GET_PICASA_ACCOUNT_STATUS);
244             mPicasaHandler.removeMessages(UPDATE_PICASA_ACCOUNT_STATUS);
245         }
246         mApp.onPause();
247     }
248
249     @Override
250     public void onStop() {
251         super.onStop();
252         if (mGridLayer != null)
253             mGridLayer.stop();
254
255         // Start the thumbnailer.
256         CacheService.startCache(this, true);
257     }
258
259     @Override
260     public void onDestroy() {
261         // Force GLThread to exit.
262         setContentView(Res.layout.main);
263
264         // Remove any post messages.
265         handler.removeMessages(CHECK_STORAGE);
266         handler.removeMessages(HANDLE_INTENT);
267
268         mPicasaAccountThread.quit();
269         mPicasaAccountThread = null;
270         mPicasaHandler = null;
271
272         if (mGridLayer != null) {
273             DataSource dataSource = mGridLayer.getDataSource();
274             if (dataSource != null) {
275                 dataSource.shutdown();
276             }
277             mGridLayer.shutdown();
278         }
279         if (mRenderView != null) {
280             mRenderView.shutdown();
281             mRenderView = null;
282         }
283         mGridLayer = null;
284         mApp.shutdown();
285         super.onDestroy();
286         Log.i(TAG, "onDestroy");
287     }
288
289     @Override
290     public void onConfigurationChanged(Configuration newConfig) {
291         super.onConfigurationChanged(newConfig);
292         if (mGridLayer != null) {
293             mGridLayer.markDirty(30);
294         }
295         if (mRenderView != null)
296             mRenderView.requestRender();
297         Log.i(TAG, "onConfigurationChanged");
298     }
299
300     @Override
301     public boolean onKeyDown(int keyCode, KeyEvent event) {
302         if (mRenderView != null) {
303             return mRenderView.onKeyDown(keyCode, event) || super.onKeyDown(keyCode, event);
304         } else {
305             return super.onKeyDown(keyCode, event);
306         }
307     }
308
309     private boolean isPickIntent() {
310         String action = getIntent().getAction();
311         return (Intent.ACTION_PICK.equals(action) || Intent.ACTION_GET_CONTENT.equals(action));
312     }
313
314     private boolean isViewIntent() {
315         String action = getIntent().getAction();
316         return Intent.ACTION_VIEW.equals(action);
317     }
318
319     private boolean isReviewIntent() {
320         String action = getIntent().getAction();
321         return REVIEW_ACTION.equals(action);
322     }
323
324     private boolean isImageType(String type) {
325         return type.contains("*/") || type.equals("vnd.android.cursor.dir/image") || type.equals("image/*");
326     }
327
328     private boolean isVideoType(String type) {
329         return type.contains("*/") || type.equals("vnd.android.cursor.dir/video") || type.equals("video/*");
330     }
331
332     @Override
333     protected void onActivityResult(int requestCode, int resultCode, Intent data) {
334         switch (requestCode) {
335         case CropImage.CROP_MSG: {
336             if (resultCode == RESULT_OK) {
337                 setResult(resultCode, data);
338                 finish();
339             }
340             break;
341         }
342         case CropImage.CROP_MSG_INTERNAL: {
343             // We cropped an image, we must try to set the focus of the camera
344             // to that image.
345             if (resultCode == RESULT_OK) {
346                 String contentUri = data.getAction();
347                 if (mGridLayer != null && contentUri != null) {
348                     mGridLayer.focusItem(contentUri);
349                 }
350             }
351             break;
352         }
353         }
354     }
355
356     @Override
357     public void onLowMemory() {
358         if (mRenderView != null) {
359             mRenderView.handleLowMemory();
360         }
361     }
362
363     private void initializeDataSource() {
364         final boolean hasStorage = mImageManagerHasStorageAfterDelay;
365         // Creating the DataSource objects.
366         final PicasaDataSource picasaDataSource = new PicasaDataSource(Gallery.this);
367         final LocalDataSource localDataSource = new LocalDataSource(Gallery.this, LocalDataSource.URI_ALL_MEDIA, false);
368         final ConcatenatedDataSource combinedDataSource = new ConcatenatedDataSource(localDataSource, picasaDataSource);
369
370         // Depending upon the intent, we assign the right dataSource.
371         if (!isPickIntent() && !isViewIntent() && !isReviewIntent()) {
372             localDataSource.setMimeFilter(true, true);
373             if (hasStorage) {
374                 mGridLayer.setDataSource(combinedDataSource);
375             } else {
376                 mGridLayer.setDataSource(picasaDataSource);
377             }
378         } else if (isPickIntent()) {
379             final Intent intent = getIntent();
380             if (intent != null) {
381                 String type = intent.resolveType(Gallery.this);
382                 if (type == null) {
383                     // By default, we include images
384                     type = "image/*";
385                 }
386                 boolean includeImages = isImageType(type);
387                 boolean includeVideos = isVideoType(type);
388                 localDataSource.setMimeFilter(includeImages, includeVideos);
389                 if (includeImages) {
390                     if (hasStorage) {
391                         mGridLayer.setDataSource(combinedDataSource);
392                     } else {
393                         mGridLayer.setDataSource(picasaDataSource);
394                     }
395                 } else {
396                     mGridLayer.setDataSource(localDataSource);
397                 }
398                 mGridLayer.setPickIntent(true);
399                 if (hasStorage) {
400                     mApp.showToast(getResources().getString(Res.string.pick_prompt), Toast.LENGTH_LONG);
401                 }
402             }
403         } else { // view intent for images and review intent for images and videos
404             final Intent intent = getIntent();
405             Uri uri = intent.getData();
406             boolean slideshow = intent.getBooleanExtra("slideshow", false);
407             final LocalDataSource singleDataSource = new LocalDataSource(Gallery.this, uri.toString(), true);
408             // Display both image and video.
409             singleDataSource.setMimeFilter(true, true);
410
411             if (hasStorage) {
412                 ConcatenatedDataSource singleCombinedDataSource = new ConcatenatedDataSource(singleDataSource,
413                         picasaDataSource);
414                 mGridLayer.setDataSource(singleCombinedDataSource);
415             } else {
416                 mGridLayer.setDataSource(picasaDataSource);
417             }
418             mGridLayer.setViewIntent(true, Utils.getBucketNameFromUri(getContentResolver(), uri));
419
420             if (isReviewIntent()) {
421                 mGridLayer.setEnterSelectionMode(true);
422             }
423
424             if (singleDataSource.isSingleImage()) {
425                 mGridLayer.setSingleImage(false);
426             } else if (slideshow) {
427                 mGridLayer.setSingleImage(true);
428                 mGridLayer.startSlideshow();
429             }
430         }
431         // We record the set of enabled accounts for picasa.
432         mPicasaHandler.sendEmptyMessage(GET_PICASA_ACCOUNT_STATUS);
433     }
434 }