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:
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?
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.
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);
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().
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With