• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2012 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 android.app;
18 
19 import android.content.Context;
20 import android.graphics.Bitmap;
21 import android.os.Bundle;
22 import android.os.Handler;
23 import android.os.IRemoteCallback;
24 import android.os.RemoteException;
25 import android.view.View;
26 
27 /**
28  * Helper class for building an options Bundle that can be used with
29  * {@link android.content.Context#startActivity(android.content.Intent, android.os.Bundle)
30  * Context.startActivity(Intent, Bundle)} and related methods.
31  */
32 public class ActivityOptions {
33     /**
34      * The package name that created the options.
35      * @hide
36      */
37     public static final String KEY_PACKAGE_NAME = "android:packageName";
38 
39     /**
40      * Type of animation that arguments specify.
41      * @hide
42      */
43     public static final String KEY_ANIM_TYPE = "android:animType";
44 
45     /**
46      * Custom enter animation resource ID.
47      * @hide
48      */
49     public static final String KEY_ANIM_ENTER_RES_ID = "android:animEnterRes";
50 
51     /**
52      * Custom exit animation resource ID.
53      * @hide
54      */
55     public static final String KEY_ANIM_EXIT_RES_ID = "android:animExitRes";
56 
57     /**
58      * Bitmap for thumbnail animation.
59      * @hide
60      */
61     public static final String KEY_ANIM_THUMBNAIL = "android:animThumbnail";
62 
63     /**
64      * Start X position of thumbnail animation.
65      * @hide
66      */
67     public static final String KEY_ANIM_START_X = "android:animStartX";
68 
69     /**
70      * Start Y position of thumbnail animation.
71      * @hide
72      */
73     public static final String KEY_ANIM_START_Y = "android:animStartY";
74 
75     /**
76      * Initial width of the animation.
77      * @hide
78      */
79     public static final String KEY_ANIM_START_WIDTH = "android:animStartWidth";
80 
81     /**
82      * Initial height of the animation.
83      * @hide
84      */
85     public static final String KEY_ANIM_START_HEIGHT = "android:animStartHeight";
86 
87     /**
88      * Callback for when animation is started.
89      * @hide
90      */
91     public static final String KEY_ANIM_START_LISTENER = "android:animStartListener";
92 
93     /** @hide */
94     public static final int ANIM_NONE = 0;
95     /** @hide */
96     public static final int ANIM_CUSTOM = 1;
97     /** @hide */
98     public static final int ANIM_SCALE_UP = 2;
99     /** @hide */
100     public static final int ANIM_THUMBNAIL_SCALE_UP = 3;
101     /** @hide */
102     public static final int ANIM_THUMBNAIL_SCALE_DOWN = 4;
103 
104     private String mPackageName;
105     private int mAnimationType = ANIM_NONE;
106     private int mCustomEnterResId;
107     private int mCustomExitResId;
108     private Bitmap mThumbnail;
109     private int mStartX;
110     private int mStartY;
111     private int mStartWidth;
112     private int mStartHeight;
113     private IRemoteCallback mAnimationStartedListener;
114 
115     /**
116      * Create an ActivityOptions specifying a custom animation to run when
117      * the activity is displayed.
118      *
119      * @param context Who is defining this.  This is the application that the
120      * animation resources will be loaded from.
121      * @param enterResId A resource ID of the animation resource to use for
122      * the incoming activity.  Use 0 for no animation.
123      * @param exitResId A resource ID of the animation resource to use for
124      * the outgoing activity.  Use 0 for no animation.
125      * @return Returns a new ActivityOptions object that you can use to
126      * supply these options as the options Bundle when starting an activity.
127      */
makeCustomAnimation(Context context, int enterResId, int exitResId)128     public static ActivityOptions makeCustomAnimation(Context context,
129             int enterResId, int exitResId) {
130         return makeCustomAnimation(context, enterResId, exitResId, null, null);
131     }
132 
133     /**
134      * Create an ActivityOptions specifying a custom animation to run when
135      * the activity is displayed.
136      *
137      * @param context Who is defining this.  This is the application that the
138      * animation resources will be loaded from.
139      * @param enterResId A resource ID of the animation resource to use for
140      * the incoming activity.  Use 0 for no animation.
141      * @param exitResId A resource ID of the animation resource to use for
142      * the outgoing activity.  Use 0 for no animation.
143      * @param handler If <var>listener</var> is non-null this must be a valid
144      * Handler on which to dispatch the callback; otherwise it should be null.
145      * @param listener Optional OnAnimationStartedListener to find out when the
146      * requested animation has started running.  If for some reason the animation
147      * is not executed, the callback will happen immediately.
148      * @return Returns a new ActivityOptions object that you can use to
149      * supply these options as the options Bundle when starting an activity.
150      * @hide
151      */
makeCustomAnimation(Context context, int enterResId, int exitResId, Handler handler, OnAnimationStartedListener listener)152     public static ActivityOptions makeCustomAnimation(Context context,
153             int enterResId, int exitResId, Handler handler, OnAnimationStartedListener listener) {
154         ActivityOptions opts = new ActivityOptions();
155         opts.mPackageName = context.getPackageName();
156         opts.mAnimationType = ANIM_CUSTOM;
157         opts.mCustomEnterResId = enterResId;
158         opts.mCustomExitResId = exitResId;
159         opts.setListener(handler, listener);
160         return opts;
161     }
162 
setListener(Handler handler, OnAnimationStartedListener listener)163     private void setListener(Handler handler, OnAnimationStartedListener listener) {
164         if (listener != null) {
165             final Handler h = handler;
166             final OnAnimationStartedListener finalListener = listener;
167             mAnimationStartedListener = new IRemoteCallback.Stub() {
168                 @Override public void sendResult(Bundle data) throws RemoteException {
169                     h.post(new Runnable() {
170                         @Override public void run() {
171                             finalListener.onAnimationStarted();
172                         }
173                     });
174                 }
175             };
176         }
177     }
178 
179     /**
180      * Callback for use with {@link ActivityOptions#makeThumbnailScaleUpAnimation}
181      * to find out when the given animation has started running.
182      * @hide
183      */
184     public interface OnAnimationStartedListener {
onAnimationStarted()185         void onAnimationStarted();
186     }
187 
188     /**
189      * Create an ActivityOptions specifying an animation where the new
190      * activity is scaled from a small originating area of the screen to
191      * its final full representation.
192      *
193      * <p>If the Intent this is being used with has not set its
194      * {@link android.content.Intent#setSourceBounds Intent.setSourceBounds},
195      * those bounds will be filled in for you based on the initial
196      * bounds passed in here.
197      *
198      * @param source The View that the new activity is animating from.  This
199      * defines the coordinate space for <var>startX</var> and <var>startY</var>.
200      * @param startX The x starting location of the new activity, relative to <var>source</var>.
201      * @param startY The y starting location of the activity, relative to <var>source</var>.
202      * @param startWidth The initial width of the new activity.
203      * @param startHeight The initial height of the new activity.
204      * @return Returns a new ActivityOptions object that you can use to
205      * supply these options as the options Bundle when starting an activity.
206      */
makeScaleUpAnimation(View source, int startX, int startY, int startWidth, int startHeight)207     public static ActivityOptions makeScaleUpAnimation(View source,
208             int startX, int startY, int startWidth, int startHeight) {
209         ActivityOptions opts = new ActivityOptions();
210         opts.mPackageName = source.getContext().getPackageName();
211         opts.mAnimationType = ANIM_SCALE_UP;
212         int[] pts = new int[2];
213         source.getLocationOnScreen(pts);
214         opts.mStartX = pts[0] + startX;
215         opts.mStartY = pts[1] + startY;
216         opts.mStartWidth = startWidth;
217         opts.mStartHeight = startHeight;
218         return opts;
219     }
220 
221     /**
222      * Create an ActivityOptions specifying an animation where a thumbnail
223      * is scaled from a given position to the new activity window that is
224      * being started.
225      *
226      * <p>If the Intent this is being used with has not set its
227      * {@link android.content.Intent#setSourceBounds Intent.setSourceBounds},
228      * those bounds will be filled in for you based on the initial
229      * thumbnail location and size provided here.
230      *
231      * @param source The View that this thumbnail is animating from.  This
232      * defines the coordinate space for <var>startX</var> and <var>startY</var>.
233      * @param thumbnail The bitmap that will be shown as the initial thumbnail
234      * of the animation.
235      * @param startX The x starting location of the bitmap, relative to <var>source</var>.
236      * @param startY The y starting location of the bitmap, relative to <var>source</var>.
237      * @return Returns a new ActivityOptions object that you can use to
238      * supply these options as the options Bundle when starting an activity.
239      */
makeThumbnailScaleUpAnimation(View source, Bitmap thumbnail, int startX, int startY)240     public static ActivityOptions makeThumbnailScaleUpAnimation(View source,
241             Bitmap thumbnail, int startX, int startY) {
242         return makeThumbnailScaleUpAnimation(source, thumbnail, startX, startY, null);
243     }
244 
245     /**
246      * Create an ActivityOptions specifying an animation where a thumbnail
247      * is scaled from a given position to the new activity window that is
248      * being started.
249      *
250      * @param source The View that this thumbnail is animating from.  This
251      * defines the coordinate space for <var>startX</var> and <var>startY</var>.
252      * @param thumbnail The bitmap that will be shown as the initial thumbnail
253      * of the animation.
254      * @param startX The x starting location of the bitmap, relative to <var>source</var>.
255      * @param startY The y starting location of the bitmap, relative to <var>source</var>.
256      * @param listener Optional OnAnimationStartedListener to find out when the
257      * requested animation has started running.  If for some reason the animation
258      * is not executed, the callback will happen immediately.
259      * @return Returns a new ActivityOptions object that you can use to
260      * supply these options as the options Bundle when starting an activity.
261      * @hide
262      */
makeThumbnailScaleUpAnimation(View source, Bitmap thumbnail, int startX, int startY, OnAnimationStartedListener listener)263     public static ActivityOptions makeThumbnailScaleUpAnimation(View source,
264             Bitmap thumbnail, int startX, int startY, OnAnimationStartedListener listener) {
265         return makeThumbnailAnimation(source, thumbnail, startX, startY, listener, true);
266     }
267 
268     /**
269      * Create an ActivityOptions specifying an animation where an activity window
270      * is scaled from a given position to a thumbnail at a specified location.
271      *
272      * @param source The View that this thumbnail is animating to.  This
273      * defines the coordinate space for <var>startX</var> and <var>startY</var>.
274      * @param thumbnail The bitmap that will be shown as the final thumbnail
275      * of the animation.
276      * @param startX The x end location of the bitmap, relative to <var>source</var>.
277      * @param startY The y end location of the bitmap, relative to <var>source</var>.
278      * @param listener Optional OnAnimationStartedListener to find out when the
279      * requested animation has started running.  If for some reason the animation
280      * is not executed, the callback will happen immediately.
281      * @return Returns a new ActivityOptions object that you can use to
282      * supply these options as the options Bundle when starting an activity.
283      * @hide
284      */
makeThumbnailScaleDownAnimation(View source, Bitmap thumbnail, int startX, int startY, OnAnimationStartedListener listener)285     public static ActivityOptions makeThumbnailScaleDownAnimation(View source,
286             Bitmap thumbnail, int startX, int startY, OnAnimationStartedListener listener) {
287         return makeThumbnailAnimation(source, thumbnail, startX, startY, listener, false);
288     }
289 
makeThumbnailAnimation(View source, Bitmap thumbnail, int startX, int startY, OnAnimationStartedListener listener, boolean scaleUp)290     private static ActivityOptions makeThumbnailAnimation(View source,
291             Bitmap thumbnail, int startX, int startY, OnAnimationStartedListener listener,
292             boolean scaleUp) {
293         ActivityOptions opts = new ActivityOptions();
294         opts.mPackageName = source.getContext().getPackageName();
295         opts.mAnimationType = scaleUp ? ANIM_THUMBNAIL_SCALE_UP : ANIM_THUMBNAIL_SCALE_DOWN;
296         opts.mThumbnail = thumbnail;
297         int[] pts = new int[2];
298         source.getLocationOnScreen(pts);
299         opts.mStartX = pts[0] + startX;
300         opts.mStartY = pts[1] + startY;
301         opts.setListener(source.getHandler(), listener);
302         return opts;
303     }
304 
ActivityOptions()305     private ActivityOptions() {
306     }
307 
308     /** @hide */
ActivityOptions(Bundle opts)309     public ActivityOptions(Bundle opts) {
310         mPackageName = opts.getString(KEY_PACKAGE_NAME);
311         mAnimationType = opts.getInt(KEY_ANIM_TYPE);
312         if (mAnimationType == ANIM_CUSTOM) {
313             mCustomEnterResId = opts.getInt(KEY_ANIM_ENTER_RES_ID, 0);
314             mCustomExitResId = opts.getInt(KEY_ANIM_EXIT_RES_ID, 0);
315             mAnimationStartedListener = IRemoteCallback.Stub.asInterface(
316                     opts.getIBinder(KEY_ANIM_START_LISTENER));
317         } else if (mAnimationType == ANIM_SCALE_UP) {
318             mStartX = opts.getInt(KEY_ANIM_START_X, 0);
319             mStartY = opts.getInt(KEY_ANIM_START_Y, 0);
320             mStartWidth = opts.getInt(KEY_ANIM_START_WIDTH, 0);
321             mStartHeight = opts.getInt(KEY_ANIM_START_HEIGHT, 0);
322         } else if (mAnimationType == ANIM_THUMBNAIL_SCALE_UP ||
323                 mAnimationType == ANIM_THUMBNAIL_SCALE_DOWN) {
324             mThumbnail = (Bitmap)opts.getParcelable(KEY_ANIM_THUMBNAIL);
325             mStartX = opts.getInt(KEY_ANIM_START_X, 0);
326             mStartY = opts.getInt(KEY_ANIM_START_Y, 0);
327             mAnimationStartedListener = IRemoteCallback.Stub.asInterface(
328                     opts.getIBinder(KEY_ANIM_START_LISTENER));
329         }
330     }
331 
332     /** @hide */
getPackageName()333     public String getPackageName() {
334         return mPackageName;
335     }
336 
337     /** @hide */
getAnimationType()338     public int getAnimationType() {
339         return mAnimationType;
340     }
341 
342     /** @hide */
getCustomEnterResId()343     public int getCustomEnterResId() {
344         return mCustomEnterResId;
345     }
346 
347     /** @hide */
getCustomExitResId()348     public int getCustomExitResId() {
349         return mCustomExitResId;
350     }
351 
352     /** @hide */
getThumbnail()353     public Bitmap getThumbnail() {
354         return mThumbnail;
355     }
356 
357     /** @hide */
getStartX()358     public int getStartX() {
359         return mStartX;
360     }
361 
362     /** @hide */
getStartY()363     public int getStartY() {
364         return mStartY;
365     }
366 
367     /** @hide */
getStartWidth()368     public int getStartWidth() {
369         return mStartWidth;
370     }
371 
372     /** @hide */
getStartHeight()373     public int getStartHeight() {
374         return mStartHeight;
375     }
376 
377     /** @hide */
getOnAnimationStartListener()378     public IRemoteCallback getOnAnimationStartListener() {
379         return mAnimationStartedListener;
380     }
381 
382     /** @hide */
abort()383     public void abort() {
384         if (mAnimationStartedListener != null) {
385             try {
386                 mAnimationStartedListener.sendResult(null);
387             } catch (RemoteException e) {
388             }
389         }
390     }
391 
392     /** @hide */
abort(Bundle options)393     public static void abort(Bundle options) {
394         if (options != null) {
395             (new ActivityOptions(options)).abort();
396         }
397     }
398 
399     /**
400      * Update the current values in this ActivityOptions from those supplied
401      * in <var>otherOptions</var>.  Any values
402      * defined in <var>otherOptions</var> replace those in the base options.
403      */
update(ActivityOptions otherOptions)404     public void update(ActivityOptions otherOptions) {
405         if (otherOptions.mPackageName != null) {
406             mPackageName = otherOptions.mPackageName;
407         }
408         switch (otherOptions.mAnimationType) {
409             case ANIM_CUSTOM:
410                 mAnimationType = otherOptions.mAnimationType;
411                 mCustomEnterResId = otherOptions.mCustomEnterResId;
412                 mCustomExitResId = otherOptions.mCustomExitResId;
413                 mThumbnail = null;
414                 if (otherOptions.mAnimationStartedListener != null) {
415                     try {
416                         otherOptions.mAnimationStartedListener.sendResult(null);
417                     } catch (RemoteException e) {
418                     }
419                 }
420                 mAnimationStartedListener = otherOptions.mAnimationStartedListener;
421                 break;
422             case ANIM_SCALE_UP:
423                 mAnimationType = otherOptions.mAnimationType;
424                 mStartX = otherOptions.mStartX;
425                 mStartY = otherOptions.mStartY;
426                 mStartWidth = otherOptions.mStartWidth;
427                 mStartHeight = otherOptions.mStartHeight;
428                 if (otherOptions.mAnimationStartedListener != null) {
429                     try {
430                         otherOptions.mAnimationStartedListener.sendResult(null);
431                     } catch (RemoteException e) {
432                     }
433                 }
434                 mAnimationStartedListener = null;
435                 break;
436             case ANIM_THUMBNAIL_SCALE_UP:
437             case ANIM_THUMBNAIL_SCALE_DOWN:
438                 mAnimationType = otherOptions.mAnimationType;
439                 mThumbnail = otherOptions.mThumbnail;
440                 mStartX = otherOptions.mStartX;
441                 mStartY = otherOptions.mStartY;
442                 if (otherOptions.mAnimationStartedListener != null) {
443                     try {
444                         otherOptions.mAnimationStartedListener.sendResult(null);
445                     } catch (RemoteException e) {
446                     }
447                 }
448                 mAnimationStartedListener = otherOptions.mAnimationStartedListener;
449                 break;
450         }
451     }
452 
453     /**
454      * Returns the created options as a Bundle, which can be passed to
455      * {@link android.content.Context#startActivity(android.content.Intent, android.os.Bundle)
456      * Context.startActivity(Intent, Bundle)} and related methods.
457      * Note that the returned Bundle is still owned by the ActivityOptions
458      * object; you must not modify it, but can supply it to the startActivity
459      * methods that take an options Bundle.
460      */
toBundle()461     public Bundle toBundle() {
462         Bundle b = new Bundle();
463         if (mPackageName != null) {
464             b.putString(KEY_PACKAGE_NAME, mPackageName);
465         }
466         switch (mAnimationType) {
467             case ANIM_CUSTOM:
468                 b.putInt(KEY_ANIM_TYPE, mAnimationType);
469                 b.putInt(KEY_ANIM_ENTER_RES_ID, mCustomEnterResId);
470                 b.putInt(KEY_ANIM_EXIT_RES_ID, mCustomExitResId);
471                 b.putIBinder(KEY_ANIM_START_LISTENER, mAnimationStartedListener
472                         != null ? mAnimationStartedListener.asBinder() : null);
473                 break;
474             case ANIM_SCALE_UP:
475                 b.putInt(KEY_ANIM_TYPE, mAnimationType);
476                 b.putInt(KEY_ANIM_START_X, mStartX);
477                 b.putInt(KEY_ANIM_START_Y, mStartY);
478                 b.putInt(KEY_ANIM_START_WIDTH, mStartWidth);
479                 b.putInt(KEY_ANIM_START_HEIGHT, mStartHeight);
480                 break;
481             case ANIM_THUMBNAIL_SCALE_UP:
482             case ANIM_THUMBNAIL_SCALE_DOWN:
483                 b.putInt(KEY_ANIM_TYPE, mAnimationType);
484                 b.putParcelable(KEY_ANIM_THUMBNAIL, mThumbnail);
485                 b.putInt(KEY_ANIM_START_X, mStartX);
486                 b.putInt(KEY_ANIM_START_Y, mStartY);
487                 b.putIBinder(KEY_ANIM_START_LISTENER, mAnimationStartedListener
488                         != null ? mAnimationStartedListener.asBinder() : null);
489                 break;
490         }
491         return b;
492     }
493 }
494