Search code examples
androidiosapplinks

How to implement Android App Links with wildcard domains?


Android has a guide about how to implement app links. That is, if my app declares that it handles certain web links, and I try to open this link in any other app, the system intercepts this and takes the user straight to my app, instead of the browser, so that I can show relevant content straight in my app. Very handy.

What I am missing in the guide is two things:

  1. How to implement app links with wildcard domains. I would like my app to handle links to *.example.com, that is, all links to subdomains of example.com (test.example.com, something.example.com etc);

  2. How to implement app links only to specific paths on my site. For example I want to intercept test.example.com/something, but not test.example.com/other. The first one should come to my app, the other one to my browser;

The corresponding iOS guide shows that iOS handles both of these scenarios (though the wildcard part was unclear from the docs and I had to clarify with Apple Support that you need to place the association file in the root domain, not a subdomain).

Can Android App Links handle wildcard domains and only a subset of paths?


Solution

    1. Update: now you can handle wildcard domains, using the Digital Asset Links

    aurilio explained it in his newer answer

    The whole process is documented here: https://developer.android.com/training/app-links/verify-android-applinks

    To sum it up, now you can use a wildcard in the host tag, and you must upload a json file called assetlinks.json to the /.well-known folder/route on your root domain.

    Alternatively, if you declare your hostname with a wildcard (such as *.example.com), you must publish your assetlinks.json file at the root hostname (example.com)

    You will also need to add the attribute android:autoVerify="true" to your intent-filter tag.

    Here's the whole example on the Android side:

    <application>
      <activity android:name=”MainActivity”>
        <intent-filter android:autoVerify="true">
          <action android:name="android.intent.action.VIEW" />
          <category android:name="android.intent.category.DEFAULT" />
          <category android:name="android.intent.category.BROWSABLE" />
          <data android:scheme="https" android:host="*.example.com" />
        </intent-filter>
      </activity>
    </application>
    

    Here's the previous answer from 2016: Unfortunately it seems that Android cannot handle wildcard domains.

    If you look at the API guide for the data tag (https://developer.android.com/guide/topics/manifest/data-element.html), you can see they mention that wildcard is available for pathPattern and mimeType, but not for host.

    The thing is that, as explained by CommonsWare in an other post on the subject (https://stackoverflow.com/a/34068591/4160079),

    the domains are checked at install time, and there is no means to add new domains except by shipping a new edition of the app with a new manifest.

    So you will have to manually list all the subdomains available, and update the app whenever a new subdomain is launched.

    Here's how you declare multiple subdomains:

     <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" />
            <data android:scheme="http" />
            <data android:host="subdomain1.example.com" />
            <data android:host="subdomain2.example.com" />
            <data android:host="subdomain3.example.com" />
        </intent-filter>
    </activity>
    
    1. Yes, you can handle only a subset of paths

    It is the same idea, just list the paths you want using the path attribute (again, see data tag API guide above).

    If you use query strings or path params, prefer using pathPrefix.

    If necessary, you can use wildcards here, by choosing pathPattern instead.

    The path part of a URI which must begin with a /. The path attribute specifies a complete path that is matched against the complete path in an Intent object. The pathPrefix attribute specifies a partial path that is matched against only the initial part of the path in the Intent object. The pathPattern attribute specifies a complete path that is matched against the complete path in the Intent object, but it can contain the following wildcards: An asterisk ('') matches a sequence of 0 to many occurrences of the immediately preceding character. A period followed by an asterisk (".") matches any sequence of 0 to many characters.

    Here's a few examples:

     <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" />
            <data android:scheme="http" />
            <data android:host="subdomain1.example.com" />
            <data android:host="subdomain2.example.com" />
            <data android:host="subdomain3.example.com" />
            <data android:path="/path1" /> <!-- matches /path1 only -->
            <data android:pathPrefix="/path2" /> <!-- matches /path2, /path2/something or also /path2?key=value etc... -->
            <data android:pathPattern="/wild.*" /> <!-- matches /wild, /wild3, /wilderness etc... -->
        </intent-filter>
    </activity>