Clearing intent

2020-01-25 13:29发布

My Android app is getting called by an intent that is passing information (pendingintent in statusbar).

When I hit the home button and reopen my app by holding the home button it calls the intent again and the same extras are still there.

    @Override
    public void onSaveInstanceState(Bundle savedInstanceState) {
      super.onSaveInstanceState(savedInstanceState);
    }
    @Override
    public void onRestoreInstanceState(Bundle savedInstanceState) {
      super.onRestoreInstanceState(savedInstanceState);
    }

this is the code that doesn't run like its supposed to

    String imgUrl;
    Bundle extras = this.getIntent().getExtras();


    if(extras != null){
        imgUrl = extras.getString("imgUrl");
        if( !imgUrl.equals(textView01.getText().toString()) ){

            imageView.setImageDrawable( getImageFromUrl( imgUrl ) );
            layout1.setVisibility(0);
            textView01.setText(imgUrl);//textview to hold the url

        }

    }

And my intent:

public void showNotification(String ticker, String title, String message, 
    String imgUrl){
    String ns = Context.NOTIFICATION_SERVICE;
    NotificationManager mNotificationManager = 
        (NotificationManager) getSystemService(ns);
    int icon = R.drawable.icon;        // icon from resources
    long when = System.currentTimeMillis();         // notification time
    CharSequence tickerText = ticker;              // ticker-text

    //make intent
    Intent notificationIntent = new Intent(this, activity.class);
    notificationIntent.putExtra("imgUrl", imgUrl);
    notificationIntent.setFlags(
        PendingIntent.FLAG_UPDATE_CURRENT | 
        PendingIntent.FLAG_ONE_SHOT);
    PendingIntent contentIntent = 
        PendingIntent.getActivity(this, 0, 
        notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT | 
        PendingIntent.FLAG_ONE_SHOT);

    //make notification
    Notification notification = new Notification(icon, tickerText, when);
    notification.setLatestEventInfo(this, title, message, contentIntent);
    //flags
    notification.flags = Notification.FLAG_SHOW_LIGHTS | 
        Notification.FLAG_ONGOING_EVENT | 
        Notification.FLAG_ONLY_ALERT_ONCE | 
        Notification.FLAG_AUTO_CANCEL;
    //sounds
    notification.defaults |= Notification.DEFAULT_SOUND;
    //notify
    mNotificationManager.notify(1, notification);
}

Is there any way to clear the intent or check whether it has been used before?

19条回答
女痞
2楼-- · 2020-01-25 14:13

Maks answer works for clearing an extra:

    getIntent().removeExtra("key"); 

Another useful command is:

    getIntent().setAction("");

You could also tag an intent by calling:

    getIntent().putExtra("used", true);

and then just check for the value.

查看更多
Lonely孤独者°
3楼-- · 2020-01-25 14:14

UPDATE:

I didn't realise this answer would be referred to so much when I first wrote it more then 5 years ago!

I'll clarify to point out that as per @tato-rodrigo answer this won't help you detect an already handled intent in some situations.

Also I should point out I put "clear" in quotes for a reason - you are not really clearing the intent by doing this, you're just using the removal of the extra as a flag that this intent has been seen by the activity already.


I had exactly the same issue.

Above answer put me on the right track and I found even simpler solution, use the:

getIntent().removeExtra("key"); 

method call to "clear" the Intent.

Its a bit late answering since this was asked a year ago, but hopefully this helps others in the future.

查看更多
ゆ 、 Hurt°
4楼-- · 2020-01-25 14:15

How about this? Sets newIntent as the intent.

@Override
protected void onNewIntent(Intent intent) {
    super.onNewIntent(intent);
    setIntent(intent);
}
查看更多
再贱就再见
5楼-- · 2020-01-25 14:17

How about when you wish to clear the intent - replace it with an empty one?

eg.

@Override
protected void onNewIntent(Intent intent) {
    super.onNewIntent(intent);
    setIntent(intent);
}

@Override 
public void onResume() {
    super.onResume();

    Intent theIntent = getIntent();
    if ("myaction".equals(theIntent.getAction()) {
         handleIntent();
         onNewIntent(new Intent());  // <--- "clear" the intent by setting empty one
    }
}
查看更多
萌系小妹纸
6楼-- · 2020-01-25 14:20

When we launch Android apps from History (Recent Apps), the app could be launched with primarily three different Intent flags.

  1. FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY
    This is when activity is being launched from history of an app that was minimised (long press home key).
    Constant Value: 1048576 (0x00100000)
  2. FLAG_ACTIVITY_NEW_TASK
    This is when activity is launched via "clicking application icon" or via "Intent filters". Here the activity will become the start of a new task on this history stack.
    Constant Value: 268435456 (0x10000000)
  3. FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY | FLAG_ACTIVITY_NEW_TASK
    This is when app was quit by pressing back button and then resumed from History (recent apps).
    Constant Value: 269484032 (0x10100000)

Constant value can be retrieved via getIntent().getFlags()

In the third case, Android reloads the last Intent values from its memory. So your app's intent (getIntent) will have values from the last intent that launched the app.

Actually, the app should behave as if it is a fresh launch, with intents values for a fresh launch rather than the intent values of the previous launch. This behaviour can be seen if you launch the app by clicking the app icon, it will never have old intent values. This is because, Android uses the following intent filter for this scenario

 <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER"/>
 </intent-filter>

But in the third case (App that was quit, is launched from History of Recent apps), Android OS uses that last intent that launched the app before it was quit (via pressing back button). So you end up having old intent values and the app flow is not proper.

Removing intent is one way of solving it, but it would not solve the issue completely! As Android OS reloads the Intent from the apps last launch, and not last instance of the launch intent.

A clean way to avoid this from happening, is to handle it via getting the type of Intent to determine the launch type.

So in your LaunchActivity (The one which has the intent filter defined in the manifest), you could use the following code in the onCreate(), onStart(), or onResume() methods.

if(getIntent().getFlags() == (Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY)) {
    //app is launched from recent apps after it was closed
        normalLaunch();
    } else {
        String intentAction = getIntent().getAction();
        String scheme = getIntent().getScheme();
        //app is launched via other means
        // URL intent scheme, Intent action etc
        if("https".equalsIgnoreCase(scheme)) {
            // URL intent for browser
        } else if("com.example.bb".equalsIgnoreCase(intentAction)) {
            // App launched via package name
        } else {
            // App was launched via Click on App Icon, or other means
            normalLaunch();
        }
    }

I presume normalLaunch(), should not use parameters from the Intent; otherwise you would need to segregate and optimise your default launch method not to use Intent parameters.

查看更多
做自己的国王
7楼-- · 2020-01-25 14:22

I confront the same problem and try to use above methods but it doesn't work.

I think it may be cause of acitvity's launch mode which I used singleTop mode.

When I background app and use RamEater to simulate issue that intent always has extra even I set it null or remove key.

The problem is gone by using preference storage on Android to check that had pass through.

查看更多
登录 后发表回答