Search code examples
androidintentfilter

Open different Activities on pathPrefixes /abc and /abc/def


I have two urls. For example:

  1. http://host.com/abc/12345
  2. http://host.com/abc/def/12345

Where an 12345 - is some id.

I want to open different activities for these urls.

Currently I have next implementation in AndroidManifest.xml:

<activity
    android:name=".ui.activities.Activity1"
    android:windowSoftInputMode="adjustResize">
    <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:scheme="http" android:host="host.com" android:pathPrefix="/abc"/>
    </intent-filter>
</activity>
<activity
    android:name=".ui.activities.Activity2"
    android:windowSoftInputMode="adjustResize">
    <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:scheme="http" android:host="host.com" android:pathPrefix="/abc/def"/>
    </intent-filter>
</activity>

First url works great: when I tap on it android suggest me to use some other apps or my Activity1.

But problem appears when I tap on second url: android suggest me to use some other apps or my Activity1 or my Activity2.

So my question is: is there a way to exclude Activity1 from list of suggestions.

I tried to play with pathPattern and tried to googling how to exclude url from IntentFilter but I failed.


Solution

  • Since I did not find elegant solution through `AndroidManifest.xml', I've decided to implement part of "choosing" logic through the code. So here what I have:

    In the manifest file we define UrlActivity that will respond on any url like "http://host.com/abc/...", so it will looks like:

    <activity
        android:name=".ui.activities.UrlActivity"
        android:screenOrientation="portrait"
        android:windowSoftInputMode="adjustResize">
        <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:scheme="http" android:host="host.com" android:pathPrefix="/abc"/>
        </intent-filter>
    </activity>
    

    Then we define interface Component (you can choose any name depends on behavior) that is tuned specially for UrlActivity. In simple case it can just duplicate analogous methods from activity. For example:

    public interface Component {
        void onStart();
        void onStop();
    }
    

    Then in your UrlActivity your retrieve uri and choose appropriate Component implementation. For example:

    private Component component;
    
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Uri uri = getIntent().getData();
        List<String> segments = uri.getPathSegments();
    
        if (segments.contains("def")) {
            component = new Component2(...);
        } else {
            component = new Component1(...);
        }
    }
    
    @Override
    protected void onStart() {
        super.onStart();
        component.onStart();
    }
    
    @Override
    protected void onStop() {
        super.onStop();
        component.onStop();
    }
    

    This solution have advantages compare to @KamranAhmed solution: scalability, reduced duplication. But also it have one flaw: you need to write more code and think about proper architecture for this solution. So it is indeed harder than @KamranAhmed approach, but for me it more DRY and flexible.