创建深层链接

借助深层链接,您可以将用户直接从网络浏览器、通知、社交媒体、广告和其他来源引导至您的应用。深层链接可实现直接的应用到应用和网站到应用过渡,有助于您通过情境化、有针对性的内容提高互动度。

本指南介绍了深层链接的工作原理,以及如何创建和测试指向您内容的深层链接。

对于引用您自己的网站或网域的深层链接,我们建议使用应用链接,以便为用户提供顺畅、可信的体验。

深层链接的工作原理

深层链接是 Android 的一般系统功能,在所有版本和所有设备上均受支持。它利用 Android 的 intent 系统将深层链接路由到感兴趣的应用。如果应用想要处理特定的深层链接 URI,则需要在其应用清单文件中声明匹配的 Intent 过滤器。

在运行时,当用户点按某个链接时,Android 会触发 intent 并尝试将其路由到某个应用。由于多个应用可以声明与给定 URI 匹配的 intent 过滤器,因此 Android 会按以下顺序执行这些操作来路由 intent:

  1. 如果用户指定了可以处理该 URI 的默认应用,就打开此应用。
  2. 打开唯一可以处理该 URI 的应用。
  3. 允许用户从消除歧义对话框中选择应用。

这意味着,即使您的 intent 过滤器与给定的 URI 相匹配,也无法保证系统会将深层链接 intent 路由到您的应用。用户在管理哪个应用处理 intent 方面发挥着关键作用,这让他们能够进行控制和选择。如需更好地控制指向您自己网站和网域的深层链接,请尝试使用 App Links。

借助 Android 的消除歧义对话框,用户可以查看已注册处理深层链接 intent 的所有已安装应用。用户还可以选择将某个应用设为此类链接的默认应用。用户设置默认应用后,系统将不再针对该特定 intent 显示对话框,而是会自动打开所选应用。

图 1. 消除歧义对话框

在不同 Android 版本中,消除歧义对话框的行为有所不同。 例如,在 Android 12 及更高版本中,未经验证的应用链接通常默认会在 Web 浏览器中打开,而在之前的版本中,如果某个应用可以处理相应网页链接,则可能会显示消除歧义对话框。

注意:从 Android 12(API 级别 31)开始,仅当您的应用获准处理某个通用网络 intent 中包含的特定网域时,该网络 intent 才会解析为应用中的 activity。如果您的应用未获准处理相应的网域,则该网络 intent 会解析为用户的默认浏览器应用。

深层链接的类型

您可以在 Android 上支持以下三种类型的深层链接:

  • 自定义深层链接:这类深层链接使用自定义 URI 架构(例如 example://products/123)将用户直接引导至应用内的特定内容。它们非常适合用于内部导航或您控制的来源中的链接,但它们不是标准 Web 链接,如果另一个应用注册了相同的自定义架构,它们仍可能会触发消除歧义对话框。
  • 网页链接:这些是使用标准 httphttps 架构的深层链接。它们是标准网址,因此用途更广泛,但在 Android 12 及更高版本中,它们几乎总是会触发消除歧义对话框,这意味着它们很可能会默认由用户的网络浏览器处理,而不是路由到您的应用。
  • 应用链接:自 Android 6.0(API 级别 23)起提供,是经过验证的网页链接。通过网站关联流程,您可以向 Android 系统证明您拥有相应网域。验证通过后,系统会自动将相应网域的链接直接路由到您的应用,完全跳过消除歧义对话框。这样可以为用户打造值得信赖的顺畅体验。

为传入链接添加 intent 过滤器

如需创建指向您应用内容的链接,请在清单中添加一个包含以下元素和属性值的 intent 过滤器:

<action>

指定 ACTION_VIEW intent 操作,以便能够从 Google 搜索中访问此 intent 过滤器。

<data>

添加一个或多个 <data> 标记,每个标记都代表一个解析为 activity 的 URI 格式。<data> 标记必须至少包含 android:scheme 属性。

您可以添加更多属性,以进一步细化 activity 接受的 URI 类型。例如,您可能拥有多个接受相似 URI 的 activity,这些 URI 只是路径名称有所不同。在这种情况下,请使用 android:path 属性或其 pathPatternpathPrefix 变体区分系统应针对不同 URI 路径打开哪个 activity。

<category>

包含 BROWSABLE 类别。如果要从网络浏览器中访问 intent 过滤器,就必须提供该类别。否则,在浏览器中点击链接便无法解析为您的应用。

此外,还要包含 DEFAULT 类别。这样您的应用才可以响应隐式 intent。否则,只有在 intent 指定您的应用组件名称时,Activity 才能启动。

以下 XML 代码段展示了如何在清单中为深层链接指定 intent 过滤器。URI "example://gizmos""http://www.example.com/gizmos" 都会解析到此 activity。

<activity
    android:name="com.example.android.GizmosActivity"
    android:label="@string/title_gizmos" >
    <intent-filter android:label="@string/filter_view_http_gizmos">
        <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://www.example.com/gizmos” -->
        <data android:scheme="http"
              android:host="www.example.com"
              android:pathPrefix="/gizmos" />
        <!-- note that the leading "/" is required for pathPrefix-->
    </intent-filter>
    <intent-filter android:label="@string/filter_view_example_gizmos">
        <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>
</activity>

请注意,<data> 元素是这两个 intent 过滤器的唯一区别。虽然可以在同一过滤器中包含多个 <data> 元素,但如果您打算声明唯一的网址(例如 schemehost 的特定组合),请务必创建单独的过滤器,因为同一 intent 过滤器中的多个 <data> 元素实际上会合并在一起,以涵盖合并后属性的所有变体。例如,请考虑以下情况:

<intent-filter>
  ...
  <data android:scheme="https" android:host="www.example.com" />
  <data android:scheme="app" android:host="open.my.app" />
</intent-filter>

看起来这似乎仅支持 https://www.example.comapp://open.my.app。但是,实际上除了这两种之外,它还支持 app://www.example.comhttps://open.my.app

注意:如果多个 activity 包含可解析为同一已验证 Android 应用链接的 intent 过滤器,则无法保证哪个 activity 会处理该链接。

当您向应用清单添加包含 activity 内容 URI 的 intent 过滤器后,Android 可以在运行时将所有包含匹配 URI 的 Intent 转发到您的应用。

如需详细了解如何定义 intent 过滤器,请参阅允许其他应用启动您的 activity

读取传入 intent 中的数据

在系统通过 intent 过滤器启动您的 activity 后,您可以根据 Intent 提供的数据确定需要呈现的内容。调用 getData()getAction() 方法检索与传入 Intent 相关联的数据和操作。您可以在 activity 生命周期的任何时间调用这些方法,但通常应在早期回调(例如 onCreate()onStart)时调用。

以下代码段展示了如何从 Intent 中检索数据:

Kotlin

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.main)

    val action: String? = intent?.action
    val data: Uri? = intent?.data
}

Java

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    Intent intent = getIntent();
    String action = intent.getAction();
    Uri data = intent.getData();
}

请遵循以下最佳做法以改进用户体验:

  • 深层链接应该将用户直接转到相应内容,而不会出现任何提示、转到任何插页式网页或登录页。请确保用户即使之前从未打开过相应应用,也可以查看应用内容。您可以在后续互动中或在用户从启动器中打开应用时进行提示。
  • 遵循使用“返回”和“向上”导航中所述的设计指南,确保您的应用能达到用户通过深层链接进入您的应用后对向后导航体验的预期。

测试深层链接

您可以将 Android 调试桥与 activity 管理器 (am) 工具结合使用,以测试您为深层链接指定的 intent 过滤器 URI 是否可以解析为正确的应用 activity。您可以针对设备或模拟器运行 adb 命令。

使用 adb 测试 intent 过滤器 URI 的一般语法为:

$ adb shell am start
        -W -a android.intent.action.VIEW
        -d <URI> <PACKAGE>

例如,以下命令试图查看与指定 URI 相关的目标应用 activity。

$ adb shell am start
        -W -a android.intent.action.VIEW
        -d "example://gizmos" com.example.android

注意:在路线中定义原始类型集合(例如 **@Serializable data class Product(val colors: List)**)时,自动生成的深层链接网址格式为 **basePath?colors={value**}。如果您尝试指定具有多个查询参数的 URI(例如 **basepath?colors=red&colors=blue**),则必须转义和号(例如 **basepath?colors=red\&colors=blue**)。

您设置的清单声明和 intent 处理程序可以定义您的应用与某网站之间的关联,以及如何处理传入链接。不过,为了让系统将您的应用视为某一组 URI 的默认处理程序,您还必须请求系统验证此关联。验证应用链接一文介绍了如何实现此验证。

如需详细了解 intent 和应用链接,请参阅以下资源: