Issue
One of my activity (A) is launched via push notifications, through the PendingIntent provided. If this intent has a certain key, then I need to start a new activity (B). Pressing back on B, I should return to A. If I enable "Don't keep activities" through developer settings, A is obviously killed after launching B, which means on return from B to A, A is recreated with the original intent (which has the extra key) - which launches B again - and it results in the user being stuck on B.
As a workaround, I tried removing the extra key in A before launching B and resetting the intent. This code is from the onCreate()
method in activity A. I have added an AlarmManager
to easily replicate the behavior - it has nothing to do with my problem.
Intent originalIntent = getIntent();
if(originalIntent != null && originalIntent.hasExtra("A")){
Log.d(TAG, "onCreate: has A" );
startActivity(new Intent(this, PAlarmTwo.class));
originalIntent.removeExtra("A");
setIntent(originalIntent);
Log.d(TAG, "onCreate: modified intent has A : " + getIntent().hasExtra("A"));
} else {
Log.d(TAG, "onCreate: no A");
}
final FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Intent alarmIntent = new Intent(PAlarmOne.this, PAlarmOne.class);
alarmIntent.putExtra("A", "a");
PendingIntent pendingIntent = PendingIntent.getActivity(PAlarmOne.this, 1, alarmIntent, 0);
alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime()+1000, pendingIntent);
}
});
The logs indicate that although setIntent()
is deleting the key before launching B, recreated A gets the old intent with the key. Basically, the log ("no A") is never printed.
2 solutions I have tried:
- Passing
PendingIntent.FLAG_ONE_SHOT
for creatingPendingIntent
. Based on the documentation, it should work, but it isn't. Is my understanding of this flag wrong? - Setting an instance variable in activity A indicating if the intent has been used once. I can externally persist this variable through
onSaveInstanceState()
and it will persist across recreated instances of the same activity. This approach does not feel clean, for introducing a new variable to track across multiple lifecycle methods.
Solution
A is obviously killed after launching B, which means on return from B to A, A is recreated with the original intent (which has the extra key) - which launches B again - and it results in the user being stuck on B.
You should be saving state in the saved instance state Bundle
that tells you whether or not you should be starting B.
The logs indicate that although setIntent() is deleting the key before launching B, recreated A gets the old intent with the key.
My guess is that setIntent()
only affects the current instance. It does not send instructions back to the core OS to somehow associate this new Intent
with the back stack record that Android will use to recreate A.
Is my understanding of this flag wrong?
That flag controls the PendingIntent
. It does not affect the component started by the Intent
wrapped in that PendingIntent
.
This approach does not feel clean, for introducing a new variable to track across multiple lifecycle methods.
You are welcome to your opinion. There are plenty of things involved in activity state, including plenty of things that might need to be invoked only once (e.g., data loads, confirmation messages). This is just another one.
Answered By - CommonsWare
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.