简体   繁体   中英

Android: Activity is using old intent if launching app from Recent Task

I'm implementing GCM. My app has two activities, say A and B . I'm using this code to launch B from the NotificationBar:

long when = System.currentTimeMillis();
NotificationManager notificationManager =
    (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
String title = context.getString(R.string.app_name);        
Notification notification = new Notification(R.drawable.app_notification_icon, "De Centrale", when);//message
Intent notificationIntent = new Intent(context, B.class);
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP); //|Intent.FLAG_ACTIVITY_REORDER_TO_FRONT
PendingIntent intent = PendingIntent.getActivity(context, 0, notificationIntent, PendingIntent.FLAG_CANCEL_CURRENT);
notification.setLatestEventInfo(context, title, msg, intent);
notification.flags |= Notification.FLAG_AUTO_CANCEL;
notificationManager.notify(0, notification);

NotificationBar opens Activity B with an Intent, say 'B-notification-intent', then I open Activity A from B using Back button, then again I launch B from A having a new Intent (say 'BA-intent'). I use the code below:

intent = new Intent(this, B.class); 
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);              
startActivity(intent);

And then I get New Data in B (ie the screen of B is refreshed). But if I press the Home button and then I launch the application from Recent app then I get older B screen with 'B-notification-intent'. Instead, I want the latest Intent, ie 'BA-intent'. I'm using this code in B :

@Override
protected void onCreate(Bundle b)
{
    fetchDataFromDB(getIntent());           
}

@Override
protected void onNewIntent(Intent intent)
{
    fetchDataFromDB(intent);        
}

So anybody please help me getting my current screen (intent).

I also noticed that sometimes an Activity 's onCreate() was getting stale Intent s when launched from Recents, but there is a way to check for that so you can handle the Intent appropriately.

JAVA:

protected boolean wasLaunchedFromRecents() {
    return (getIntent().getFlags() & Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY) == Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY;
}

Kotlin:

fun wasLaunchedFromRecents(): Boolean {
    val flags: Int = intent.flags and Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY
    return flags == Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY
}

In my humble opinion, that flag is poorly named (other flags referencing the Recents list actually use that word, eg FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS , FLAG_ACTIVITY_RETAIN_IN_RECENTS ) and the documentation was never updated to reflect the fact that many popular Android devices have a dedicated button for Recents:

This flag is not normally set by application code, but set for you by the system if this activity is being launched from history (longpress home key).

(NB I realize that you solved your issue another way years ago, but this question is one of the top search results for 'android old intent recent' and none of the other related questions mention this flag, so hopefully this Answer can help someone else.)

For some reason bkDJ's / the accepted answer did not work for me. Only if the accepted answer also does not work for you, try this:

Neither FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY, nor setting a boolean to the intent after it was handled the first time prevented the intent from being being reused.

I had to add a timestamp to each intent where this issue occured. And only execute the intent if the timestamp was not older than 30 seconds.

Like this:

Intent intent = new Intent(CONTEXT, TargetActivity.class);
Calendar now = Calendar.getInstance();
intent.putExtra("timestampOfIntentInMilliseconds", now.getTimeInMillis());
// put your actual extras to the intent 

then when handling the intent:

Bundle extras = intent.getExtras();
long timestampOfIntentInMilliseconds = extras.getLong("timestampOfIntentInMilliseconds");
now = Calendar.getInstance();
if(now.getTimeInMillis() < (timestampOfIntentInMilliseconds + 30000))
{
   // do what you want to do with the intent
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM