TaskStackBuilder and extras for the back stack
Asked Answered
S

3

40

I'm trying to use TaskStackBuilder with notifications to create a back stack for the back button to go through. Normal flow of my app:

  1. Activity A is launched from the launcher.
  2. User selects an item from A, which launches B with extras for what to load.
  3. User selects an item from B, this launches C with extras for what to load.

Sometimes, after a background update when the user isn't using my app, I generate a notification. If they click this notification, it launches Activity C, skipping A and B. I'm trying to follow the design guidelines and create a back stack, so when they press back it will go to Activity B instead of the home screen. My problem is that Activity B requires an extra in its launch intent to tell it what to grab from the database.

My current TaskStackBuilder code:

TaskStackBuilder sBuilder = TaskStackBuilder.create( this );
sBuilder.addParentStack( ActivityC.class );
sBuilder.addNextIntent( launchIntent );

pIntent = sBuilder.getPendingIntent( 0, PendingIntent.FLAG_ONE_SHOT );

Clicking on the notification launches Activity C just fine, but when I press back it explodes with an IllegalArgumentException from my ContentProvider because Activity B doesn't know what ID to request. Is there any way to get this extra into the back stack or am I stuck?

Serene answered 30/10, 2012 at 22:47 Comment(0)
I
58

This line:

sBuilder.addParentStack( ActivityC.class );

adds all parents declared for ActivityC in AndroidManifest.xml in <meta-data>. I don't know what it is, I haven't used it. I doubt you need it.

This line adds intent to an array:

sBuilder.addNextIntent(launchIntent);

then the array of intents is used to create PendingIntent, probably with PendingIntent.getActivities, I couldn't find the implementation, which is then started somewhere with Context.startActivities.

I think you just need to create set of intents, there you can add extras:

Intent activityA = new Intent(context, ActivityA.class);
activityA.putExtra(key, valueA);
Intent activityB = new Intent(context, ActivityB.class);
activityB.putExtra(key, valueB);
Intent activityC = new Intent(context, ActivityC.class);
activityC.putExtra(key, valueC);

and add them to builder:

sBuilder.addNextIntent(activityA);
sBuilder.addNextIntent(activityB);
sBuilder.addNextIntent(activityC);
pIntent = sBuilder.getPendingIntent( 0, PendingIntent.FLAG_ONE_SHOT );

I haven't tested it, this is only a result of my fast research, I hope someone will correct me if I'm wrong.

Infighting answered 8/11, 2012 at 17:25 Comment(3)
Interesting approach, I didn't even think of trying that. I'll give it a shot and see if it works, might take a couple days until I have time, but I'll let you know. Thanks for the idea!Serene
I had to remove addParentStack and then I got the extras I sent. Strange because the code that is using addParentStack is from google's exampleSwinford
If I use PendingIntent.FLAG_UPDATE_CURRENT instead of PendingIntent.FLAG_ONE_SHOT back button click not navigating to Activity B from C. Why?Uppercase
D
14

I found another way to tackle this problem: use the method TaskStackBuilder.editIntentAt(int)

ex.

Intent intentC = new Intent(context, ActivityC.class);
intentC.putExtra(key, valueC);

TaskStackBuilder sBuilder = TaskStackBuilder.create(this)
    .addParentStack(ActivityB.class)
    .addParentStack(ActivityC.class)
    .addNextIntent(intentC);

Intent intentA = sBuilder.editIntentAt(0);
intentA.putExtra(key, value);
Intent intentB = sBuilder.editIntentAt(1);
intentB.putExtra(key, value);
Delight answered 26/6, 2014 at 18:2 Comment(1)
I fail to retrieve the Intent extra's at the ActivityA side when the notification is clicked :(Probationer
A
9

I have struggled with this one. My research resulted in the following solution (very similar to @pawelzieba but with one important deletion):

Intent activityA = new Intent(context, ActivityA.class);
activityA.putExtra(key, valueA);
Intent activityB = new Intent(context, ActivityB.class);
activityB.putExtra(key, valueB);
Intent activityC = new Intent(context, ActivityC.class);
activityC.putExtra(key, valueC);

TaskStackBuilder sBuilder = TaskStackBuilder.create(this)
    .addNextIntent(activityA);
    .addNextIntent(activityB);
    .addNextIntent(activityC);
PendingIntent pIntent = sBuilder.getPendingIntent( 0, PendingIntent.FLAG_UPDATE_CURRENT );

Note that you should not modify your manifest with the parent associations, and you do not want to use:

sBuilder.addParentStack( ActivityC.class );

or else you will get repeats of ActivityA and ActivityB in the newly created task that have intents without extras. If you do not need to pass intents with extras, you could add the parent associations in the manifest and call addParentStack().

Avalon answered 24/4, 2014 at 22:22 Comment(1)
You're right, that line adds a duplicate stack with no extra bundle. Thanks!Unscratched

© 2022 - 2024 — McMap. All rights reserved.