为目标创建深度链接

在Android中,深度链接是指将您直接带到应用内特定目标的链接。

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

创建显式深度链接

一个显式深度链接是深度链接的单个实例,它使用PendingIntent将用户带到应用内的特定位置。例如,您可能会将显式深度链接作为通知或应用小部件的一部分显示。

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

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

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 位于另一个活动中,则在创建深层链接构建器时必须指定其组件名称。

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、意图操作和 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. 在导航编辑器的“设计”选项卡中,选择深层链接的目标位置。
  2. 点击“属性”面板的“深层链接”部分中的“+”。
  3. 在出现的“添加深层链接”对话框中,输入深层链接的信息。

    请注意以下事项:

    • 没有方案的 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
    • 为使用默认值或可空值定义的变量定义的查询参数占位符不需要匹配。例如,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,即使 URI 模式中未定义 extraneousParam
  4. (可选)选中“自动验证”以要求 Google 验证您是 URI 的所有者。有关更多信息,请参阅 验证 Android 应用链接

  5. 点击“添加”。选定目标位置上方会出现一个链接图标 ,以指示该目标位置具有深层链接。

  6. 点击“代码”选项卡以切换到 XML 视图。嵌套的 <deepLink> 元素已添加到目标位置。

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

要启用隐式深层链接,您还必须对应用程序的 manifest.xml 文件进行添加。将单个 <nav-graph> 元素添加到指向现有导航图的活动中,如下例所示。

<?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> 元素的起始目标位置)添加到栈中。这意味着,当用户从深层链接目标位置按“后退”按钮时,他们会像从入口点进入应用程序一样,向上导航到导航栈。
  • 如果未设置该标志,则您将停留在触发隐式深层链接的先前应用程序的任务栈中。在这种情况下,“后退”按钮将带您返回到先前应用程序,而“向上”按钮将在导航图中启动应用程序任务的层次结构父目标位置。

处理深层链接

强烈建议在使用导航时始终使用默认的 launchMode standard。使用 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

视频