How to implement Android App Links with wildcard domains?

流过昼夜 提交于 2019-12-03 13:31:51
  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-site-associations

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>

Android cannot handle wildcard domain as such(as per their documentation as of today), but, this will answer your query on inclusion and exclusion of certain /paths.

To implement deep linking for URL's like-

http://example.com/gizmos?1234, 
http://example.com/gizmos/1234,
http://example.com/gizmos/toys/1234,
etc.

Your XML should look something like this-

<activity android:name="com.example.android.GizmosActivity" android:label="@string/title_gizmos" > 

    <intent-filter android:label="@string/filter_title_viewgizmos">
        <action android:name="android.intent.action.VIEW" />
        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.BROWSABLE" /> <!-- Accepts URIs that begin with "example://gizmos” --> 

        <data android:scheme="example" android:host="gizmos" />
    </intent-filter>
    <intent-filter android:label="@string/filter_title_viewgizmos">
        <action android:name="android.intent.action.VIEW" />
        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.BROWSABLE" />
        <!-- Accepts URIs that begin with "http://example.com/gizmos” -->
        <data android:scheme="http" android:host="example.com" android:pathPrefix="/gizmos" /> 
    </intent-filter> 
</activity>

Now considering that you were able to achieve this, Here is how you restrict access to parts of your app content-

<?xml version="1.0" encoding="utf-8"?>
<search-engine xmlns:android="http://schemas.android.com/apk/res/android">
    <noindex uri="http://example.com/gizmos/hidden_uri"/>
    <noindex uriPrefix="http://example.com/gizmos/hidden_prefix"/>
    <noindex uri="gizmos://hidden_path"/>
    <noindex uriPrefix="gizmos://hidden_prefix"/>
</search-engine>

And The Manifest part-

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.android.Gizmos">
    <application> 
        <activity android:name="com.example.android.GizmosActivity" android:label="@string/title_gizmos" >
            <intent-filter android:label="@string/filter_title_viewgizmos">
            <action android:name="android.intent.action.VIEW"/> ... 
        </activity> 
            <meta-data android:name="search-engine" android:resource="@xml/noindex"/> 
    </application>
    <uses-permission android:name="android.permission.INTERNET"/>
</manifest>

For more details and explanation of this example, you can take a look at-

Android Deep Linking

Hope it helps, Happy Coding

Quoting from: https://developer.android.com/training/app-links/verify-site-associations.html

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). For example, an app with the following intent filter will pass verification for any sub-name of example.com (such as foo.example.com) as long as the assetlinks.json file is published at https:/ /example.com/.well- known/assetlinks.json:

<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="www.example.com" />
      <data android:scheme="https" android:host="mobile.example.com" />
    </intent-filter>
  </activity>
</application>
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!