测试应用链接

实现应用关联功能时,您应测试关联功能,以确保系统可以按预期将您的应用与网站相关联,并处理网址请求。

如需测试现有状态文件,您可以使用状态列表生成器和测试器工具。

以下部分介绍了如何手动测试应用链接验证。如果您愿意,也可以通过 Play 深层链接工具或 Android Studio App Links Assistant 测试验证。

确认需要验证的主机列表

测试时,您应确认系统应为您的应用验证的关联主机列表。列出其对应 intent 过滤器包含以下属性和元素的所有网址:

  • 值为 http 或 https 的 android:scheme 属性
  • 具有网域网址格式的 android:host 属性
  • android.intent.action.VIEW 操作元素
  • android.intent.category.BROWSABLE 类别元素

请使用此列表检查每个指定的主机和子网域是否都提供了 Digital Asset Links JSON 文件。

确认 Digital Asset Links 文件

对于每个网站,请使用 Digital Asset Links API 确认 Digital Asset Links JSON 文件是否已正确托管和定义:

https://digitalassetlinks.googleapis.com/v1/statements:list?
   source.web.site=https://<var>domain.name</var>:<var>optional_port</var>&amp;
   relation=delegate_permission/common.handle_all_urls

对于动态应用链接,您还可以检查关系扩展。

https://digitalassetlinks.googleapis.com/v1/statements:list?source.web.site=https://www.example.com&relation=delegate_permission/common.handle_all_urls&return_relation_extensions=true

在测试过程中,您可以检查当前的系统设置,了解链接处理方式。使用以下命令可获取已连接设备上所有应用的现有链接处理政策的列表:

adb shell dumpsys package domain-preferred-apps

以下命令执行相同的操作:

adb shell dumpsys package d

该命令会返回设备上定义的每个用户或个人资料的列表,前面带有以下格式的标头:

App linkages for user 0:

在此标题之后,输出会使用以下格式列出该用户的链接处理设置:

Package: com.android.vending
Domains: play.google.com market.android.com
Status: always : 200000002

此列表指明了哪些应用与该用户的哪些网域相关联:

  • Package - 通过应用的软件包名称(在清单中声明)来标识应用。
  • Domains - 显示此应用处理其网页链接的主机的完整列表,使用空格作为分隔符。
  • Status - 显示此应用的当前链接处理设置。如果应用已通过验证,并且其清单包含 android:autoVerify="true",则会显示 always 状态。此状态后面的十六进制数字与 Android 系统对用户应用关联偏好设置的记录有关。此值不表示验证是否成功。

测试示例

为了成功验证应用链接,系统必须能够根据您在符合应用链接条件的给定 intent 过滤器中指定的每个网站来验证您的应用。以下示例展示了定义了多个应用链接的清单配置:

<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" />
            <data android:scheme="https" />
            <data android:host="www.example.com" />
            <data android:host="mobile.example.com" />
        </intent-filter>
        <intent-filter>
            <action android:name="android.intent.action.VIEW" />
            <category android:name="android.intent.category.BROWSABLE" />
            <data android:scheme="https" />
            <data android:host="www.example2.com" />
        </intent-filter>
    </activity>

    <activity android:name="SecondActivity">
        <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="https" />
            <data android:host="account.example.com" />
        </intent-filter>
    </activity>

      <activity android:name="ThirdActivity">
        <intent-filter>
            <action android:name="android.intent.action.VIEW" />
            <category android:name="android.intent.category.DEFAULT" />
            <data android:scheme="https" />
            <data android:host="map.example.com" />
        </intent-filter>
        <intent-filter>
            <action android:name="android.intent.action.VIEW" />
            <category android:name="android.intent.category.BROWSABLE" />
            <data android:scheme="market" />
            <data android:host="example.com" />
        </intent-filter>
      </activity>

</application>

平台会尝试从上述清单中验证的主机列表如下:

www.example.com
mobile.example.com
www.example2.com
account.example.com

平台不会尝试从上述清单中验证的主机列表如下:

map.example.com (it does not have android.intent.category.BROWSABLE)
market://example.com (it does not have either an "http" or "https" scheme)

如需详细了解语句列表,请参阅创建语句列表。

从 Android 17 开始,您可以将 --debug-link 标志与 activity 管理器 (am start) 命令搭配使用,以诊断系统如何解析特定网址。此工具会详细列出与 intent 匹配的候选应用,以及在解析过程中评估的应用清单和 assetlinks.json 文件(对于动态应用链接)中的特定规则。

如需测试特定网址的链接解析,请在终端窗口中运行以下命令:

adb shell am start --debug-link -a android.intent.action.VIEW -d "https://xyz.com/foo"

诊断输出会输出在标题 App Link Resolution Debug 下,并包含以下部分,可帮助您了解解析过程:

  • 目标详情:通过软件包名称和目标 activity 标识每个匹配的候选应用。
  • Intent 过滤器匹配 (AndroidManifest.xml):显示清单 intent 过滤器中的哪些静态属性(例如 scheme、host、path、pathPrefix 或 pathPattern)与 URI 匹配。
  • 应用链接验证:显示当前网域验证状态(例如 STATE_SUCCESS)。
  • 动态应用链接:如果应用在其 assetlinks.json 文件中使用了动态应用链接匹配规则,此部分会列出针对该 URI 评估过的每条规则。每条规则都指明了匹配的 URI 过滤条件(例如路径前缀或格式)以及 allow 字段:
    • allow = 0:允许/包含规则 (allow: true)。如果此规则匹配,则允许应用打开 URI。
    • allow = 1:屏蔽/排除规则 (allow: false / exclude: true)。如果此规则匹配,系统会阻止应用打开相应 URI。
    • 注意:空过滤条件字符串 (filter =) 表示空路径前缀,它与网域下的所有路径匹配(充当通配符或包罗万象)。

调试输出示例

假设有一个应用 (com.example.xyzapp) 与网域 https://xyz.com 相关联,该应用在其 assetlinks.json 文件中定义了动态规则,以排除 /foo*,同时允许所有其他路径:

[
  {
    "relation": [
      "delegate_permission/common.handle_all_urls"
    ],
    "target": {
      "namespace": "android_app",
      "package_name": "com.example.xyzapp",
      "sha256_cert_fingerprints": ["..."]
    },
    "relation_extensions": {
      "delegate_permission/common.handle_all_urls": {
        "dynamic_app_link_components": [
          {"/": "/foo*", "exclude": true},
          {"/": "*"}
        ]
      }
    }
  }
]

使用 --debug-link 诊断网址 https://xyz.com/foo 时:

adb shell am start --debug-link -a android.intent.action.VIEW -d "https://xyz.com/foo"

该命令会输出以下诊断细分:

--- App Link Resolution Debug ---

URI: https://xyz.com/foo
Resolution: Ambiguous (Multiple apps or Browser fallback)
This usually happens when multiple apps can handle the link and no default is set.

All Matching Candidates:

Target:
  Package: com.example.xyzapp
  Activity: com.example.xyzapp.MainActivity

  Intent Filter Match (AndroidManifest.xml)
    Scheme: 'https' matched android:scheme="https"
    Host: 'xyz.com' matched android:host="xyz.com"

App Link Verification:
  Verification status: STATE_SUCCESS
  Dynamic App Links:
    -> Matched Rule 0: UriRelativeFilterGroup { allow = 1, uri_filters = {UriRelativeFilter { uriPart = PATH, patternType = PREFIX, filter = /foo }},  }
    -> Matched Rule 1: UriRelativeFilterGroup { allow = 0, uri_filters = {UriRelativeFilter { uriPart = PATH, patternType = PREFIX, filter =  }},  }

Target:
  Package: org.chromium.webview_shell
  Activity: org.chromium.webview_shell.WebViewBrowserActivity

  Intent Filter Match (AndroidManifest.xml)
    Scheme: 'https' matched android:scheme="https"

---------------------------------

Starting: Intent { act=android.intent.action.VIEW dat=https://xyz.com/foo }

在此示例中,系统评估了 assetlinks.json 中的两条动态应用链接规则:

  • 规则 0(allow = 1、filter = /foo):根据 {"/": "/foo*", "exclude": true} 生成,这是一条排除规则 (allow: false),用于屏蔽以 /foo 路径前缀开头的网址。
  • 规则 1(allow = 0、filter =):根据 {"/": "*"} 生成,这是一条包含规则 (allow: true),其路径前缀为空 (filter =),可匹配 xyz.com 下的所有路径(包罗万象)。

此场景中的解析工作原理:

  1. 规则 0 和规则 1 均与网址 https://xyz.com/foo 匹配。
  2. 系统会按照从上到下的顺序依次评估动态应用链接规则(第一个匹配的规则胜出)。
  3. 由于规则 0 首先出现在语句列表中,并且是一条排除规则 (allow = 1),因此它优先于常规允许规则(规则 1)。
  4. 因此,该应用会被排除在处理 https://xyz.com/foo 的范围之外,从而导致系统回退到浏览器或显示消除歧义对话框。