androidandroid-activitylaunchmodetaskstackbuilder

Activity in launchMode singleTask gets destroyed when started via TaskStackBuilder


I have an activity A, declared in Manifest with android:launchMode="singleTask" and another activity B that has no further attributes.

As far as I know, if there is already some task running activity A, instead of creating a new instance, the current task is brought to front, if I attempt to start activity A.

Now, I want to use the TaskStackBuilder to make a call which includes both activities.

Let's suppose I am on a Fragment within Activity A and call:

                TaskStackBuilder.create(context)
                    .addNextIntent(new Intent(context, A.class))
                    .addNextIntent(new Intent(context, B.class))
                    .startActivities();

I assume the current stack to become: A > B with A getting a call to onNewIntent and B with a new instance. Furthermore I expect Activity A to hold it's state.

But what happens is: I do not get a call to onNewIntent, but to onDestroy for Activity A. And if I go back from my newly created Activity B, onCreate is called for a new instance of Activity A. (They are not equal!).

Can anybody explain to me, why my Activity A is thrown away instead of doing nothing to it, but adding B to the stack? It is a shame, that I can't get my head around this problem by myself, but I can't see the obstacle here.

Edit/Ps: The context which I use for the StackBuilder can either be a views context or a Service context.


Solution

  • So, as nobody answered so far, I dived into the code from android in the meanwhile and discovered that the StackBuilder itself is the issue.

    In detail..this part of code, which is present in the methods startActivities() and also in getPendingIntent(), causes my Activity A to get destroyed:

        public PendingIntent getPendingIntent(int requestCode, int flags, Bundle options) {
            if (mIntents.isEmpty()) {
                throw new IllegalStateException(
                        "No intents added to TaskStackBuilder; cannot getPendingIntent");
            }
    
            Intent[] intents = mIntents.toArray(new Intent[mIntents.size()]);
            intents[0] = new Intent(intents[0]).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
                IntentCompat.FLAG_ACTIVITY_CLEAR_TASK |
                IntentCompat.FLAG_ACTIVITY_TASK_ON_HOME);
            // Appropriate flags will be added by the call below.
            return IMPL.getPendingIntent(mSourceContext, intents, requestCode, flags, options);
        }
    

    It is this part:

    Intent[] intents = mIntents.toArray(new Intent[mIntents.size()]);
        intents[0] = new Intent(intents[0]).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
                IntentCompat.FLAG_ACTIVITY_CLEAR_TASK |
                IntentCompat.FLAG_ACTIVITY_TASK_ON_HOME);
    

    My Activity A was in an existing Task. Although it has the launchMode = "singleTask" and should get reordered to front normally, the FLAG_ACTIVITY_CLEAR_TASK is set to my first activity (which is A) and causes the existing task that would be associated with the A to be cleared before the activity is started.

    That said, I won't use the StackBuilder in my special case now. I see several approaches to this: either use an empty Activity before my first target Activity or building the stack myself inside of my Activity A's onCreate / onNewIntent, by providing a Bundle with a List of parcelables (intents) to start.