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.android.gallery3d.app;
18 
19 import android.app.Dialog;
20 import android.content.ContentResolver;
21 import android.content.DialogInterface;
22 import android.content.DialogInterface.OnCancelListener;
23 import android.content.Intent;
24 import android.net.Uri;
25 import android.os.Bundle;
26 import android.view.InputDevice;
27 import android.view.MotionEvent;
28 import android.view.View;
29 import android.view.Window;
30 import android.view.WindowManager;
31 import android.widget.Toast;
32 
33 import com.android.gallery3d.R;
34 import com.android.gallery3d.common.Utils;
35 import com.android.gallery3d.data.DataManager;
36 import com.android.gallery3d.data.MediaItem;
37 import com.android.gallery3d.data.MediaSet;
38 import com.android.gallery3d.data.Path;
39 import com.android.gallery3d.picasasource.PicasaSource;
40 import com.android.gallery3d.util.GalleryUtils;
41 
42 public final class GalleryActivity extends AbstractGalleryActivity implements OnCancelListener {
43     public static final String EXTRA_SLIDESHOW = "slideshow";
44     public static final String EXTRA_DREAM = "dream";
45     public static final String EXTRA_CROP = "crop";
46 
47     public static final String ACTION_REVIEW = "com.android.camera.action.REVIEW";
48     public static final String KEY_GET_CONTENT = "get-content";
49     public static final String KEY_GET_ALBUM = "get-album";
50     public static final String KEY_TYPE_BITS = "type-bits";
51     public static final String KEY_MEDIA_TYPES = "mediaTypes";
52     public static final String KEY_DISMISS_KEYGUARD = "dismiss-keyguard";
53 
54     private static final String TAG = "GalleryActivity";
55     private Dialog mVersionCheckDialog;
56 
57     @Override
onCreate(Bundle savedInstanceState)58     protected void onCreate(Bundle savedInstanceState) {
59         super.onCreate(savedInstanceState);
60         requestWindowFeature(Window.FEATURE_ACTION_BAR);
61         requestWindowFeature(Window.FEATURE_ACTION_BAR_OVERLAY);
62 
63         if (getIntent().getBooleanExtra(KEY_DISMISS_KEYGUARD, false)) {
64             getWindow().addFlags(
65                     WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
66         }
67 
68         setContentView(R.layout.main);
69 
70         if (savedInstanceState != null) {
71             getStateManager().restoreFromState(savedInstanceState);
72         } else {
73             initializeByIntent();
74         }
75     }
76 
initializeByIntent()77     private void initializeByIntent() {
78         Intent intent = getIntent();
79         String action = intent.getAction();
80 
81         if (Intent.ACTION_GET_CONTENT.equalsIgnoreCase(action)) {
82             startGetContent(intent);
83         } else if (Intent.ACTION_PICK.equalsIgnoreCase(action)) {
84             // We do NOT really support the PICK intent. Handle it as
85             // the GET_CONTENT. However, we need to translate the type
86             // in the intent here.
87             Log.w(TAG, "action PICK is not supported");
88             String type = Utils.ensureNotNull(intent.getType());
89             if (type.startsWith("vnd.android.cursor.dir/")) {
90                 if (type.endsWith("/image")) intent.setType("image/*");
91                 if (type.endsWith("/video")) intent.setType("video/*");
92             }
93             startGetContent(intent);
94         } else if (Intent.ACTION_VIEW.equalsIgnoreCase(action)
95                 || ACTION_REVIEW.equalsIgnoreCase(action)){
96             startViewAction(intent);
97         } else {
98             startDefaultPage();
99         }
100     }
101 
startDefaultPage()102     public void startDefaultPage() {
103         PicasaSource.showSignInReminder(this);
104         Bundle data = new Bundle();
105         data.putString(AlbumSetPage.KEY_MEDIA_PATH,
106                 getDataManager().getTopSetPath(DataManager.INCLUDE_ALL));
107         getStateManager().startState(AlbumSetPage.class, data);
108         mVersionCheckDialog = PicasaSource.getVersionCheckDialog(this);
109         if (mVersionCheckDialog != null) {
110             mVersionCheckDialog.setOnCancelListener(this);
111         }
112     }
113 
startGetContent(Intent intent)114     private void startGetContent(Intent intent) {
115         Bundle data = intent.getExtras() != null
116                 ? new Bundle(intent.getExtras())
117                 : new Bundle();
118         data.putBoolean(KEY_GET_CONTENT, true);
119         int typeBits = GalleryUtils.determineTypeBits(this, intent);
120         data.putInt(KEY_TYPE_BITS, typeBits);
121         data.putString(AlbumSetPage.KEY_MEDIA_PATH,
122                 getDataManager().getTopSetPath(typeBits));
123         getStateManager().startState(AlbumSetPage.class, data);
124     }
125 
getContentType(Intent intent)126     private String getContentType(Intent intent) {
127         String type = intent.getType();
128         if (type != null) {
129             return GalleryUtils.MIME_TYPE_PANORAMA360.equals(type)
130                 ? MediaItem.MIME_TYPE_JPEG : type;
131         }
132 
133         Uri uri = intent.getData();
134         try {
135             return getContentResolver().getType(uri);
136         } catch (Throwable t) {
137             Log.w(TAG, "get type fail", t);
138             return null;
139         }
140     }
141 
startViewAction(Intent intent)142     private void startViewAction(Intent intent) {
143         Boolean slideshow = intent.getBooleanExtra(EXTRA_SLIDESHOW, false);
144         if (slideshow) {
145             getActionBar().hide();
146             DataManager manager = getDataManager();
147             Path path = manager.findPathByUri(intent.getData(), intent.getType());
148             if (path == null || manager.getMediaObject(path)
149                     instanceof MediaItem) {
150                 path = Path.fromString(
151                         manager.getTopSetPath(DataManager.INCLUDE_IMAGE));
152             }
153             Bundle data = new Bundle();
154             data.putString(SlideshowPage.KEY_SET_PATH, path.toString());
155             data.putBoolean(SlideshowPage.KEY_RANDOM_ORDER, true);
156             data.putBoolean(SlideshowPage.KEY_REPEAT, true);
157             if (intent.getBooleanExtra(EXTRA_DREAM, false)) {
158                 data.putBoolean(SlideshowPage.KEY_DREAM, true);
159             }
160             getStateManager().startState(SlideshowPage.class, data);
161         } else {
162             Bundle data = new Bundle();
163             DataManager dm = getDataManager();
164             Uri uri = intent.getData();
165             String contentType = getContentType(intent);
166             if (contentType == null) {
167                 Toast.makeText(this,
168                         R.string.no_such_item, Toast.LENGTH_LONG).show();
169                 finish();
170                 return;
171             }
172             if (uri == null) {
173                 int typeBits = GalleryUtils.determineTypeBits(this, intent);
174                 data.putInt(KEY_TYPE_BITS, typeBits);
175                 data.putString(AlbumSetPage.KEY_MEDIA_PATH,
176                         getDataManager().getTopSetPath(typeBits));
177                 getStateManager().startState(AlbumSetPage.class, data);
178             } else if (contentType.startsWith(
179                     ContentResolver.CURSOR_DIR_BASE_TYPE)) {
180                 int mediaType = intent.getIntExtra(KEY_MEDIA_TYPES, 0);
181                 if (mediaType != 0) {
182                     uri = uri.buildUpon().appendQueryParameter(
183                             KEY_MEDIA_TYPES, String.valueOf(mediaType))
184                             .build();
185                 }
186                 Path setPath = dm.findPathByUri(uri, null);
187                 MediaSet mediaSet = null;
188                 if (setPath != null) {
189                     mediaSet = (MediaSet) dm.getMediaObject(setPath);
190                 }
191                 if (mediaSet != null) {
192                     if (mediaSet.isLeafAlbum()) {
193                         data.putString(AlbumPage.KEY_MEDIA_PATH, setPath.toString());
194                         data.putString(AlbumPage.KEY_PARENT_MEDIA_PATH,
195                                 dm.getTopSetPath(DataManager.INCLUDE_ALL));
196                         getStateManager().startState(AlbumPage.class, data);
197                     } else {
198                         data.putString(AlbumSetPage.KEY_MEDIA_PATH, setPath.toString());
199                         getStateManager().startState(AlbumSetPage.class, data);
200                     }
201                 } else {
202                     startDefaultPage();
203                 }
204             } else {
205                 Path itemPath = dm.findPathByUri(uri, contentType);
206                 Path albumPath = dm.getDefaultSetOf(itemPath);
207 
208                 data.putString(PhotoPage.KEY_MEDIA_ITEM_PATH, itemPath.toString());
209                 data.putBoolean(PhotoPage.KEY_READONLY, true);
210 
211                 // TODO: Make the parameter "SingleItemOnly" public so other
212                 //       activities can reference it.
213                 boolean singleItemOnly = (albumPath == null)
214                         || intent.getBooleanExtra("SingleItemOnly", false);
215                 if (!singleItemOnly) {
216                     data.putString(PhotoPage.KEY_MEDIA_SET_PATH, albumPath.toString());
217                     // when FLAG_ACTIVITY_NEW_TASK is set, (e.g. when intent is fired
218                     // from notification), back button should behave the same as up button
219                     // rather than taking users back to the home screen
220                     if (intent.getBooleanExtra(PhotoPage.KEY_TREAT_BACK_AS_UP, false)
221                             || ((intent.getFlags() & Intent.FLAG_ACTIVITY_NEW_TASK) != 0)) {
222                         data.putBoolean(PhotoPage.KEY_TREAT_BACK_AS_UP, true);
223                     }
224                 }
225 
226                 getStateManager().startState(SinglePhotoPage.class, data);
227             }
228         }
229     }
230 
231     @Override
onResume()232     protected void onResume() {
233         Utils.assertTrue(getStateManager().getStateCount() > 0);
234         super.onResume();
235         if (mVersionCheckDialog != null) {
236             mVersionCheckDialog.show();
237         }
238     }
239 
240     @Override
onPause()241     protected void onPause() {
242         super.onPause();
243         if (mVersionCheckDialog != null) {
244             mVersionCheckDialog.dismiss();
245         }
246     }
247 
248     @Override
onCancel(DialogInterface dialog)249     public void onCancel(DialogInterface dialog) {
250         if (dialog == mVersionCheckDialog) {
251             mVersionCheckDialog = null;
252         }
253     }
254 
255     @Override
onGenericMotionEvent(MotionEvent event)256     public boolean onGenericMotionEvent(MotionEvent event) {
257         final boolean isTouchPad = (event.getSource()
258                 & InputDevice.SOURCE_CLASS_POSITION) != 0;
259         if (isTouchPad) {
260             float maxX = event.getDevice().getMotionRange(MotionEvent.AXIS_X).getMax();
261             float maxY = event.getDevice().getMotionRange(MotionEvent.AXIS_Y).getMax();
262             View decor = getWindow().getDecorView();
263             float scaleX = decor.getWidth() / maxX;
264             float scaleY = decor.getHeight() / maxY;
265             float x = event.getX() * scaleX;
266             //x = decor.getWidth() - x; // invert x
267             float y = event.getY() * scaleY;
268             //y = decor.getHeight() - y; // invert y
269             MotionEvent touchEvent = MotionEvent.obtain(event.getDownTime(),
270                     event.getEventTime(), event.getAction(), x, y, event.getMetaState());
271             return dispatchTouchEvent(touchEvent);
272         }
273         return super.onGenericMotionEvent(event);
274     }
275 }
276