• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2011 Google Inc.
3  * Licensed to The Android Open Source Project.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 package com.android.ex.photo;
19 
20 import android.app.Activity;
21 import android.content.ContentProvider;
22 import android.content.Context;
23 import android.content.Intent;
24 import android.net.Uri;
25 
26 import com.android.ex.photo.fragments.PhotoViewFragment;
27 
28 /**
29  * Build intents to start app activities
30  */
31 
32 public class Intents {
33     // Intent extras
34     public static final String EXTRA_PHOTO_INDEX = "photo_index";
35     public static final String EXTRA_INITIAL_PHOTO_URI = "initial_photo_uri";
36     public static final String EXTRA_PHOTOS_URI = "photos_uri";
37     public static final String EXTRA_RESOLVED_PHOTO_URI = "resolved_photo_uri";
38     public static final String EXTRA_PROJECTION = "projection";
39     public static final String EXTRA_THUMBNAIL_URI = "thumbnail_uri";
40     public static final String EXTRA_MAX_INITIAL_SCALE = "max_scale";
41     public static final String EXTRA_WATCH_NETWORK = "watch_network";
42     public static final String EXTRA_ENABLE_TIMER_LIGHTS_OUT = "enable_timer_lights_out";
43 
44 
45     // Parameters affecting the intro/exit animation
46     public static final String EXTRA_SCALE_UP_ANIMATION = "scale_up_animation";
47     public static final String EXTRA_ANIMATION_START_X = "start_x_extra";
48     public static final String EXTRA_ANIMATION_START_Y = "start_y_extra";
49     public static final String EXTRA_ANIMATION_START_WIDTH = "start_width_extra";
50     public static final String EXTRA_ANIMATION_START_HEIGHT = "start_height_extra";
51 
52     // Parameters affecting the display and features
53     public static final String EXTRA_ACTION_BAR_HIDDEN_INITIALLY = "action_bar_hidden_initially";
54     public static final String EXTRA_DISPLAY_THUMBS_FULLSCREEN = "display_thumbs_fullscreen";
55 
56     /**
57      * Gets a photo view intent builder to display the photos from phone activity.
58      *
59      * @param context The context
60      * @return The intent builder
61      */
newPhotoViewActivityIntentBuilder(Context context)62     public static PhotoViewIntentBuilder newPhotoViewActivityIntentBuilder(Context context) {
63         return new PhotoViewIntentBuilder(context, PhotoViewActivity.class);
64     }
65 
66     /**
67      * Gets a photo view intent builder to display the photo view fragment
68      *
69      * @param context The context
70      * @return The intent builder
71      */
newPhotoViewFragmentIntentBuilder(Context context)72     public static PhotoViewIntentBuilder newPhotoViewFragmentIntentBuilder(Context context) {
73         return newPhotoViewFragmentIntentBuilder(context, PhotoViewFragment.class);
74     }
75 
76     /**
77      * Gets a photo view intent builder to display the photo view fragment with a custom fragment
78      * subclass.
79      *
80      * @param context The context
81      * @param clazz Subclass of PhotoViewFragment to use
82      * @return The intent builder
83      */
newPhotoViewFragmentIntentBuilder(Context context, Class<? extends PhotoViewFragment> clazz)84     public static PhotoViewIntentBuilder newPhotoViewFragmentIntentBuilder(Context context,
85             Class<? extends PhotoViewFragment> clazz) {
86         return new PhotoViewIntentBuilder(context, clazz);
87     }
88 
89     /** Gets a new photo view intent builder */
newPhotoViewIntentBuilder( Context context, Class<? extends Activity> cls)90     public static PhotoViewIntentBuilder newPhotoViewIntentBuilder(
91             Context context, Class<? extends Activity> cls) {
92         return new PhotoViewIntentBuilder(context, cls);
93     }
94 
95     /** Gets a new photo view intent builder */
newPhotoViewIntentBuilder( Context context, String activityName)96     public static PhotoViewIntentBuilder newPhotoViewIntentBuilder(
97             Context context, String activityName) {
98         return new PhotoViewIntentBuilder(context, activityName);
99     }
100 
101     /** Builder to create a photo view intent */
102     public static class PhotoViewIntentBuilder {
103         private final Intent mIntent;
104 
105         /** The index of the photo to show */
106         private Integer mPhotoIndex;
107         /** The URI of the initial photo to show */
108         private String mInitialPhotoUri;
109         /** The URI of the initial thumbnail to show */
110         private String mInitialThumbnailUri;
111         /** The URI of the group of photos to display */
112         private String mPhotosUri;
113         /** The URL of the photo to display */
114         private String mResolvedPhotoUri;
115         /** The projection for the query to use; optional */
116         private String[] mProjection;
117         /** The URI of a thumbnail of the photo to display */
118         private String mThumbnailUri;
119         /** The maximum scale to display images at before  */
120         private Float mMaxInitialScale;
121         /** True if lights out should automatically be invoked on a timer basis */
122         private boolean mEnableTimerLightsOut;
123         /**
124          * True if the PhotoViewFragments should watch for network changes to restart their loaders
125          */
126         private boolean mWatchNetwork;
127         /** true we want to run the image scale animation */
128         private boolean mScaleAnimation;
129         /** The parameters for performing the scale up/scale down animations
130          * upon enter and exit. StartX and StartY represent the screen coordinates
131          * of the upper left corner of the start rectangle, startWidth and startHeight
132          * represent the width and height of the start rectangle.
133          */
134         private int mStartX;
135         private int mStartY;
136         private int mStartWidth;
137         private int mStartHeight;
138 
139         private boolean mActionBarHiddenInitially;
140         private boolean mDisplayFullScreenThumbs;
141 
PhotoViewIntentBuilder(Context context, Class<?> cls)142         private PhotoViewIntentBuilder(Context context, Class<?> cls) {
143             mIntent = new Intent(context, cls);
144             initialize();
145         }
146 
PhotoViewIntentBuilder(Context context, String activityName)147         private PhotoViewIntentBuilder(Context context, String activityName) {
148             mIntent = new Intent();
149             mIntent.setClassName(context, activityName);
150             initialize();
151         }
152 
initialize()153         private void initialize() {
154             mScaleAnimation = false;
155             mActionBarHiddenInitially = false;
156             mDisplayFullScreenThumbs = false;
157             mEnableTimerLightsOut = true;
158         }
159 
160         /** Sets auto lights out */
setEnableTimerLightsOut(boolean enable)161         public PhotoViewIntentBuilder setEnableTimerLightsOut(boolean enable) {
162             mEnableTimerLightsOut = enable;
163             return this;
164         }
165 
166         /** Sets the photo index */
setPhotoIndex(Integer photoIndex)167         public PhotoViewIntentBuilder setPhotoIndex(Integer photoIndex) {
168             mPhotoIndex = photoIndex;
169             return this;
170         }
171 
172         /** Sets the initial photo URI */
setInitialPhotoUri(String initialPhotoUri)173         public PhotoViewIntentBuilder setInitialPhotoUri(String initialPhotoUri) {
174             mInitialPhotoUri = initialPhotoUri;
175             return this;
176         }
177 
178         /** Sets the photos URI */
setPhotosUri(String photosUri)179         public PhotoViewIntentBuilder setPhotosUri(String photosUri) {
180             mPhotosUri = photosUri;
181             return this;
182         }
183 
184         /** Sets the query projection */
setProjection(String[] projection)185         public PhotoViewIntentBuilder setProjection(String[] projection) {
186             mProjection = projection;
187             return this;
188         }
189 
190         /** Sets the resolved photo URI. This method is for the case
191          *  where the URI given to {@link PhotoViewActivity} points directly
192          *  to a single image and does not need to be resolved via a query
193          *  to the {@link ContentProvider}. If this value is set, it supersedes
194          *  {@link #setPhotosUri(String)}. */
setResolvedPhotoUri(String resolvedPhotoUri)195         public PhotoViewIntentBuilder setResolvedPhotoUri(String resolvedPhotoUri) {
196             mResolvedPhotoUri = resolvedPhotoUri;
197             return this;
198         }
199 
200         /**
201          * Sets the URI for a thumbnail preview of the photo.
202          */
setThumbnailUri(String thumbnailUri)203         public PhotoViewIntentBuilder setThumbnailUri(String thumbnailUri) {
204             mThumbnailUri = thumbnailUri;
205             return this;
206         }
207 
208         /**
209          * Sets the maximum scale which an image is initially displayed at
210          */
setMaxInitialScale(float maxScale)211         public PhotoViewIntentBuilder setMaxInitialScale(float maxScale) {
212             mMaxInitialScale = maxScale;
213             return this;
214         }
215 
216         /**
217          * Enable watching the network for connectivity changes.
218          *
219          * When a change is detected, bitmap loaders will be restarted if required.
220          */
watchNetworkConnectivityChanges()221         public PhotoViewIntentBuilder watchNetworkConnectivityChanges() {
222             mWatchNetwork = true;
223             return this;
224         }
225 
226         /**
227          * Enable a scale animation that animates the initial photo URI passed in using
228          * {@link #setInitialPhotoUri}.
229          *
230          * Note: To avoid janky transitions, particularly when exiting the photoviewer, ensure the
231          * following system UI flags are set on the root view of the relying app's activity
232          * (via @{link View.setSystemUiVisibility(int)}):
233          *     {@code View.SYSTEM_UI_FLAG_VISIBLE | View.SYSTEM_UI_FLAG_LAYOUT_STABLE}
234          * As well, client should ensure {@code android:fitsSystemWindows} is set on the root
235          * content view.
236          */
setScaleAnimation(int startX, int startY, int startWidth, int startHeight)237         public PhotoViewIntentBuilder setScaleAnimation(int startX, int startY,
238                 int startWidth, int startHeight) {
239             mScaleAnimation = true;
240             mStartX = startX;
241             mStartY = startY;
242             mStartWidth = startWidth;
243             mStartHeight = startHeight;
244             return this;
245         }
246 
247         // If this option is turned on, then the photoViewer will be initially
248         // displayed with the action bar hidden. This is as opposed to the default
249         // behavior, where the actionBar is initially shown.
setActionBarHiddenInitially( boolean actionBarHiddenInitially)250         public PhotoViewIntentBuilder setActionBarHiddenInitially(
251                 boolean actionBarHiddenInitially) {
252             mActionBarHiddenInitially = actionBarHiddenInitially;
253             return this;
254         }
255 
256         // If this option is turned on, then the small, lo-res thumbnail will
257         // be scaled up to the maximum size to cover as much of the screen as
258         // possible while still maintaining the correct aspect ratio. This means
259         // that the image may appear blurry until the the full-res image is
260         // loaded.
261         // This is as opposed to the default behavior, where only part of the
262         // thumbnail is displayed in a small view in the center of the screen,
263         // and a loading spinner is displayed until the full-res image is loaded.
setDisplayThumbsFullScreen( boolean displayFullScreenThumbs)264         public PhotoViewIntentBuilder setDisplayThumbsFullScreen(
265                 boolean displayFullScreenThumbs) {
266             mDisplayFullScreenThumbs = displayFullScreenThumbs;
267             return this;
268         }
269 
270         /** Build the intent */
build()271         public Intent build() {
272             mIntent.setAction(Intent.ACTION_VIEW);
273 
274             // In Lollipop, each list of photos should appear as a document in the "Recents"
275             // list. In earlier versions, this flag was Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET.
276             mIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT
277                     // FLAG_ACTIVITY_CLEAR_TOP is needed for the case where the app tries to
278                     // display a different photo while there is an existing activity instance
279                     // for that list of photos. Since the initial photo is specified as an
280                     // extra, without FLAG_ACTIVITY_CLEAR_TOP, the activity instance would
281                     // just get restarted and it would display whatever photo it was last
282                     // displaying. FLAG_ACTIVITY_CLEAR_TOP causes a new instance to be created,
283                     // and it will display the new initial photo.
284                     | Intent.FLAG_ACTIVITY_CLEAR_TOP);
285 
286             if (mPhotoIndex != null) {
287                 mIntent.putExtra(EXTRA_PHOTO_INDEX, (int) mPhotoIndex);
288             }
289 
290             if (mInitialPhotoUri != null) {
291                 mIntent.putExtra(EXTRA_INITIAL_PHOTO_URI, mInitialPhotoUri);
292             }
293 
294             if (mInitialPhotoUri != null && mPhotoIndex != null) {
295                 throw new IllegalStateException(
296                         "specified both photo index and photo uri");
297             }
298 
299             if (mPhotosUri != null) {
300                 mIntent.putExtra(EXTRA_PHOTOS_URI, mPhotosUri);
301                 mIntent.setData(Uri.parse(mPhotosUri));
302             }
303 
304             if (mResolvedPhotoUri != null) {
305                 mIntent.putExtra(EXTRA_RESOLVED_PHOTO_URI, mResolvedPhotoUri);
306             }
307 
308             if (mProjection != null) {
309                 mIntent.putExtra(EXTRA_PROJECTION, mProjection);
310             }
311 
312             if (mThumbnailUri != null) {
313                 mIntent.putExtra(EXTRA_THUMBNAIL_URI, mThumbnailUri);
314             }
315 
316             if (mMaxInitialScale != null) {
317                 mIntent.putExtra(EXTRA_MAX_INITIAL_SCALE, mMaxInitialScale);
318             }
319 
320             mIntent.putExtra(EXTRA_WATCH_NETWORK, mWatchNetwork);
321 
322             mIntent.putExtra(EXTRA_SCALE_UP_ANIMATION, mScaleAnimation);
323             if (mScaleAnimation) {
324                 mIntent.putExtra(EXTRA_ANIMATION_START_X, mStartX);
325                 mIntent.putExtra(EXTRA_ANIMATION_START_Y, mStartY);
326                 mIntent.putExtra(EXTRA_ANIMATION_START_WIDTH, mStartWidth);
327                 mIntent.putExtra(EXTRA_ANIMATION_START_HEIGHT, mStartHeight);
328             }
329 
330             mIntent.putExtra(EXTRA_ACTION_BAR_HIDDEN_INITIALLY, mActionBarHiddenInitially);
331             mIntent.putExtra(EXTRA_DISPLAY_THUMBS_FULLSCREEN, mDisplayFullScreenThumbs);
332             mIntent.putExtra(EXTRA_ENABLE_TIMER_LIGHTS_OUT, mEnableTimerLightsOut);
333             return mIntent;
334         }
335     }
336 }
337