How to implement Android App Links with wildcard domains?

落爺英雄遲暮 提交于 2019-12-04 19:01:50

问题


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?


回答1:


  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>



回答2:


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




回答3:


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>


来源:https://stackoverflow.com/questions/39616895/how-to-implement-android-app-links-with-wildcard-domains

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!