25

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.

ArtKorchagin
  • 4,801
  • 13
  • 42
  • 58

5 Answers5

19

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
        }
Ole-Kristian
  • 541
  • 5
  • 6
  • what a coincidence, I was looking for the solution. `FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY` is not working – Krrishnaaaa Mar 21 '18 at 12:25
  • 8
    It's `(getIntent().getFlags() & Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY) == Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY` to check if the activity has been launched from history: it's a great idea, and it works – Giulio Piancastelli Sep 18 '18 at 07:02
  • 4
    Kotlin extension `fun Intent.isLaunchFromHistory(): Boolean = this.flags and Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY == Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY` – smora Feb 20 '20 at 18:48
17

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.

Hiren Patel
  • 52,124
  • 21
  • 173
  • 151
3

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.

Andrew Panasiuk
  • 626
  • 1
  • 8
  • 17
  • One activity - one screen is not the best practice anymore because since the introduction of architecture components the Android team promotes the single activity architecture. – Xam Mar 05 '21 at 14:33
1

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
}
Siegmeyer
  • 4,312
  • 6
  • 26
  • 43
Paul Hayes
  • 44
  • 2
  • This doesn't work since the hashcode is different everytime, but the same intent still comes through – Rajath Sep 06 '17 at 06:51
-1

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
    }
Danuofr
  • 1,661
  • 19
  • 25
  • 2
    have you tried this? I did a `setIntent(new Intent())` and still I get the old intent – Boy Oct 25 '17 at 06:11
  • @Boy : Whenever your activity is opened, it is done with an Intent. Now that will always renew the intent (if singleTop, singleTask or singleInstance launch mode ( method onNewIntent(), after the first time). setNewIntent() will immediately clear the current intent, and you will not be able to use the original bundle what was there primarily. – Abhinav Saxena Apr 11 '22 at 04:48