为目标位置创建深层链接

在 Android 中,深层链接是一种可直接将用户引导至应用内特定目标位置的链接。

导航组件允许您创建两种不同类型的深层链接:显式隐式

创建显式深层链接

一个显式深层链接是深层链接的一个单一实例,它使用 PendingIntent 将用户引导至应用内的特定位置。例如,您可以在通知或应用微件中显示显式深层链接。

当用户通过显式深层链接打开您的应用时,任务返回堆栈会被清除,并替换为深层链接目标位置。当嵌套图时,每个嵌套层级的起始目标位置(即层次结构中每个<navigation>元素的起始目标位置)也会添加到堆栈中。这意味着当用户从深层链接目标位置按下返回按钮时,他们会像从应用入口点进入应用一样,沿导航堆栈返回。

您可以使用 NavDeepLinkBuilder 类来构建 PendingIntent,如以下示例所示。请注意,如果提供的上下文不是 Activity,则构造函数会使用 PackageManager.getLaunchIntentForPackage() 作为要启动的默认 Activity(如果可用)。

Kotlin

val pendingIntent = NavDeepLinkBuilder(context)
    .setGraph(R.navigation.nav_graph)
    .setDestination(R.id.android)
    .setArguments(args)
    .createPendingIntent()

Java

PendingIntent pendingIntent = new NavDeepLinkBuilder(context)
    .setGraph(R.navigation.nav_graph)
    .setDestination(R.id.android)
    .setArguments(args)
    .createPendingIntent();

默认情况下,NavDeepLinkBuilder 会将您的显式深层链接启动到在应用清单中声明的默认启动 Activity 中。如果您的 NavHost 位于另一个 Activity 中,则在创建深层链接构建器时,您必须指定其组件名称

Kotlin

val pendingIntent = NavDeepLinkBuilder(context)
    .setGraph(R.navigation.nav_graph)
    .setDestination(R.id.android)
    .setArguments(args)
    .setComponentName(DestinationActivity::class.java)
    .createPendingIntent()

Java

PendingIntent pendingIntent = new NavDeepLinkBuilder(context)
        .setGraph(R.navigation.nav_graph)
        .setDestination(R.id.android)
        .setArguments(args)
        .setComponentName(DestinationActivity.class)
        .createPendingIntent();

如果您有 ComponentName,则可以直接将其传递给构建器

Kotlin

val componentName = ...

val pendingIntent = NavDeepLinkBuilder(context)
    .setGraph(R.navigation.nav_graph)
    .setDestination(R.id.android)
    .setArguments(args)
    .setComponentName(componentName)
    .createPendingIntent()

Java

ComponentName componentName = ...;

PendingIntent pendingIntent = new NavDeepLinkBuilder(context)
        .setGraph(R.navigation.nav_graph)
        .setDestination(R.id.android)
        .setArguments(args)
        .setComponentName(componentName)
        .createPendingIntent();

如果您有现有的 NavController,则也可以通过使用 NavController.createDeepLink() 来创建深层链接。

创建隐式深层链接

一个隐式深层链接是指向应用中特定目标位置的链接。当深层链接被调用时(例如,当用户点击链接时),Android 就可以打开您的应用并跳转到相应的目标位置。

深层链接可以通过 URI、Intent 操作和 MIME 类型进行匹配。您可以为单个深层链接指定多种匹配类型,但请注意,URI 参数匹配优先级最高,其次是操作,然后是 MIME 类型。

以下是包含 URI、操作和 MIME 类型的深层链接示例

<fragment android:id="@+id/a"
          android:name="com.example.myapplication.FragmentA"
          tools:layout="@layout/a">
        <deepLink app:uri="www.example.com"
                app:action="android.intent.action.MY_ACTION"
                app:mimeType="type/subtype"/>
</fragment>

您也可以使用导航编辑器按以下步骤为目标位置创建隐式深层链接

  1. 在导航编辑器的 Design(设计)标签页中,选择深层链接的目标位置。
  2. 点击 Attributes(属性)面板的 Deep Links(深层链接)部分中的 +
  3. 在随即显示的 Add Deep Link(添加深层链接)对话框中,输入您的深层链接信息。

    请注意以下几点

    • 没有方案的 URI 会被假定为 http 或 https。例如,www.google.com 会同时匹配 http://www.google.comhttps://www.google.com
    • 路径参数占位符(形式为 {placeholder_name})匹配一个或多个字符。例如,http://www.example.com/users/{id} 会匹配 http://www.example.com/users/4。导航组件会尝试通过将占位符名称与为深层链接目标位置定义的参数进行匹配,将占位符值解析为相应的类型。如果未定义同名参数,则参数值会使用默认的 String 类型。您可以使用 .* 通配符来匹配 0 个或更多字符。
    • 查询参数占位符可替代路径参数使用,也可与路径参数结合使用。例如,http://www.example.com/users/{id}?myarg={myarg} 会匹配 http://www.example.com/users/4?myarg=28
    • 对于使用默认值或可为 null 值定义的变量,查询参数占位符不需要匹配。例如,http://www.example.com/users/{id}?arg1={arg1}&arg2={arg2} 会匹配 http://www.example.com/users/4?arg2=28http://www.example.com/users/4?arg1=7。路径参数则不然。例如,http://www.example.com/users?arg1=7&arg2=28 不会匹配上述模式,因为未提供所需的路径参数。
    • 无关的查询参数不会影响深层链接 URI 匹配。例如,http://www.example.com/users/{id} 会匹配 http://www.example.com/users/4?extraneousParam=7,即使 extraneousParam 未在 URI 模式中定义。
  4. (可选)选中 Auto Verify(自动验证)以要求 Google 验证您是 URI 的所有者。如需了解详情,请参阅验证 Android 应用链接

  5. 点击 Add(添加)。所选目标位置上方会显示一个链接图标 ,表示该目标位置有深层链接。

  6. 点击 Code(代码)标签页以切换到 XML 视图。一个嵌套的 <deepLink> 元素已添加到目标位置

    <deepLink app:uri="https://www.google.com" />
    

要启用隐式深层链接,您还必须修改应用的 manifest.xml 文件。将一个 <nav-graph> 元素添加到指向现有导航图的 Activity 中,如以下示例所示

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.myapplication">

    <application ... >

        <activity name=".MainActivity" ...>
            ...

            <nav-graph android:value="@navigation/nav_graph" />

            ...

        </activity>
    </application>
</manifest>

构建项目时,导航组件会将 <nav-graph> 元素替换为生成的 <intent-filter> 元素,以匹配导航图中的所有深层链接。

触发隐式深层链接时,返回堆栈的状态取决于隐式 Intent 是否使用 Intent.FLAG_ACTIVITY_NEW_TASK 标志启动

  • 如果设置了该标志,则任务返回堆栈会被清除,并替换为深层链接目标位置。与显式深层链接一样,当嵌套图时,每个嵌套层级的起始目标位置(即层次结构中每个 <navigation> 元素的起始目标位置)也会添加到堆栈中。这意味着当用户从深层链接目标位置按下返回按钮时,他们会像从应用入口点进入应用一样,沿导航堆栈返回。
  • 如果未设置该标志,您将停留在触发隐式深层链接的先前应用的返回堆栈中。在此情况下,返回按钮会将您带回上一个应用,而向上按钮则会在您的导航图内的分层父目标位置启动您的应用任务。

处理深层链接

强烈建议在使用导航时始终使用默认的 standard launchMode。在使用 standard 启动模式时,导航组件会通过调用 handleDeepLink() 自动处理深层链接,以处理 Intent 中的所有显式或隐式深层链接。但是,如果在使用备用 launchMode(例如 singleTop)时 Activity 被重复使用,则不会自动发生此情况。在这种情况下,有必要在 onNewIntent() 中手动调用 handleDeepLink(),如以下示例所示

Kotlin

override fun onNewIntent(intent: Intent?) {
    super.onNewIntent(intent)
    navController.handleDeepLink(intent)
}

Java

@Override
protected void onNewIntent(Intent intent) {
    super.onNewIntent(intent);
    navController.handleDeepLink(intent);
}

其他资源

要详细了解导航,请参阅以下资源。

Codelabs

视频