ArtKorchagin
ArtKorchagin

Reputation: 4853

How to clear intent data in Activity after open from url?

I have Activity, which can be launched directly from browser, calling url.

Activity code:

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        Uri data = getIntent().getData();
        Log.d(getClass().getName(), "onCreate data=" + data);

        getIntent().replaceExtras(new Bundle());
        getIntent().setAction("");
        getIntent().setData(null);
        getIntent().setFlags(0);

        if (data != null && isValidUrl(data)) {
            // open some special fragment
        } else {
            // open main fragment
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.d(MainActivity.class.getName(), "onDestroy");
    }

    //...
}

Application manifest code:

    ...

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

            <category android:name="android.intent.category.DEFAULT"/>
            <category android:name="android.intent.category.BROWSABLE"/>

            <data
                android:host="example.com"
                android:pathPrefix="/"
                android:scheme="http"/>
        </intent-filter>
    </activity>

    ...

This code works perfectly. When I open application from browser using link (http://example.com/somepage.html), I have this output:

D/com.package.MainActivity: onCreate data=http://example.com/somepage.html

But if I leave the application (using back button) and open application again, from recent menu, I get the same result:

D/com.package.MainActivity: onDestroy
D/com.package.MainActivity: onCreate data=http://example.com/somepage.html

I want to clear intent data in method onCreate. Or is there way to detect, when application is launched from recent menu?

UPD: I tried to do this:

@Override
protected void onDestroy() {
    super.onDestroy();

    getIntent().replaceExtras(new Bundle());
    getIntent().setAction("");
    getIntent().setData(null);
    getIntent().setFlags(0);

    Log.d(MainActivity.class.getName(), "onDestroy");
}

But it does not help.

Upvotes: 28

Views: 18038

Answers (6)

0101100101
0101100101

Reputation: 5911

I recommend running this right after super.onCreate:

if (intent.flags and Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY != 0)
     intent.data = null

then all further checks for intent data will return null and you won't have to bother with this ever again.

As it should've been on Android from day 1, if you ask me. If anyone knows any valid reason why it would make sense to re-trigger the same intent over and over when launching from history, please add a comment!

Upvotes: 0

Ole-Kristian
Ole-Kristian

Reputation: 691

Quite old thread here, but in case someone else is looking for this one:

You can check if your intent was sent due to app being launched from the recent-list by checking the flag FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY

    if ((getIntent().getData() != null) && ((getIntent().getFlags() & Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY) == 0)) {
            //Handle the url passed through the intent
        } else {
            //proceed as normal
        }

Upvotes: 23

Danuofr
Danuofr

Reputation: 1710

In your onCreate method you have

if (data != null && isValidUrl(data)) {
// open some special fragment
} else {
// open main fragment
}

Change to

if (data != null && isValidUrl(data)) {
    // open some special fragment
    getIntent().setData(null);
    setIntent(getIntent()); //This will set the new intent to have no data,
    //so future launches won't relaunch the data url.
    } else {
    // open main fragment
    }

Upvotes: -1

Paul Hayes
Paul Hayes

Reputation: 44

Rather than changing the intent data, you can store the hash of the intent and compare that hash each time the app gets focus. This way you get see if a new intent is present.

Example:

int currentIntent = getIntent().hashCode();

if (lastIntent != currentIntent) {
    // do stuff
}

Upvotes: 1

Andrew Panasiuk
Andrew Panasiuk

Reputation: 656

The way you want to do it goes against the principles of Android system. Android is designed so that Intent opens Activity and then if you want to open this Activity from Recents menu it receives the same intent.

I just guess that if you use one-Activity-many-fragments approach then you see one of its disadvantages. Android Intent system is designed in the way to use One Screen - One Activity approach which is the best practice.

If I'm wrong and you have some other case it would be really interesting to know it. Then you may think of how to redesign the app to achieve your needs.

Upvotes: 3

Hiren Patel
Hiren Patel

Reputation: 52810

Remove intent.getData() by below code:

Edit 1:

Uri data = getIntent().getData();
    Log.d(getClass().getName(), "onCreate data=" + data);

    if (data != null && isValidUrl(data)) {
        // open some special fragment
    } else {
        // open main fragment
    }

getIntent().setData(null);

Edit 2:

getIntent().replaceExtras(new Bundle());
getIntent().setAction("");
getIntent().setData(null);
getIntent().setFlags(0);

Hope this will help you.

Upvotes: 17

Related Questions