验证 Android 应用链接

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

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

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

  2. 声明您的网站和 Intent 过滤器之间的关联,方法是在以下位置托管 Digital Asset Links JSON 文件

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

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

为应用链接验证添加 Intent 过滤器

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

<!-- 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". -->
    <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 或更高版本的应用验证域。

支持多个主机上的应用链接

系统必须能够将应用的 URL 意图过滤器数据元素中指定的主机,与该意图过滤器中相应 Web 域上托管的数字资产链接文件进行验证。如果验证失败,系统将默认为其标准行为来解析意图,如创建指向应用内容的深层链接中所述。但是,应用仍然可以被验证为应用其他意图过滤器中定义的任何 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>元素将合并在一起,以考虑其组合属性的所有变体。例如,上面的第一个意图过滤器包含一个仅声明 HTTPS 方案的<data>元素。但它与另一个<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文件。例如,只要assetlinks.json文件发布在https://example.com/.well-known/assetlinks.json处,具有以下意图过滤器的应用将通过example.com(例如foo.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="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提供服务。
  • assetlinks.json文件必须通过 HTTPS 连接访问,无论您的应用意图过滤器是否将 HTTPS 声明为数据方案。
  • assetlinks.json文件必须能够访问,且无需任何重定向(无 301 或 302 重定向)。
  • 如果您的应用链接支持多个主机域,则必须在每个域上发布assetlinks.json文件。请参阅支持多个主机上的应用链接
  • 不要在清单文件中发布应用的开发/测试 URL,这些 URL 可能无法供公众访问(例如,仅可以通过 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意图操作,以及与目标应用匹配的package:com.example.pkg数据字符串,如以下代码片段所示

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

调用意图后,用户会看到一个名为“默认打开”的设置屏幕。此屏幕包含一个名为“打开支持的链接”的单选按钮,如图 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. 用户可以在其中选择其他要与您的应用关联的域名的对话框。

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

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

此外,请考虑引入一个对话框或跳板活动,以便用户可以在用户首选的情况下在第一方应用中打开链接,充当代理。在设置此类对话框或跳板活动之前,请设置您的应用,使其对与您的应用的网络意图过滤器匹配的第一方应用具有软件包可见性

测试应用链接

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

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

确认要验证的主机列表

在测试期间,您应该确认系统应为您的应用验证的相关主机列表。列出所有 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 系统对用户应用链接首选项的记录相关。此值不指示验证是否成功。

注意:如果用户在验证完成之前更改了应用的链接设置,您可能会看到成功验证的误报,即使验证失败也是如此。但是,如果用户在未询问的情况下显式启用应用以打开支持的链接,则此验证失败无关紧要。这是因为用户首选项优先于程序化验证(或缺乏验证)。因此,链接会直接转到您的应用,而不会显示对话框,就像验证已成功一样。

测试示例

要使应用链接验证成功,系统必须能够使用您在满足应用链接条件的给定意图过滤器中指定的每个网站来验证您的应用。以下示例显示了定义了多个应用链接的清单配置

<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-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 代码段。