深层链接合成返回栈配方
此方案演示了如何通过管理合成的 backStack 和任务堆栈,在深层链接的上下文中应用导航原则。
食谱结构
此配方模拟了“应用 A”深层链接到“应用 B”的实际应用场景。
模块 syntheticbackstack 用于模拟“应用 A”,其中包含 SyntheticBackStackDeepLinkActivity,可让您创建深层链接 intent,并在现有任务或新任务中触发该 intent。
模块 syntheticbackstackapp 会模拟“应用 B”,其中包含您要深层链接到的 SyntheticBackStackAppActivity。该模块介绍了如何构建合成的返回栈,以及如何正确管理任务栈,以同时支持“返回”和“向上”按钮。
使用方法
确保模拟器或已连接的设备上安装了主 app 和 syntheticbackstackapp。确保已安装的 syntheticbackstackapp 支持 "www.nav3deeplink.com" 链接。
在食谱的着陆页上,选择过滤条件,然后点击按钮以进行深层链接。这应该会带您前往 syntheticbackstackapp 的 activity。
具体用法
该配方遵循了此处总结的深层链接指南。
如需查看 Existing Task 的行为,请执行以下操作:
- 使用当前任务打开深层链接
- 在设备上,向上滑动即可查看所有最近用过的应用
- 请注意,新 activity 会在 Nav3Recipes 应用中打开
- 点击返回按钮,返回到原始 Activity
- 重复第 1 步
- 点击向上按钮可前往父屏幕
- 在设备上,向上滑动即可查看所有最近用过的应用
- 请注意,新 activity 现在已在 Nav3SyntheticBackStack 应用中打开
如需查看 New Task 的行为,请执行以下操作:
- 使用新任务打开深层链接
- 在设备上,向上滑动即可查看所有最近用过的应用
- 请注意,新 activity 在 Nav3SyntheticBackStack 应用中打开
- 点击“向上”或“返回”按钮前往父界面
核心实现
有关 navigateUp 和构建合成 backStack 的核心辅助函数可在此处找到
进一步阅读
如需获取有关深层链接原则以及如何在 Navigation 3 中应用这些原则的全面指南,请查看深层链接指南。
package com.example.nav3recipes.deeplink.handlerequests.syntheticbackstack import android.content.Intent import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.core.net.toUri import androidx.lifecycle.compose.dropUnlessResumed import com.example.nav3recipes.common.deeplink.EntryScreen import com.example.nav3recipes.common.deeplink.LIST_FIRST_NAMES import com.example.nav3recipes.common.deeplink.LIST_LOCATIONS import com.example.nav3recipes.common.deeplink.MenuDropDown import com.example.nav3recipes.common.deeplink.PaddedButton import com.example.nav3recipes.common.deeplink.TextContent import com.example.nav3recipes.ui.setEdgeToEdgeConfig internal const val ADVANCED_PATH_BASE = "https://www.nav3deeplink.com" /** * The recipe entry point that allows users to create a deep link and make a request with it. * * **HOW THIS RECIPE WORKS** This recipe simulates a real-world scenario where "App A" deep links * into "App B". * * "App A" is simulated by this current module `syntheticbackstack`, which * contains the [SyntheticBackStackDeepLinkActivity] that allows you to create a deeplink intent and * trigger that in either the existing Task, or in a new Task. * * "App B" is simulated by the module `syntheticbackstackapp`, which contains * the SyntheticBackStackAppActivity that you deeplink into. That module shows you how to build a synthetic backStack * and how to manage the Task stack properly in order to support both Back and Up buttons. * * See the [README](README.md) file of current module for more info on advanced deep linking. */ class SyntheticBackStackDeepLinkActivity: ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { setEdgeToEdgeConfig() super.onCreate(savedInstanceState) setContent { EntryScreen("Sandbox - Build Your Deeplink Intent") { val initFirstName = MENU_OPTIONS_FIRST_NAME.values.first().first() val initLocation = MENU_OPTIONS_LOCATION.values.last().first() val initTaskStack = MENU_OPTIONS_TASK_STACK.values.first().first() var firstName by remember { mutableStateOf(initFirstName) } var location by remember { mutableStateOf(initLocation) } var taskStack by remember { mutableStateOf(initTaskStack) } // select first name MenuDropDown( menuOptions = MENU_OPTIONS_FIRST_NAME, ) { _, selected -> firstName = selected } // select first name MenuDropDown( menuOptions = MENU_OPTIONS_LOCATION, ) { _, selected -> location = selected } // select current task stack or build new task stack MenuDropDown( menuOptions = MENU_OPTIONS_TASK_STACK, ) { _, selected -> taskStack = selected } // build final deeplink URL and Intent val finalUrl = "${ADVANCED_PATH_BASE}/user/$firstName/$location" // display Intent info val flagString = if (taskStack == TAG_NEW_TASK) { "Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK" } else "<none>" val intentString = """ | Final Intent: | data = "$finalUrl" | action = Intent.ACTION_VIEW | flags = $flagString """.trimMargin() TextContent(intentString) // deeplink to target PaddedButton("Deeplink Away!", onClick = dropUnlessResumed { val intent = Intent().apply { data = finalUrl.toUri() action = Intent.ACTION_VIEW if (taskStack == TAG_NEW_TASK) { flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK } } startActivity(intent) }) } } } } private const val TAG_FIRST_NAME = "firstName" private const val TAG_LOCATION = "location" private const val TAG_TASK_STACK = "Task stack" private const val TAG_CURRENT_TASK = "Use Current Task Stack" private const val TAG_NEW_TASK = "Start New Task Stack" private val MENU_OPTIONS_FIRST_NAME = mapOf( TAG_FIRST_NAME to LIST_FIRST_NAMES ) private val MENU_OPTIONS_LOCATION = mapOf( TAG_LOCATION to LIST_LOCATIONS ) private val MENU_OPTIONS_TASK_STACK = mapOf( TAG_TASK_STACK to listOf(TAG_CURRENT_TASK, TAG_NEW_TASK), )