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.
EDIT: I'm editing to post the complete solution I'm using.
This solution will work if the problem is "Not execute some code when the activity starts from History (Recent Apps)".
First of all, declare a boolean
in your Activity
to indicate if the Intent
was already consumed:
private boolean consumedIntent;
Then, safely store and restore this value using the onSaveInstanceState
and onCreate
methods to handle configuration changes and cases that the system may kill your Activity
when it goes to background.
private final String SAVED_INSTANCE_STATE_CONSUMED_INTENT = "SAVED_INSTANCE_STATE_CONSUMED_INTENT";
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putBoolean(SAVED_INSTANCE_STATE_CONSUMED_INTENT, consumedIntent);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//set content view ...
if( savedInstanceState != null ) {
consumedIntent = savedInstanceState.getBoolean(SAVED_INSTANCE_STATE_CONSUMED_INTENT);
}
//other initializations
}
Now, check if you can run your code under onResume
method.
@Override
protected void onResume() {
super.onResume();
//check if this intent should run your code
//for example, check the Intent action
boolean shouldThisIntentTriggerMyCode = [...];
Intent intent = getIntent();
boolean launchedFromHistory = intent != null ? (intent.getFlags() & Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY) != 0 : false;
if( !launchedFromHistory && shouldThisIntentTriggerMyCode && !consumedIntent ) {
consumedIntent = true;
//execute the code that should be executed if the activity was not launched from history
}
}
Additionally, if your Activity
is configured to singleTop
, you should reset your flag when a new Intent
is delivered.
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
setIntent(intent);
consumedIntent = false;
}
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.
When we launch Android apps from History (Recent Apps), the app could be launched with primarily three different Intent flags.
FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY
FLAG_ACTIVITY_NEW_TASK
FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY | FLAG_ACTIVITY_NEW_TASK
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.
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