Home | History | Annotate | Download | only in app
      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.content.Intent;
     21 import android.graphics.Bitmap;
     22 import android.os.Bundle;
     23 import android.os.Handler;
     24 import android.os.IRemoteCallback;
     25 import android.os.RemoteException;
     26 import android.os.ResultReceiver;
     27 import android.util.Pair;
     28 import android.view.View;
     29 import android.view.Window;
     30 
     31 import java.util.ArrayList;
     32 
     33 /**
     34  * Helper class for building an options Bundle that can be used with
     35  * {@link android.content.Context#startActivity(android.content.Intent, android.os.Bundle)
     36  * Context.startActivity(Intent, Bundle)} and related methods.
     37  */
     38 public class ActivityOptions {
     39     private static final String TAG = "ActivityOptions";
     40 
     41     /**
     42      * The package name that created the options.
     43      * @hide
     44      */
     45     public static final String KEY_PACKAGE_NAME = "android:packageName";
     46 
     47     /**
     48      * Type of animation that arguments specify.
     49      * @hide
     50      */
     51     public static final String KEY_ANIM_TYPE = "android:animType";
     52 
     53     /**
     54      * Custom enter animation resource ID.
     55      * @hide
     56      */
     57     public static final String KEY_ANIM_ENTER_RES_ID = "android:animEnterRes";
     58 
     59     /**
     60      * Custom exit animation resource ID.
     61      * @hide
     62      */
     63     public static final String KEY_ANIM_EXIT_RES_ID = "android:animExitRes";
     64 
     65     /**
     66      * Custom in-place animation resource ID.
     67      * @hide
     68      */
     69     public static final String KEY_ANIM_IN_PLACE_RES_ID = "android:animInPlaceRes";
     70 
     71     /**
     72      * Bitmap for thumbnail animation.
     73      * @hide
     74      */
     75     public static final String KEY_ANIM_THUMBNAIL = "android:animThumbnail";
     76 
     77     /**
     78      * Start X position of thumbnail animation.
     79      * @hide
     80      */
     81     public static final String KEY_ANIM_START_X = "android:animStartX";
     82 
     83     /**
     84      * Start Y position of thumbnail animation.
     85      * @hide
     86      */
     87     public static final String KEY_ANIM_START_Y = "android:animStartY";
     88 
     89     /**
     90      * Initial width of the animation.
     91      * @hide
     92      */
     93     public static final String KEY_ANIM_WIDTH = "android:animWidth";
     94 
     95     /**
     96      * Initial height of the animation.
     97      * @hide
     98      */
     99     public static final String KEY_ANIM_HEIGHT = "android:animHeight";
    100 
    101     /**
    102      * Callback for when animation is started.
    103      * @hide
    104      */
    105     public static final String KEY_ANIM_START_LISTENER = "android:animStartListener";
    106 
    107     /**
    108      * For Activity transitions, the calling Activity's TransitionListener used to
    109      * notify the called Activity when the shared element and the exit transitions
    110      * complete.
    111      */
    112     private static final String KEY_TRANSITION_COMPLETE_LISTENER
    113             = "android:transitionCompleteListener";
    114 
    115     private static final String KEY_TRANSITION_IS_RETURNING = "android:transitionIsReturning";
    116     private static final String KEY_TRANSITION_SHARED_ELEMENTS = "android:sharedElementNames";
    117     private static final String KEY_RESULT_DATA = "android:resultData";
    118     private static final String KEY_RESULT_CODE = "android:resultCode";
    119     private static final String KEY_EXIT_COORDINATOR_INDEX = "android:exitCoordinatorIndex";
    120 
    121     /** @hide */
    122     public static final int ANIM_NONE = 0;
    123     /** @hide */
    124     public static final int ANIM_CUSTOM = 1;
    125     /** @hide */
    126     public static final int ANIM_SCALE_UP = 2;
    127     /** @hide */
    128     public static final int ANIM_THUMBNAIL_SCALE_UP = 3;
    129     /** @hide */
    130     public static final int ANIM_THUMBNAIL_SCALE_DOWN = 4;
    131     /** @hide */
    132     public static final int ANIM_SCENE_TRANSITION = 5;
    133     /** @hide */
    134     public static final int ANIM_DEFAULT = 6;
    135     /** @hide */
    136     public static final int ANIM_LAUNCH_TASK_BEHIND = 7;
    137     /** @hide */
    138     public static final int ANIM_THUMBNAIL_ASPECT_SCALE_UP = 8;
    139     /** @hide */
    140     public static final int ANIM_THUMBNAIL_ASPECT_SCALE_DOWN = 9;
    141     /** @hide */
    142     public static final int ANIM_CUSTOM_IN_PLACE = 10;
    143 
    144     private String mPackageName;
    145     private int mAnimationType = ANIM_NONE;
    146     private int mCustomEnterResId;
    147     private int mCustomExitResId;
    148     private int mCustomInPlaceResId;
    149     private Bitmap mThumbnail;
    150     private int mStartX;
    151     private int mStartY;
    152     private int mWidth;
    153     private int mHeight;
    154     private IRemoteCallback mAnimationStartedListener;
    155     private ResultReceiver mTransitionReceiver;
    156     private boolean mIsReturning;
    157     private ArrayList<String> mSharedElementNames;
    158     private Intent mResultData;
    159     private int mResultCode;
    160     private int mExitCoordinatorIndex;
    161 
    162     /**
    163      * Create an ActivityOptions specifying a custom animation to run when
    164      * the activity is displayed.
    165      *
    166      * @param context Who is defining this.  This is the application that the
    167      * animation resources will be loaded from.
    168      * @param enterResId A resource ID of the animation resource to use for
    169      * the incoming activity.  Use 0 for no animation.
    170      * @param exitResId A resource ID of the animation resource to use for
    171      * the outgoing activity.  Use 0 for no animation.
    172      * @return Returns a new ActivityOptions object that you can use to
    173      * supply these options as the options Bundle when starting an activity.
    174      */
    175     public static ActivityOptions makeCustomAnimation(Context context,
    176             int enterResId, int exitResId) {
    177         return makeCustomAnimation(context, enterResId, exitResId, null, null);
    178     }
    179 
    180     /**
    181      * Create an ActivityOptions specifying a custom animation to run when
    182      * the activity is displayed.
    183      *
    184      * @param context Who is defining this.  This is the application that the
    185      * animation resources will be loaded from.
    186      * @param enterResId A resource ID of the animation resource to use for
    187      * the incoming activity.  Use 0 for no animation.
    188      * @param exitResId A resource ID of the animation resource to use for
    189      * the outgoing activity.  Use 0 for no animation.
    190      * @param handler If <var>listener</var> is non-null this must be a valid
    191      * Handler on which to dispatch the callback; otherwise it should be null.
    192      * @param listener Optional OnAnimationStartedListener to find out when the
    193      * requested animation has started running.  If for some reason the animation
    194      * is not executed, the callback will happen immediately.
    195      * @return Returns a new ActivityOptions object that you can use to
    196      * supply these options as the options Bundle when starting an activity.
    197      * @hide
    198      */
    199     public static ActivityOptions makeCustomAnimation(Context context,
    200             int enterResId, int exitResId, Handler handler, OnAnimationStartedListener listener) {
    201         ActivityOptions opts = new ActivityOptions();
    202         opts.mPackageName = context.getPackageName();
    203         opts.mAnimationType = ANIM_CUSTOM;
    204         opts.mCustomEnterResId = enterResId;
    205         opts.mCustomExitResId = exitResId;
    206         opts.setOnAnimationStartedListener(handler, listener);
    207         return opts;
    208     }
    209 
    210     /**
    211      * Creates an ActivityOptions specifying a custom animation to run in place on an existing
    212      * activity.
    213      *
    214      * @param context Who is defining this.  This is the application that the
    215      * animation resources will be loaded from.
    216      * @param animId A resource ID of the animation resource to use for
    217      * the incoming activity.
    218      * @return Returns a new ActivityOptions object that you can use to
    219      * supply these options as the options Bundle when running an in-place animation.
    220      * @hide
    221      */
    222     public static ActivityOptions makeCustomInPlaceAnimation(Context context, int animId) {
    223         if (animId == 0) {
    224             throw new RuntimeException("You must specify a valid animation.");
    225         }
    226 
    227         ActivityOptions opts = new ActivityOptions();
    228         opts.mPackageName = context.getPackageName();
    229         opts.mAnimationType = ANIM_CUSTOM_IN_PLACE;
    230         opts.mCustomInPlaceResId = animId;
    231         return opts;
    232     }
    233 
    234     private void setOnAnimationStartedListener(Handler handler,
    235             OnAnimationStartedListener listener) {
    236         if (listener != null) {
    237             final Handler h = handler;
    238             final OnAnimationStartedListener finalListener = listener;
    239             mAnimationStartedListener = new IRemoteCallback.Stub() {
    240                 @Override public void sendResult(Bundle data) throws RemoteException {
    241                     h.post(new Runnable() {
    242                         @Override public void run() {
    243                             finalListener.onAnimationStarted();
    244                         }
    245                     });
    246                 }
    247             };
    248         }
    249     }
    250 
    251     /**
    252      * Callback for use with {@link ActivityOptions#makeThumbnailScaleUpAnimation}
    253      * to find out when the given animation has started running.
    254      * @hide
    255      */
    256     public interface OnAnimationStartedListener {
    257         void onAnimationStarted();
    258     }
    259 
    260     /**
    261      * Create an ActivityOptions specifying an animation where the new
    262      * activity is scaled from a small originating area of the screen to
    263      * its final full representation.
    264      *
    265      * <p>If the Intent this is being used with has not set its
    266      * {@link android.content.Intent#setSourceBounds Intent.setSourceBounds},
    267      * those bounds will be filled in for you based on the initial
    268      * bounds passed in here.
    269      *
    270      * @param source The View that the new activity is animating from.  This
    271      * defines the coordinate space for <var>startX</var> and <var>startY</var>.
    272      * @param startX The x starting location of the new activity, relative to <var>source</var>.
    273      * @param startY The y starting location of the activity, relative to <var>source</var>.
    274      * @param width The initial width of the new activity.
    275      * @param height The initial height of the new activity.
    276      * @return Returns a new ActivityOptions object that you can use to
    277      * supply these options as the options Bundle when starting an activity.
    278      */
    279     public static ActivityOptions makeScaleUpAnimation(View source,
    280             int startX, int startY, int width, int height) {
    281         ActivityOptions opts = new ActivityOptions();
    282         opts.mPackageName = source.getContext().getPackageName();
    283         opts.mAnimationType = ANIM_SCALE_UP;
    284         int[] pts = new int[2];
    285         source.getLocationOnScreen(pts);
    286         opts.mStartX = pts[0] + startX;
    287         opts.mStartY = pts[1] + startY;
    288         opts.mWidth = width;
    289         opts.mHeight = height;
    290         return opts;
    291     }
    292 
    293     /**
    294      * Create an ActivityOptions specifying an animation where a thumbnail
    295      * is scaled from a given position to the new activity window that is
    296      * being started.
    297      *
    298      * <p>If the Intent this is being used with has not set its
    299      * {@link android.content.Intent#setSourceBounds Intent.setSourceBounds},
    300      * those bounds will be filled in for you based on the initial
    301      * thumbnail location and size provided here.
    302      *
    303      * @param source The View that this thumbnail is animating from.  This
    304      * defines the coordinate space for <var>startX</var> and <var>startY</var>.
    305      * @param thumbnail The bitmap that will be shown as the initial thumbnail
    306      * of the animation.
    307      * @param startX The x starting location of the bitmap, relative to <var>source</var>.
    308      * @param startY The y starting location of the bitmap, relative to <var>source</var>.
    309      * @return Returns a new ActivityOptions object that you can use to
    310      * supply these options as the options Bundle when starting an activity.
    311      */
    312     public static ActivityOptions makeThumbnailScaleUpAnimation(View source,
    313             Bitmap thumbnail, int startX, int startY) {
    314         return makeThumbnailScaleUpAnimation(source, thumbnail, startX, startY, null);
    315     }
    316 
    317     /**
    318      * Create an ActivityOptions specifying an animation where a thumbnail
    319      * is scaled from a given position to the new activity window that is
    320      * being started.
    321      *
    322      * @param source The View that this thumbnail is animating from.  This
    323      * defines the coordinate space for <var>startX</var> and <var>startY</var>.
    324      * @param thumbnail The bitmap that will be shown as the initial thumbnail
    325      * of the animation.
    326      * @param startX The x starting location of the bitmap, relative to <var>source</var>.
    327      * @param startY The y starting location of the bitmap, relative to <var>source</var>.
    328      * @param listener Optional OnAnimationStartedListener to find out when the
    329      * requested animation has started running.  If for some reason the animation
    330      * is not executed, the callback will happen immediately.
    331      * @return Returns a new ActivityOptions object that you can use to
    332      * supply these options as the options Bundle when starting an activity.
    333      * @hide
    334      */
    335     public static ActivityOptions makeThumbnailScaleUpAnimation(View source,
    336             Bitmap thumbnail, int startX, int startY, OnAnimationStartedListener listener) {
    337         return makeThumbnailAnimation(source, thumbnail, startX, startY, listener, true);
    338     }
    339 
    340     /**
    341      * Create an ActivityOptions specifying an animation where an activity window
    342      * is scaled from a given position to a thumbnail at a specified location.
    343      *
    344      * @param source The View that this thumbnail is animating to.  This
    345      * defines the coordinate space for <var>startX</var> and <var>startY</var>.
    346      * @param thumbnail The bitmap that will be shown as the final thumbnail
    347      * of the animation.
    348      * @param startX The x end location of the bitmap, relative to <var>source</var>.
    349      * @param startY The y end location of the bitmap, relative to <var>source</var>.
    350      * @param listener Optional OnAnimationStartedListener to find out when the
    351      * requested animation has started running.  If for some reason the animation
    352      * is not executed, the callback will happen immediately.
    353      * @return Returns a new ActivityOptions object that you can use to
    354      * supply these options as the options Bundle when starting an activity.
    355      * @hide
    356      */
    357     public static ActivityOptions makeThumbnailScaleDownAnimation(View source,
    358             Bitmap thumbnail, int startX, int startY, OnAnimationStartedListener listener) {
    359         return makeThumbnailAnimation(source, thumbnail, startX, startY, listener, false);
    360     }
    361 
    362     private static ActivityOptions makeThumbnailAnimation(View source,
    363             Bitmap thumbnail, int startX, int startY, OnAnimationStartedListener listener,
    364             boolean scaleUp) {
    365         ActivityOptions opts = new ActivityOptions();
    366         opts.mPackageName = source.getContext().getPackageName();
    367         opts.mAnimationType = scaleUp ? ANIM_THUMBNAIL_SCALE_UP : ANIM_THUMBNAIL_SCALE_DOWN;
    368         opts.mThumbnail = thumbnail;
    369         int[] pts = new int[2];
    370         source.getLocationOnScreen(pts);
    371         opts.mStartX = pts[0] + startX;
    372         opts.mStartY = pts[1] + startY;
    373         opts.setOnAnimationStartedListener(source.getHandler(), listener);
    374         return opts;
    375     }
    376 
    377     /**
    378      * Create an ActivityOptions specifying an animation where the new activity
    379      * window and a thumbnail is aspect-scaled to a new location.
    380      *
    381      * @param source The View that this thumbnail is animating from.  This
    382      * defines the coordinate space for <var>startX</var> and <var>startY</var>.
    383      * @param thumbnail The bitmap that will be shown as the initial thumbnail
    384      * of the animation.
    385      * @param startX The x starting location of the bitmap, relative to <var>source</var>.
    386      * @param startY The y starting location of the bitmap, relative to <var>source</var>.
    387      * @param handler If <var>listener</var> is non-null this must be a valid
    388      * Handler on which to dispatch the callback; otherwise it should be null.
    389      * @param listener Optional OnAnimationStartedListener to find out when the
    390      * requested animation has started running.  If for some reason the animation
    391      * is not executed, the callback will happen immediately.
    392      * @return Returns a new ActivityOptions object that you can use to
    393      * supply these options as the options Bundle when starting an activity.
    394      * @hide
    395      */
    396     public static ActivityOptions makeThumbnailAspectScaleUpAnimation(View source,
    397             Bitmap thumbnail, int startX, int startY, int targetWidth, int targetHeight,
    398             Handler handler, OnAnimationStartedListener listener) {
    399         return makeAspectScaledThumbnailAnimation(source, thumbnail, startX, startY,
    400                 targetWidth, targetHeight, handler, listener, true);
    401     }
    402 
    403     /**
    404      * Create an ActivityOptions specifying an animation where the new activity
    405      * window and a thumbnail is aspect-scaled to a new location.
    406      *
    407      * @param source The View that this thumbnail is animating to.  This
    408      * defines the coordinate space for <var>startX</var> and <var>startY</var>.
    409      * @param thumbnail The bitmap that will be shown as the final thumbnail
    410      * of the animation.
    411      * @param startX The x end location of the bitmap, relative to <var>source</var>.
    412      * @param startY The y end location of the bitmap, relative to <var>source</var>.
    413      * @param handler If <var>listener</var> is non-null this must be a valid
    414      * Handler on which to dispatch the callback; otherwise it should be null.
    415      * @param listener Optional OnAnimationStartedListener to find out when the
    416      * requested animation has started running.  If for some reason the animation
    417      * is not executed, the callback will happen immediately.
    418      * @return Returns a new ActivityOptions object that you can use to
    419      * supply these options as the options Bundle when starting an activity.
    420      * @hide
    421      */
    422     public static ActivityOptions makeThumbnailAspectScaleDownAnimation(View source,
    423             Bitmap thumbnail, int startX, int startY, int targetWidth, int targetHeight,
    424             Handler handler, OnAnimationStartedListener listener) {
    425         return makeAspectScaledThumbnailAnimation(source, thumbnail, startX, startY,
    426                 targetWidth, targetHeight, handler, listener, false);
    427     }
    428 
    429     private static ActivityOptions makeAspectScaledThumbnailAnimation(View source, Bitmap thumbnail,
    430             int startX, int startY, int targetWidth, int targetHeight,
    431             Handler handler, OnAnimationStartedListener listener, boolean scaleUp) {
    432         ActivityOptions opts = new ActivityOptions();
    433         opts.mPackageName = source.getContext().getPackageName();
    434         opts.mAnimationType = scaleUp ? ANIM_THUMBNAIL_ASPECT_SCALE_UP :
    435                 ANIM_THUMBNAIL_ASPECT_SCALE_DOWN;
    436         opts.mThumbnail = thumbnail;
    437         int[] pts = new int[2];
    438         source.getLocationOnScreen(pts);
    439         opts.mStartX = pts[0] + startX;
    440         opts.mStartY = pts[1] + startY;
    441         opts.mWidth = targetWidth;
    442         opts.mHeight = targetHeight;
    443         opts.setOnAnimationStartedListener(handler, listener);
    444         return opts;
    445     }
    446 
    447     /**
    448      * Create an ActivityOptions to transition between Activities using cross-Activity scene
    449      * animations. This method carries the position of one shared element to the started Activity.
    450      * The position of <code>sharedElement</code> will be used as the epicenter for the
    451      * exit Transition. The position of the shared element in the launched Activity will be the
    452      * epicenter of its entering Transition.
    453      *
    454      * <p>This requires {@link android.view.Window#FEATURE_ACTIVITY_TRANSITIONS} to be
    455      * enabled on the calling Activity to cause an exit transition. The same must be in
    456      * the called Activity to get an entering transition.</p>
    457      * @param activity The Activity whose window contains the shared elements.
    458      * @param sharedElement The View to transition to the started Activity.
    459      * @param sharedElementName The shared element name as used in the target Activity. This
    460      *                          must not be null.
    461      * @return Returns a new ActivityOptions object that you can use to
    462      *         supply these options as the options Bundle when starting an activity.
    463      * @see android.transition.Transition#setEpicenterCallback(
    464      *          android.transition.Transition.EpicenterCallback)
    465      */
    466     public static ActivityOptions makeSceneTransitionAnimation(Activity activity,
    467             View sharedElement, String sharedElementName) {
    468         return makeSceneTransitionAnimation(activity, Pair.create(sharedElement, sharedElementName));
    469     }
    470 
    471     /**
    472      * Create an ActivityOptions to transition between Activities using cross-Activity scene
    473      * animations. This method carries the position of multiple shared elements to the started
    474      * Activity. The position of the first element in sharedElements
    475      * will be used as the epicenter for the exit Transition. The position of the associated
    476      * shared element in the launched Activity will be the epicenter of its entering Transition.
    477      *
    478      * <p>This requires {@link android.view.Window#FEATURE_ACTIVITY_TRANSITIONS} to be
    479      * enabled on the calling Activity to cause an exit transition. The same must be in
    480      * the called Activity to get an entering transition.</p>
    481      * @param activity The Activity whose window contains the shared elements.
    482      * @param sharedElements The names of the shared elements to transfer to the called
    483      *                       Activity and their associated Views. The Views must each have
    484      *                       a unique shared element name.
    485      * @return Returns a new ActivityOptions object that you can use to
    486      *         supply these options as the options Bundle when starting an activity.
    487      * @see android.transition.Transition#setEpicenterCallback(
    488      *          android.transition.Transition.EpicenterCallback)
    489      */
    490     public static ActivityOptions makeSceneTransitionAnimation(Activity activity,
    491             Pair<View, String>... sharedElements) {
    492         ActivityOptions opts = new ActivityOptions();
    493         if (!activity.getWindow().hasFeature(Window.FEATURE_ACTIVITY_TRANSITIONS)) {
    494             opts.mAnimationType = ANIM_DEFAULT;
    495             return opts;
    496         }
    497         opts.mAnimationType = ANIM_SCENE_TRANSITION;
    498 
    499         ArrayList<String> names = new ArrayList<String>();
    500         ArrayList<View> views = new ArrayList<View>();
    501 
    502         if (sharedElements != null) {
    503             for (int i = 0; i < sharedElements.length; i++) {
    504                 Pair<View, String> sharedElement = sharedElements[i];
    505                 String sharedElementName = sharedElement.second;
    506                 if (sharedElementName == null) {
    507                     throw new IllegalArgumentException("Shared element name must not be null");
    508                 }
    509                 names.add(sharedElementName);
    510                 View view = sharedElement.first;
    511                 if (view == null) {
    512                     throw new IllegalArgumentException("Shared element must not be null");
    513                 }
    514                 views.add(sharedElement.first);
    515             }
    516         }
    517 
    518         ExitTransitionCoordinator exit = new ExitTransitionCoordinator(activity, names, names,
    519                 views, false);
    520         opts.mTransitionReceiver = exit;
    521         opts.mSharedElementNames = names;
    522         opts.mIsReturning = false;
    523         opts.mExitCoordinatorIndex =
    524                 activity.mActivityTransitionState.addExitTransitionCoordinator(exit);
    525         return opts;
    526     }
    527 
    528     /** @hide */
    529     public static ActivityOptions makeSceneTransitionAnimation(Activity activity,
    530             ExitTransitionCoordinator exitCoordinator, ArrayList<String> sharedElementNames,
    531             int resultCode, Intent resultData) {
    532         ActivityOptions opts = new ActivityOptions();
    533         opts.mAnimationType = ANIM_SCENE_TRANSITION;
    534         opts.mSharedElementNames = sharedElementNames;
    535         opts.mTransitionReceiver = exitCoordinator;
    536         opts.mIsReturning = true;
    537         opts.mResultCode = resultCode;
    538         opts.mResultData = resultData;
    539         opts.mExitCoordinatorIndex =
    540                 activity.mActivityTransitionState.addExitTransitionCoordinator(exitCoordinator);
    541         return opts;
    542     }
    543 
    544     /**
    545      * If set along with Intent.FLAG_ACTIVITY_NEW_DOCUMENT then the task being launched will not be
    546      * presented to the user but will instead be only available through the recents task list.
    547      * In addition, the new task wil be affiliated with the launching activity's task.
    548      * Affiliated tasks are grouped together in the recents task list.
    549      *
    550      * <p>This behavior is not supported for activities with {@link
    551      * android.R.styleable#AndroidManifestActivity_launchMode launchMode} values of
    552      * <code>singleInstance</code> or <code>singleTask</code>.
    553      */
    554     public static ActivityOptions makeTaskLaunchBehind() {
    555         final ActivityOptions opts = new ActivityOptions();
    556         opts.mAnimationType = ANIM_LAUNCH_TASK_BEHIND;
    557         return opts;
    558     }
    559 
    560     /** @hide */
    561     public boolean getLaunchTaskBehind() {
    562         return mAnimationType == ANIM_LAUNCH_TASK_BEHIND;
    563     }
    564 
    565     private ActivityOptions() {
    566     }
    567 
    568     /** @hide */
    569     public ActivityOptions(Bundle opts) {
    570         mPackageName = opts.getString(KEY_PACKAGE_NAME);
    571         mAnimationType = opts.getInt(KEY_ANIM_TYPE);
    572         switch (mAnimationType) {
    573             case ANIM_CUSTOM:
    574                 mCustomEnterResId = opts.getInt(KEY_ANIM_ENTER_RES_ID, 0);
    575                 mCustomExitResId = opts.getInt(KEY_ANIM_EXIT_RES_ID, 0);
    576                 mAnimationStartedListener = IRemoteCallback.Stub.asInterface(
    577                         opts.getBinder(KEY_ANIM_START_LISTENER));
    578                 break;
    579 
    580             case ANIM_CUSTOM_IN_PLACE:
    581                 mCustomInPlaceResId = opts.getInt(KEY_ANIM_IN_PLACE_RES_ID, 0);
    582                 break;
    583 
    584             case ANIM_SCALE_UP:
    585                 mStartX = opts.getInt(KEY_ANIM_START_X, 0);
    586                 mStartY = opts.getInt(KEY_ANIM_START_Y, 0);
    587                 mWidth = opts.getInt(KEY_ANIM_WIDTH, 0);
    588                 mHeight = opts.getInt(KEY_ANIM_HEIGHT, 0);
    589                 break;
    590 
    591             case ANIM_THUMBNAIL_SCALE_UP:
    592             case ANIM_THUMBNAIL_SCALE_DOWN:
    593             case ANIM_THUMBNAIL_ASPECT_SCALE_UP:
    594             case ANIM_THUMBNAIL_ASPECT_SCALE_DOWN:
    595                 mThumbnail = (Bitmap) opts.getParcelable(KEY_ANIM_THUMBNAIL);
    596                 mStartX = opts.getInt(KEY_ANIM_START_X, 0);
    597                 mStartY = opts.getInt(KEY_ANIM_START_Y, 0);
    598                 mWidth = opts.getInt(KEY_ANIM_WIDTH, 0);
    599                 mHeight = opts.getInt(KEY_ANIM_HEIGHT, 0);
    600                 mAnimationStartedListener = IRemoteCallback.Stub.asInterface(
    601                         opts.getBinder(KEY_ANIM_START_LISTENER));
    602                 break;
    603 
    604             case ANIM_SCENE_TRANSITION:
    605                 mTransitionReceiver = opts.getParcelable(KEY_TRANSITION_COMPLETE_LISTENER);
    606                 mIsReturning = opts.getBoolean(KEY_TRANSITION_IS_RETURNING, false);
    607                 mSharedElementNames = opts.getStringArrayList(KEY_TRANSITION_SHARED_ELEMENTS);
    608                 mResultData = opts.getParcelable(KEY_RESULT_DATA);
    609                 mResultCode = opts.getInt(KEY_RESULT_CODE);
    610                 mExitCoordinatorIndex = opts.getInt(KEY_EXIT_COORDINATOR_INDEX);
    611                 break;
    612         }
    613     }
    614 
    615     /** @hide */
    616     public String getPackageName() {
    617         return mPackageName;
    618     }
    619 
    620     /** @hide */
    621     public int getAnimationType() {
    622         return mAnimationType;
    623     }
    624 
    625     /** @hide */
    626     public int getCustomEnterResId() {
    627         return mCustomEnterResId;
    628     }
    629 
    630     /** @hide */
    631     public int getCustomExitResId() {
    632         return mCustomExitResId;
    633     }
    634 
    635     /** @hide */
    636     public int getCustomInPlaceResId() {
    637         return mCustomInPlaceResId;
    638     }
    639 
    640     /** @hide */
    641     public Bitmap getThumbnail() {
    642         return mThumbnail;
    643     }
    644 
    645     /** @hide */
    646     public int getStartX() {
    647         return mStartX;
    648     }
    649 
    650     /** @hide */
    651     public int getStartY() {
    652         return mStartY;
    653     }
    654 
    655     /** @hide */
    656     public int getWidth() {
    657         return mWidth;
    658     }
    659 
    660     /** @hide */
    661     public int getHeight() {
    662         return mHeight;
    663     }
    664 
    665     /** @hide */
    666     public IRemoteCallback getOnAnimationStartListener() {
    667         return mAnimationStartedListener;
    668     }
    669 
    670     /** @hide */
    671     public int getExitCoordinatorKey() { return mExitCoordinatorIndex; }
    672 
    673     /** @hide */
    674     public void abort() {
    675         if (mAnimationStartedListener != null) {
    676             try {
    677                 mAnimationStartedListener.sendResult(null);
    678             } catch (RemoteException e) {
    679             }
    680         }
    681     }
    682 
    683     /** @hide */
    684     public boolean isReturning() {
    685         return mIsReturning;
    686     }
    687 
    688     /** @hide */
    689     public ArrayList<String> getSharedElementNames() {
    690         return mSharedElementNames;
    691     }
    692 
    693     /** @hide */
    694     public ResultReceiver getResultReceiver() { return mTransitionReceiver; }
    695 
    696     /** @hide */
    697     public int getResultCode() { return mResultCode; }
    698 
    699     /** @hide */
    700     public Intent getResultData() { return mResultData; }
    701 
    702     /** @hide */
    703     public static void abort(Bundle options) {
    704         if (options != null) {
    705             (new ActivityOptions(options)).abort();
    706         }
    707     }
    708 
    709     /**
    710      * Update the current values in this ActivityOptions from those supplied
    711      * in <var>otherOptions</var>.  Any values
    712      * defined in <var>otherOptions</var> replace those in the base options.
    713      */
    714     public void update(ActivityOptions otherOptions) {
    715         if (otherOptions.mPackageName != null) {
    716             mPackageName = otherOptions.mPackageName;
    717         }
    718         mTransitionReceiver = null;
    719         mSharedElementNames = null;
    720         mIsReturning = false;
    721         mResultData = null;
    722         mResultCode = 0;
    723         mExitCoordinatorIndex = 0;
    724         mAnimationType = otherOptions.mAnimationType;
    725         switch (otherOptions.mAnimationType) {
    726             case ANIM_CUSTOM:
    727                 mCustomEnterResId = otherOptions.mCustomEnterResId;
    728                 mCustomExitResId = otherOptions.mCustomExitResId;
    729                 mThumbnail = null;
    730                 if (mAnimationStartedListener != null) {
    731                     try {
    732                         mAnimationStartedListener.sendResult(null);
    733                     } catch (RemoteException e) {
    734                     }
    735                 }
    736                 mAnimationStartedListener = otherOptions.mAnimationStartedListener;
    737                 break;
    738             case ANIM_CUSTOM_IN_PLACE:
    739                 mCustomInPlaceResId = otherOptions.mCustomInPlaceResId;
    740                 break;
    741             case ANIM_SCALE_UP:
    742                 mStartX = otherOptions.mStartX;
    743                 mStartY = otherOptions.mStartY;
    744                 mWidth = otherOptions.mWidth;
    745                 mHeight = otherOptions.mHeight;
    746                 if (mAnimationStartedListener != null) {
    747                     try {
    748                         mAnimationStartedListener.sendResult(null);
    749                     } catch (RemoteException e) {
    750                     }
    751                 }
    752                 mAnimationStartedListener = null;
    753                 break;
    754             case ANIM_THUMBNAIL_SCALE_UP:
    755             case ANIM_THUMBNAIL_SCALE_DOWN:
    756             case ANIM_THUMBNAIL_ASPECT_SCALE_UP:
    757             case ANIM_THUMBNAIL_ASPECT_SCALE_DOWN:
    758                 mThumbnail = otherOptions.mThumbnail;
    759                 mStartX = otherOptions.mStartX;
    760                 mStartY = otherOptions.mStartY;
    761                 mWidth = otherOptions.mWidth;
    762                 mHeight = otherOptions.mHeight;
    763                 if (mAnimationStartedListener != null) {
    764                     try {
    765                         mAnimationStartedListener.sendResult(null);
    766                     } catch (RemoteException e) {
    767                     }
    768                 }
    769                 mAnimationStartedListener = otherOptions.mAnimationStartedListener;
    770                 break;
    771             case ANIM_SCENE_TRANSITION:
    772                 mTransitionReceiver = otherOptions.mTransitionReceiver;
    773                 mSharedElementNames = otherOptions.mSharedElementNames;
    774                 mIsReturning = otherOptions.mIsReturning;
    775                 mThumbnail = null;
    776                 mAnimationStartedListener = null;
    777                 mResultData = otherOptions.mResultData;
    778                 mResultCode = otherOptions.mResultCode;
    779                 mExitCoordinatorIndex = otherOptions.mExitCoordinatorIndex;
    780                 break;
    781         }
    782     }
    783 
    784     /**
    785      * Returns the created options as a Bundle, which can be passed to
    786      * {@link android.content.Context#startActivity(android.content.Intent, android.os.Bundle)
    787      * Context.startActivity(Intent, Bundle)} and related methods.
    788      * Note that the returned Bundle is still owned by the ActivityOptions
    789      * object; you must not modify it, but can supply it to the startActivity
    790      * methods that take an options Bundle.
    791      */
    792     public Bundle toBundle() {
    793         if (mAnimationType == ANIM_DEFAULT) {
    794             return null;
    795         }
    796         Bundle b = new Bundle();
    797         if (mPackageName != null) {
    798             b.putString(KEY_PACKAGE_NAME, mPackageName);
    799         }
    800         b.putInt(KEY_ANIM_TYPE, mAnimationType);
    801         switch (mAnimationType) {
    802             case ANIM_CUSTOM:
    803                 b.putInt(KEY_ANIM_ENTER_RES_ID, mCustomEnterResId);
    804                 b.putInt(KEY_ANIM_EXIT_RES_ID, mCustomExitResId);
    805                 b.putBinder(KEY_ANIM_START_LISTENER, mAnimationStartedListener
    806                         != null ? mAnimationStartedListener.asBinder() : null);
    807                 break;
    808             case ANIM_CUSTOM_IN_PLACE:
    809                 b.putInt(KEY_ANIM_IN_PLACE_RES_ID, mCustomInPlaceResId);
    810                 break;
    811             case ANIM_SCALE_UP:
    812                 b.putInt(KEY_ANIM_START_X, mStartX);
    813                 b.putInt(KEY_ANIM_START_Y, mStartY);
    814                 b.putInt(KEY_ANIM_WIDTH, mWidth);
    815                 b.putInt(KEY_ANIM_HEIGHT, mHeight);
    816                 break;
    817             case ANIM_THUMBNAIL_SCALE_UP:
    818             case ANIM_THUMBNAIL_SCALE_DOWN:
    819             case ANIM_THUMBNAIL_ASPECT_SCALE_UP:
    820             case ANIM_THUMBNAIL_ASPECT_SCALE_DOWN:
    821                 b.putParcelable(KEY_ANIM_THUMBNAIL, mThumbnail);
    822                 b.putInt(KEY_ANIM_START_X, mStartX);
    823                 b.putInt(KEY_ANIM_START_Y, mStartY);
    824                 b.putInt(KEY_ANIM_WIDTH, mWidth);
    825                 b.putInt(KEY_ANIM_HEIGHT, mHeight);
    826                 b.putBinder(KEY_ANIM_START_LISTENER, mAnimationStartedListener
    827                         != null ? mAnimationStartedListener.asBinder() : null);
    828                 break;
    829             case ANIM_SCENE_TRANSITION:
    830                 if (mTransitionReceiver != null) {
    831                     b.putParcelable(KEY_TRANSITION_COMPLETE_LISTENER, mTransitionReceiver);
    832                 }
    833                 b.putBoolean(KEY_TRANSITION_IS_RETURNING, mIsReturning);
    834                 b.putStringArrayList(KEY_TRANSITION_SHARED_ELEMENTS, mSharedElementNames);
    835                 b.putParcelable(KEY_RESULT_DATA, mResultData);
    836                 b.putInt(KEY_RESULT_CODE, mResultCode);
    837                 b.putInt(KEY_EXIT_COORDINATOR_INDEX, mExitCoordinatorIndex);
    838                 break;
    839         }
    840 
    841         return b;
    842     }
    843 
    844     /**
    845      * Return the filtered options only meant to be seen by the target activity itself
    846      * @hide
    847      */
    848     public ActivityOptions forTargetActivity() {
    849         if (mAnimationType == ANIM_SCENE_TRANSITION) {
    850             final ActivityOptions result = new ActivityOptions();
    851             result.update(this);
    852             return result;
    853         }
    854 
    855         return null;
    856     }
    857 
    858 }
    859