验证Android应用链接

Android 应用链接是一种特殊的深度链接,允许您的网站 URL 立即在您的 Android 应用中打开相应的内容,而无需用户选择应用。Android 应用链接使用数字资产链接 API来建立信任,证明您的应用已获得网站批准,可以自动打开该域的链接。如果系统成功验证您拥有这些 URL,则系统会自动将这些 URL 意图路由到您的应用。

要验证您同时拥有您的应用和网站 URL,请完成以下步骤

  1. 添加包含autoVerify属性的意图过滤器。此属性向系统发出信号,表明它应该验证您的应用是否属于意图过滤器中使用的 URL 域。

  2. 声明您的网站和意图过滤器之间的关联,方法是在以下位置托管数字资产链接 JSON 文件

    https://domain.name/.well-known/assetlinks.json

您可以在以下资源中找到相关信息

添加应用链接验证的意图过滤器

要为您的应用启用链接处理验证,请添加与以下格式匹配的意图过滤器

<!-- Make sure you explicitly set android:autoVerify to "true". -->
<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" />

    <!-- If a user clicks on a shared link that uses the "http" scheme, your
         app should be able to delegate that traffic to "https". -->
    <!-- Do not include other schemes. -->
    <data android:scheme="http" />
    <data android:scheme="https" />

    <!-- Include one or more domains that should be verified. -->
    <data android:host="..." />
</intent-filter>

虽然在每个主机的一个<intent-filter>声明中包含autoVerify就足够了,即使该主机在其他未标记的声明中使用,但建议您为每个<intent-filter>元素添加autoVerify以保持一致性。这还可以确保在删除或重构清单文件中的元素后,您的应用仍然与您仍然定义的所有域关联。

域验证过程需要互联网连接,并且可能需要一些时间才能完成。为了提高过程效率,系统仅当域位于包含前面代码片段中指定的精确格式的<intent-filter>元素内时,才验证目标为 Android 12 或更高版本的应用的域。例如,与“http”和“https”不同的方案,例如<data android:scheme="custom" />,将阻止<intent-filter>触发域验证。

支持多个主机的应用链接

系统必须能够针对应用的 URL 意图过滤器的数据元素中指定的主机,验证在该意图过滤器中各自的网络域上托管的数字资产链接文件。如果验证失败,则系统将默认为其标准行为来解析意图,如创建指向应用内容的深度链接中所述。但是,应用仍然可以验证为其其他意图过滤器中定义的任何 URL 模式的默认处理程序。

注意:在 Android 11(API 级别 30)及更低版本上,除非系统找到与您在清单中定义的所有主机匹配的数字资产链接文件,否则系统不会将您的应用验证为默认处理程序。

例如,如果在https://www.example.com/.well-known/assetlinks.json处找到assetlinks.json文件,但在https://www.example.net/.well-known/assetlinks.json处没有找到,则具有以下意图过滤器的应用将仅针对https://www.example.com通过验证

<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="http" />
      <data android:scheme="https" />
      <data android:host="www.example.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="www.example.net" />
    </intent-filter>
  </activity>

</application>

注意:同一意图过滤器中的所有<data>元素都将合并在一起,以考虑其组合属性的所有变体。例如,上面的第一个意图过滤器包含一个<data>元素,该元素仅声明 HTTPS 方案。但是它与其他<data>元素组合在一起,因此意图过滤器同时支持http://www.example.comhttps://www.example.com。因此,当您要定义 URI 方案和域的特定组合时,必须创建单独的意图过滤器。

支持多个子域的应用链接

数字资产链接协议将意图过滤器中的子域视为唯一、独立的主机。因此,如果您的意图过滤器列出了具有不同子域的多个主机,则必须在每个域上发布有效的assetlinks.json。例如,以下意图过滤器包含www.example.commobile.example.com作为可接受的意图 URL 主机。因此,必须在https://www.example.com/.well-known/assetlinks.jsonhttps://mobile.example.com/.well-known/assetlinks.json处发布有效的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" />
      <data android:scheme="https" />
      <data android:host="www.example.com" />
      <data android:host="mobile.example.com" />
    </intent-filter>
  </activity>
</application>

或者,如果您使用通配符声明主机名(例如*.example.com),则必须在根主机名(example.com)上发布您的assetlinks.json文件。例如,具有以下意图过滤器的应用将通过 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" />
      <data android:host="*.example.com" />
    </intent-filter>
  </activity>
</application>

检查与同一域名关联的多个应用

如果您发布多个都与同一域名关联的应用,则每个应用都可以成功验证。但是,如果这些应用可以解析完全相同的域名主机和路径(例如应用的精简版和完整版),则只有最近安装的应用才能解析该域名的 Web 意图。

在这种情况下,请检查用户设备上是否存在可能的冲突应用(前提是您拥有必要的包可见性)。然后,在您的应用中,显示一个自定义选择器对话框,其中包含调用queryIntentActivities()的结果。用户可以从对话框中显示的匹配应用列表中选择其首选应用。

声明网站关联

必须在您的网站上发布一个数字资产链接 JSON 文件,以指示与该网站关联的 Android 应用并验证应用的 URL 意图。JSON 文件使用以下字段来标识关联的应用

  • package_name:应用的build.gradle文件中声明的应用 ID
  • sha256_cert_fingerprints:应用签名证书的 SHA256 指纹。您可以使用以下命令通过 Java keytool 生成指纹
    keytool -list -v -keystore my-release-key.keystore
    
    此字段支持多个指纹,可用于支持应用的不同版本,例如调试版本和生产版本。

    如果您正在使用Play 应用签名,则本地运行keytool生成的证书指纹通常与用户设备上的指纹不匹配。您可以在Play Console开发者帐号的发行版 > 设置 > 应用签名下验证您的应用是否使用了 Play 应用签名;如果使用了,您还可以在同一页面上找到应用的正确数字资产链接 JSON 代码片段。

以下示例assetlinks.json文件授予com.example Android 应用链接打开权限

[{
  "relation": ["delegate_permission/common.handle_all_urls"],
  "target": {
    "namespace": "android_app",
    "package_name": "com.example",
    "sha256_cert_fingerprints":
    ["14:6D:E9:83:C5:73:06:50:D8:EE:B9:95:2F:34:FC:64:16:A0:83:42:E6:1D:BE:A8:8A:04:96:B2:3F:CF:44:E5"]
  }
}]

将网站与多个应用关联

网站可以在同一assetlinks.json文件中声明与多个应用的关联。以下文件列表显示了一个声明语句文件的示例,该文件分别声明了与两个应用的关联,并位于https://www.example.com/.well-known/assetlinks.json

[{
  "relation": ["delegate_permission/common.handle_all_urls"],
  "target": {
    "namespace": "android_app",
    "package_name": "com.example.puppies.app",
    "sha256_cert_fingerprints":
    ["14:6D:E9:83:C5:73:06:50:D8:EE:B9:95:2F:34:FC:64:16:A0:83:42:E6:1D:BE:A8:8A:04:96:B2:3F:CF:44:E5"]
  }
  },
  {
  "relation": ["delegate_permission/common.handle_all_urls"],
  "target": {
    "namespace": "android_app",
    "package_name": "com.example.monkeys.app",
    "sha256_cert_fingerprints":
    ["14:6D:E9:83:C5:73:06:50:D8:EE:B9:95:2F:34:FC:64:16:A0:83:42:E6:1D:BE:A8:8A:04:96:B2:3F:CF:44:E5"]
  }
}]

不同的应用可以处理同一 Web 主机下不同资源的链接。例如,app1 可以为https://example.com/articles声明意图过滤器,而 app2 可以为https://example.com/videos声明意图过滤器。

注意:与同一域名关联的多个应用可以使用相同或不同的证书进行签名。

将多个网站与单个应用关联

多个网站可以在各自的assetlinks.json文件中声明与同一应用的关联。以下文件列表显示了如何声明 example.com 和 example.net 与 app1 的关联的示例。第一个列表显示了 example.com 与 app1 的关联

https://www.example.com/.well-known/assetlinks.json

[{
  "relation": ["delegate_permission/common.handle_all_urls"],
  "target": {
    "namespace": "android_app",
    "package_name": "com.mycompany.app1",
    "sha256_cert_fingerprints":
    ["14:6D:E9:83:C5:73:06:50:D8:EE:B9:95:2F:34:FC:64:16:A0:83:42:E6:1D:BE:A8:8A:04:96:B2:3F:CF:44:E5"]
  }
}]

下一个列表显示了 example.net 与 app1 的关联。只有这些文件托管的位置不同(.com.net

https://www.example.net/.well-known/assetlinks.json

[{
  "relation": ["delegate_permission/common.handle_all_urls"],
  "target": {
    "namespace": "android_app",
    "package_name": "com.mycompany.app1",
    "sha256_cert_fingerprints":
    ["14:6D:E9:83:C5:73:06:50:D8:EE:B9:95:2F:34:FC:64:16:A0:83:42:E6:1D:BE:A8:8A:04:96:B2:3F:CF:44:E5"]
  }
}]

发布 JSON 验证文件

您必须在以下位置发布您的 JSON 验证文件

https://domain.name/.well-known/assetlinks.json

请确保以下几点

  • assetlinks.json文件使用内容类型application/json提供服务。
  • 无论您的应用意图过滤器是否将 HTTPS 声明为数据方案,assetlinks.json文件都必须可以通过 HTTPS 连接访问。
  • assetlinks.json文件必须可以直接访问,无需任何重定向(无 301 或 302 重定向)。
  • 如果您的应用链接支持多个主机域名,则必须在每个域名上发布assetlinks.json文件。请参阅支持多个主机的应用链接
  • 请勿在清单文件中发布可能无法供公众访问的应用(例如,只能通过 VPN 访问的应用)的开发/测试 URL。在这种情况下,一种解决方法是配置构建变体以生成不同的清单文件用于开发构建。

Android 应用链接验证

当您的应用的至少一个意图过滤器中存在android:autoVerify="true"时,在运行 Android 6.0(API 级别 23)或更高版本的设备上安装您的应用会导致系统自动验证与应用意图过滤器中的 URL 关联的主机。在 Android 12 及更高版本上,您还可以手动调用验证过程来测试验证逻辑。

自动验证

系统的自动验证涉及以下步骤

  1. 系统会检查包含以下任何内容的所有意图过滤器:
    • 操作:android.intent.action.VIEW
    • 类别:android.intent.category.BROWSABLEandroid.intent.category.DEFAULT
    • 数据方案:httphttps
  2. 对于在上述意图过滤器中找到的每个唯一主机名,Android 会查询相应网站上的https://hostname/.well-known/assetlinks.json处的数字资产链接文件。

确认要与您的应用关联的网站列表以及托管的 JSON 文件有效后,将应用安装到您的设备上。等待至少 20 秒才能完成异步验证过程。使用以下命令检查系统是否已验证您的应用并设置了正确的链接处理策略

adb shell am start -a android.intent.action.VIEW \
    -c android.intent.category.BROWSABLE \
    -d "http://domain.name:optional_port"

手动验证

从 Android 12 开始,您可以手动调用已安装在设备上的应用的域名验证。无论您的应用是否面向 Android 12,都可以执行此过程。

建立互联网连接

要执行域名验证,您的测试设备必须连接到互联网。

支持更新的域名验证过程

如果您的应用面向 Android 12 或更高版本,则系统会自动使用更新的域名验证过程。

否则,您可以手动启用更新的验证过程。为此,请在终端窗口中运行以下命令

adb shell am compat enable 175408749 PACKAGE_NAME

重置设备上的 Android 应用链接状态

在手动调用设备上的域名验证之前,必须重置测试设备上的 Android 应用链接状态。为此,请在终端窗口中运行以下命令

adb shell pm set-app-links --package PACKAGE_NAME 0 all

此命令将设备置于用户尚未为任何域名选择默认应用之前的相同状态。

调用域名验证过程

重置设备上的 Android 应用链接状态后,您可以执行验证本身。为此,请在终端窗口中运行以下命令

adb shell pm verify-app-links --re-verify PACKAGE_NAME

查看验证结果

在允许验证代理完成其请求后,查看验证结果。为此,请运行以下命令

adb shell pm get-app-links PACKAGE_NAME

此命令的输出类似于以下内容

com.example.pkg:
    ID: 01234567-89ab-cdef-0123-456789abcdef
    Signatures: [***]
    Domain verification state:
      example.com: verified
      sub.example.com: legacy_failure
      example.net: verified
      example.org: 1026

成功通过验证的域的域名验证状态为verified。任何其他状态都表示无法执行域名验证。特别是,状态none表示验证代理可能尚未完成验证过程。

以下列表显示了域名验证可以为给定域名返回的可能返回值

none
此域名没有任何记录。等待几分钟,让验证代理完成与域名验证相关的请求,然后再次调用域名验证过程
verified
已成功验证声明应用的域名。
approved
该域名已强制批准,通常是通过执行 shell 命令。
denied
该域名已被强制拒绝,通常是通过执行 shell 命令。
migrated
系统保留了使用旧版域名验证的先前过程的结果。
restored
用户执行数据恢复后,已批准该域名。假设该域名之前已验证。
legacy_failure
旧版验证器拒绝了该域名。未知具体的失败原因。
system_configured
设备配置自动批准了该域名。
错误代码为1024或更大

特定于设备验证器的自定义错误代码。

仔细检查您是否已建立网络连接,并再次调用域名验证过程

请求用户将您的应用与域名关联

您的应用获得域名批准的另一种方法是请求用户将您的应用与该域名关联。

检查您的应用是否已获得域名的批准

在提示用户之前,请检查您的应用是否是在 `<intent-filter> 元素中定义的域的默认处理程序。您可以使用以下方法之一查询批准状态

DomainVerificationManager

以下代码片段演示了如何使用 DomainVerificationManager API

Kotlin

val context: Context = TODO("Your activity or fragment's Context")
val manager = context.getSystemService(DomainVerificationManager::class.java)
val userState = manager.getDomainVerificationUserState(context.packageName)

// Domains that have passed Android App Links verification.
val verifiedDomains = userState?.hostToStateMap
    ?.filterValues { it == DomainVerificationUserState.DOMAIN_STATE_VERIFIED }

// Domains that haven't passed Android App Links verification but that the user
// has associated with an app.
val selectedDomains = userState?.hostToStateMap
    ?.filterValues { it == DomainVerificationUserState.DOMAIN_STATE_SELECTED }

// All other domains.
val unapprovedDomains = userState?.hostToStateMap
    ?.filterValues { it == DomainVerificationUserState.DOMAIN_STATE_NONE }

Java

Context context = TODO("Your activity or fragment's Context");
DomainVerificationManager manager =
        context.getSystemService(DomainVerificationManager.class);
DomainVerificationUserState userState =
        manager.getDomainVerificationUserState(context.getPackageName());

Map<String, Integer> hostToStateMap = userState.getHostToStateMap();
List<String> verifiedDomains = new ArrayList<>();
List<String> selectedDomains = new ArrayList<>();
List<String> unapprovedDomains = new ArrayList<>();
for (String key : hostToStateMap.keySet()) {
    Integer stateValue = hostToStateMap.get(key);
    if (stateValue == DomainVerificationUserState.DOMAIN_STATE_VERIFIED) {
        // Domain has passed Android App Links verification.
        verifiedDomains.add(key);
    } else if (stateValue == DomainVerificationUserState.DOMAIN_STATE_SELECTED) {
        // Domain hasn't passed Android App Links verification, but the user has
        // associated it with an app.
        selectedDomains.add(key);
    } else {
        // All other domains.
        unapprovedDomains.add(key);
    }
}

命令行程序

在开发过程中测试应用时,您可以运行以下命令来查询组织拥有的域的验证状态

adb shell pm get-app-links --user cur PACKAGE_NAME

在以下示例输出中,即使应用未通过“example.org”域的验证,用户 0 也已在系统设置中手动批准了该应用,并且没有其他软件包已通过该域的验证。

com.example.pkg:
ID: ***
Signatures: [***]
Domain verification state:
  example.com: verified
  example.net: verified
  example.org: 1026
User 0:
  Verification link handling allowed: true
  Selection state:
    Enabled:
      example.org
    Disabled:
      example.com
      example.net

您还可以使用 shell 命令来模拟用户选择哪个应用与给定域名关联的过程。这些命令的完整解释可在 adb shell pm 的输出中找到。

提供请求上下文

在发出域名批准请求之前,请为用户提供一些上下文。例如,您可以向他们显示启动画面、对话框或类似的 UI 元素,向用户解释为什么您的应用应该是特定域的默认处理程序。

发出请求

在用户理解您的应用请求他们执行的操作后,发出请求。为此,调用包含 ACTION_APP_OPEN_BY_DEFAULT_SETTINGS intent 操作和与目标应用匹配的 package:com.example.pkg 数据字符串的 intent,如下面的代码片段所示

Kotlin

val context: Context = TODO("Your activity or fragment's Context")
val intent = Intent(Settings.ACTION_APP_OPEN_BY_DEFAULT_SETTINGS,
    Uri.parse("package:${context.packageName}"))
context.startActivity(intent)

Java

Context context = TODO("Your activity or fragment's Context");
Intent intent = new Intent(Settings.ACTION_APP_OPEN_BY_DEFAULT_SETTINGS,
    Uri.parse("package:" + context.getPackageName()));
context.startActivity(intent);

调用 intent 后,用户会看到一个名为“默认打开”的设置屏幕。此屏幕包含一个名为“打开支持的链接”的单选按钮,如图 1 所示。

当用户打开“打开支持的链接”时,一组复选框会出现在名为“在此应用中打开的链接”的部分下。在这里,用户可以选择他们想要与您的应用关联的域名。他们还可以选择“添加链接”来添加域名,如图 2 所示。当用户稍后选择他们添加的域名内的任何链接时,该链接会自动在您的应用中打开。

When the radio button is enabled, a section near the bottom
    includes checkboxes as well as a button called 'Add link'
图 1. 用户可以在其中选择哪些链接默认在您的应用中打开的系统设置屏幕。
Each checkbox represents a domain that you can add. The
    dialog's buttons are 'Cancel' and 'Add.'
图 2. 用户可以在其中选择要与您的应用关联的其他域的对话框。

在您的应用中打开您的应用无法验证的域名

您的应用的主要功能可能是作为第三方打开链接,而无法验证其处理的域名。如果是这种情况,请向用户解释,当他们选择网页链接时,他们无法在第一方应用和您的(第三方)应用之间进行选择。用户需要手动将域名与您的第三方应用关联。

此外,请考虑引入一个对话框或跳板活动,以便用户可以选择在第一方应用中打开链接(如果用户更倾向于这样做),充当代理。在设置此类对话框或跳板活动之前,请设置您的应用,使其具有对与您的应用的网页 intent 过滤器匹配的第一方应用的 包可见性

测试应用链接

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

要测试现有的声明文件,您可以使用 声明列表生成器和测试器 工具。

确认要验证的主机列表

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

  • android:scheme 属性,其值为 httphttps
  • android:host 属性,其值为域名 URL 模式
  • android.intent.action.VIEW 操作元素
  • android.intent.category.BROWSABLE 类别元素

使用此列表检查每个命名主机和子域上是否提供了数字资产链接 JSON 文件。

确认数字资产链接文件

对于每个网站,使用数字资产链接 API 确认数字资产链接 JSON 文件是否已正确托管和定义

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

作为测试过程的一部分,您可以检查链接处理的当前系统设置。使用以下命令获取连接设备上所有应用的现有链接处理策略列表

adb shell dumpsys package domain-preferred-apps

或者以下命令执行相同的操作

adb shell dumpsys package d

注意:请确保在安装应用后至少等待 20 秒,以允许系统完成验证过程。

该命令返回设备上定义的每个用户或配置文件的列表,前面带有以下格式的标题

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 过滤器中指定的每个网站验证您的应用。以下示例显示了定义了多个应用链接的清单配置

<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" />
            <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 应用链接,请检查以下常见错误。本节使用 example.com 作为占位符域名;执行这些检查时,请将 example.com 替换为服务器的实际域名。

不正确的 intent 过滤器设置
检查您是否在 `<intent-filter> 元素中包含您的应用不拥有的 URL。
不正确的服务器配置

检查服务器的 JSON 配置,并确保 SHA 值正确。

此外,请检查 example.com.(带尾部句点)是否提供与 example.com 相同的内容。

服务器端重定向

如果您设置了以下重定向,则系统将不会验证您的应用的任何 Android 应用链接

  • http://example.com 重定向到 https://example.com
  • example.com 重定向到 www.example.com

此行为可保护您的应用安全。

服务器稳健性

检查您的服务器是否可以连接到您的客户端应用。

不可验证的链接

出于测试目的,您可能会故意添加不可验证的链接。请记住,在 Android 11 及更低版本上,这些链接会导致系统不验证您的应用的所有 Android 应用链接。

assetlinks.json 中的签名不正确

验证您的签名是否正确,并与用于签署您的应用的签名匹配。常见的错误包括:

  • 使用调试证书签署应用,并且 assetlinks.json 中只有发行版签名。
  • assetlinks.json 中的签名为小写。签名应为大写。
  • 如果您使用 Play 应用签名,请确保您使用的是 Google 用于签署每个发行版的签名。您可以按照有关 声明网站关联 的说明验证这些详细信息,包括完整的 JSON 代码片段。