Removing extras from passed-in Intent

AndroidAndroid Intent

Android Problem Overview


I have a search screen which can be launched from clicking on a "name" field of another screen.

If the user follows this workflow, I add an extra to the Intent's Extras called "search". This extra uses the text populating the "name" field as its value. When the search screen is created, that extra is used as a search parameter and a search is automatically launched for the user.

However, since Android destroys and recreates Activitys when the screen rotates, rotating the phone causes an auto-search again. Because of this, I'd like to remove the "search" extra from the Activity's Intent when the initial search is executed.

I've tried doing this like so:

    Bundle extras = getIntent().getExtras();
    if (extras != null) {
    	if (extras.containsKey("search")) {
    		mFilter.setText(extras.getString("search"));
    		launchSearchThread(true);
    		extras.remove("search");
    	}
    }

However, this isn't working. If I rotate the screen again, the "search" extra still exists in the Activity's Intent's Extras.

Any ideas?

Android Solutions


Solution 1 - Android

I have it working.

It appears getExtras() creates a copy of the Intent's extras.

If I use the following line, this works fine:

getIntent().removeExtra("search");

Source code of getExtras()

/**
 * Retrieves a map of extended data from the intent.
 *
 * @return the map of all extras previously added with putExtra(),
 * or null if none have been added.
 */
public Bundle getExtras() {
    return (mExtras != null)
            ? new Bundle(mExtras)
            : null;
}

Solution 2 - Android

While @Andrew's answer may provide a means for removing a specific Intent extra, sometimes it is necessary to clear ALL of the intent extras and, in this case, you will want to use

Intent.replaceExtras(new Bundle())

Source code of replaceExtras:

/**
 * Completely replace the extras in the Intent with the given Bundle of
 * extras.
 *
 * @param extras The new set of extras in the Intent, or null to erase
 * all extras.
 */
public @NonNull Intent replaceExtras(@NonNull Bundle extras) {
    mExtras = extras != null ? new Bundle(extras) : null;
    return this;
}

Solution 3 - Android

The problem can be solved using extra flag which is persistent during destroys and recreations. Here is the narrowed down code:

boolean mProcessed;

@Override
protected void onCreate(Bundle state) {
    super.onCreate(state);
    mProcessed = (null != state) && state.getBoolean("state-processed");
    processIntent(getIntent());
}

@Override
protected void onNewIntent(Intent intent) {
    super.onNewIntent(intent);
    mProcessed = false;
    processIntent(intent);
}

@Override
protected void onSaveInstanceState(Bundle state) {
    super.onSaveInstanceState(state);
    state.putBoolean("state-processed", mProcessed);
}

protected void processIntent(Intent intent) {
    // do your processing
    mProcessed = true;
}

Solution 4 - Android

Kotlin

activity?.intent?.removeExtra("key")

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAndrewView Question on Stackoverflow
Solution 1 - AndroidAndrewView Answer on Stackoverflow
Solution 2 - Androidw3bsharkView Answer on Stackoverflow
Solution 3 - AndroidGregoryKView Answer on Stackoverflow
Solution 4 - AndroidBenView Answer on Stackoverflow