如何实现 Android App Links with wildcard domains?

How to implement Android App Links with wildcard domains?

Android 有 a guide about how to implement app links. 也就是说,如果我的应用程序声明它处理某些 Web links,并且我尝试在任何其他应用程序中打开这个 link ,系统会拦截它并将用户直接带到我的应用程序,而不是浏览器,这样我就可以直接在我的应用程序中显示相关内容。非常好用。

我在指南中缺少的是两件事:

  1. 如何使用通配符域实现应用 links。我希望我的应用程序能够处理 links 到 *.example.com,也就是说,所有 links 到 example.com 的 subdomains(test.example.com, 某事。example.com 等);

  2. 如何仅将应用 link 应用到我网站上的特定路径。例如,我想拦截 test.example.com/something,但不想拦截 test.example.com/other。第一个应该到我的应用程序,另一个到我的浏览器;

The corresponding iOS guide 显示 iOS 处理这两种情况(尽管文档中的通配符部分不清楚,我不得不向 Apple 支持人员澄清您需要将关联文件放在根域,而不是子域)。

Android 应用程序链接可以处理通配符域并且只处理部分路径吗?

Android 无法处理通配符域(根据他们今天的文档),但是,这将回答您关于包含和排除某些 /paths[=32= 的查询].

为 URL 的赞实现深度链接-

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

您的 XML 应该看起来像这样-

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

现在考虑到您能够做到这一点,下面是您如何限制对部分应用内容的访问-

<?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>

和清单部分-

<?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>

关于这个例子的更多细节和解释,可以看看-

Android Deep Linking

希望对您有所帮助,编码愉快

  1. 更新:现在您可以使用数字资产链接
  2. 处理通配符域

整个过程记录在这里:https://developer.android.com/training/app-links/verify-site-associations

综上所述,现在您可以在主机标签中使用通配符,并且您必须上传一个名为 assetlinks.json 的 json 文件/.well-known folder/route在您的 root 域上。

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)

您还需要添加属性 android:autoVerify="true"到您的intent-filter 标签。

这是 Android 方面的整个示例:

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

这是 2016 年的上一个答案: 很遗憾,Android 似乎无法处理通配符域

如果您查看 data 标记 (https://developer.android.com/guide/topics/manifest/data-element.html) 的 API 指南,您会看到他们提到通配符可用于 pathPattern 和mimeType,但不适用于主机。

事实是,正如 CommonsWare 在另一篇关于该主题 () 的 post 中所解释的那样,

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.

因此您必须手动列出所有可用的子域,并在启动新子域时更新应用程序。

声明多个子域的方法如下:

 <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. 是的,您只能处理路径的子集

也是一样的思路,只需要使用path属性列出你想要的路径(同样,参见data标签API 上面的指南)。

如果您使用查询字符串或路径参数,最好使用 pathPrefix.

如有必要,您可以在此处使用通配符,方法是选择 pathPattern

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.

这里有几个例子:

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

引用自:https://developer.android.com/training/app-links/verify-site-associations.html

或者,如果您使用通配符(例如 *.example.com)声明您的主机名,则必须在根主机名 (example.com) 处发布您的 assetlinks.json 文件。例如,具有以下 Intent 过滤器的应用程序将通过对 example.com 的任何子名称(例如 foo.example.com)的验证,只要 assetlinks.json 文件发布在 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>