17

The closest I could find was this question here. but it doesnt quite cover the problem im having.

I have deep links in my app setup to use /app as the path prefix. The problem I'm having is that links like http://example.com/upgrade are also trying to open in my app even though it doesn't have /app anywhere in the url. I understand you cant exclude urls specified by the prefix, but isn't the whole point of path prefix to include only those urls?

basically I want links like these to deep link:

http://example.com/app/home
http://example.com/app/specials

but not links like these:

http://exaple.com/
http://example.com/login

and here is what I have in my manifest:

<data android:scheme="http"
    android:host="example.com"
    android:pathPrefix="/app"/>

Edit 1

also found this link but i dont have any empty prefixes, only ones with just a slash "/"

Edit 2

The url that was triggering it was http://example.com/upgrade.php?app=1&method=1&uid=1, I wasn't sure if app after the ? would also trigger it so I changed the prefix to /application but that also didn't work, its still triggering them.

Edit 3

here are the other deep link data tags in the manifest:

profile activity

<data android:scheme="myapp"
    android:host="profile"
    android:pathPrefix="/"/>

login/signup activity

<data android:scheme="myapp"
     android:host="login"
     android:pathPrefix="/signup"/>

main activity

<data android:scheme="myapp"
     android:host="main"
     android:pathPrefix="/"/>

<data android:scheme="http"
     android:host="test.example.com"
     android:pathPrefix="/app"/>

<data android:scheme="http"
     android:host="live.example.com"
     android:pathPrefix="/app"/>

Edit 4

This is getting more and more confusing, if I remove the data tag with myapp as the scheme from the activity (or if i remove the pathPrefix from everything with a prefix of "/") it no longer triggers the deep links from the web urls, even if they have /app in them.

Community
  • 1
  • 1
JStephen
  • 1,059
  • 3
  • 13
  • 28
  • Is that the only `` tag in your manifest? – Bryan Herbst Dec 14 '15 at 21:17
  • i have 3 for that activity, and two other activities each have one. – JStephen Dec 14 '15 at 21:20
  • thats the only one using example.com though, the others use my app name as the scheme, some of those use "/" as the prefix, but all of the ones that use http schemes have a defined prefix of "/app" – JStephen Dec 14 '15 at 21:23
  • Try using "android:pathPattern="/app*" – geNia Dec 14 '15 at 21:24
  • just tried pathPattern="/application*" and its not working either, the link is still triggering it even though it doesnt contain "application" at all. I'll add each of the data tags to the question in case theres something else there im missing. – JStephen Dec 14 '15 at 21:42
  • how are you testing this? – kandroidj Dec 14 '15 at 22:32

3 Answers3

24

I figured it out, It seems like the data tags sort of bleed into one another, so the prefix of "/" on the data with scheme "example" was also applying to all of the schemes in the other data tags. I just had to use separate Intent filters for my custom scheme deep links and the url deep links like so:

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

        <!-- must start with http://test.example.com/app -->
        <!-- http://test.example.com/ won't work since prefix / is in a different intent-filter -->
        <data android:scheme="http"
            android:host="test.example.com"
            android:pathPrefix="/app"/>

        <!-- must start with http://live.example.com/app -->
        <data android:scheme="http"
            android:host="live.example.com"
            android:pathPrefix="/app"/>

    </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" />

        <!-- must start with example://main/ -->
        <!-- http://test.example.com/ won't work since http is in a different intent-filter -->
        <data android:scheme="example"
            android:host="main"
            android:pathPrefix="/"/>

    </intent-filter>
</activity>
Bouh
  • 1,303
  • 2
  • 10
  • 24
JStephen
  • 1,059
  • 3
  • 13
  • 28
9

As explained here, your attributes get merged:

Although it's possible to include multiple <data> elements in the same filter, it's important that you create separate filters when your intention is to declare unique URLs (such as a specific combination of scheme and host), because multiple <data> elements in the same intent filter are actually merged together to account for all variations of their combined attributes.

Putting them into separate instances of <intent-filter> therefore fixes your problem.

saraedum
  • 1,389
  • 1
  • 11
  • 7
1

Running a few tests on my own I think you have created this problem yourself, before continuing to test any more deep links from your app go to

Settings -> Your App Name -> Launch by Default and select Clear defaults

Then navigate back to your app manifest and add the intent filter to your Activity for each url:

In your example you ask for

http://example.com/app/home
http://example.com/app/specials

I am going to assume you have an Activity that would launch each one of these for the URI given above.

for HomeActivity in manifest do:

<activity android:name=".HomeActivity">
    <intent-filter>
        <action android:name="android.intent.action.VIEW" />
        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.BROWSABLE" />

        <!-- http://example.com/app/home -->
        <data android:scheme="http"
            android:host="example.com"
            android:pathPrefix="/app/home"/>

        <!-- https://example.com/app/home -->
        <data android:scheme="https"
            android:host="example.com"
            android:pathPrefix="/app/home"/>

        <!-- custom url scheme example://app/home -->
        <data android:scheme="example"
            android:host="app"
            android:pathPrefix="/home"/>
    </intent-filter>
</activity>

Test with adb shell am start -W -a android.intent.action.VIEW -d http://example.com/app/home and adb shell am start -W -a android.intent.action.VIEW -d example.com/app/home From your terminal

then for your SpecialsActivity

<activity android:name=".SpecialsActivity">
    <intent-filter>
        <action android:name="android.intent.action.VIEW" />
        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.BROWSABLE" />

        <!-- http://example.com/app/specials -->
        <data android:scheme="http"
            android:host="example.com"
            android:pathPrefix="/app/specials"/>

        <!-- https://example.com/app/specials -->
        <data android:scheme="https"
            android:host="example.com"
            android:pathPrefix="/app/specials"/>

        <!-- custom url scheme example://app/specials -->
        <data android:scheme="example"
            android:host="app"
            android:pathPrefix="/specials"/>
    </intent-filter>
</activity>

Test with adb shell am start -W -a android.intent.action.VIEW -d http://example.com/app/specials and adb shell am start -W -a android.intent.action.VIEW -d example.com/app/specials From your terminal

this is pretty much how it works, if you set your app to handle a http://example.com/ url and select choose by default then, well its going to try to open http://example.com/{anything} using your app

So in short, when you specify your pathPrefix, make sure you include what you really want to intercept and don't choose your app by default if you test a link that shouldn't open your app, just adjust your pathPrefix so it won't be triggered by your app.

For example the URLS above won't open

http://example.com/app

because we haven't defined a <data /> tag to handle this.

UPDATE And to add straight from the docs when using \ or *:

Because '\' is used as an escape character when the string is read from XML (before it is parsed as a pattern), you will need to double-escape: For example, a literal '*' would be written as '\\*' and a literal '\' would be written as '\\\\'. This is basically the same as what you would need to write if constructing the string in Java code.

Good luck and happy coding!

Mr Lister
  • 45,515
  • 15
  • 108
  • 150
kandroidj
  • 13,784
  • 5
  • 64
  • 76
  • This probably would work, except I also have some existing deep links that use the custom scheme with no prefix, like `example://main/` which just goes to the main page, then some that open specific fragments in the main activity like `example://main/settings` It sounds like I will have to get rid of the first one and just have prefixes on everything. But that requires i change my deep links which is easier said than done once they are out there. – JStephen Dec 15 '15 at 16:02