You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android Compose Navigation如何正确传递URL类型参数?

Jetpack Compose Navigation传递Firebase邮箱认证链接时的截断问题

问题场景

我使用Jetpack Compose + Navigation开发Firebase邮箱链接认证功能:用户输入邮箱发起认证后,会收到包含认证链接的邮件,点击链接可通过Firebase Dynamic Link重新打开App。获取到emailLink后,尝试通过NavController的路由参数传递给Home页面,但出现参数被截断的问题。

出现问题的代码

动态链接处理代码

Firebase.dynamicLinks
    .getDynamicLink(intent)
    .addOnSuccessListener(this@MainActivity) { pendingDynamicLinkData: PendingDynamicLinkData? ->
        if (pendingDynamicLinkData != null) {
            val emailLink = intent?.data?.toString()
            if (emailLink != null && firebaseAuth.isSignInWithEmailLink(emailLink)) {
                intent = null
                navController.navigate("${Home.route}?emailLink={$emailLink}")
            }
        }
    }
}
NavHost(
    navController = navController,
    startDestination = Home.route,
) {
    composable(
        route = "${Home.route}?emailLink={emailLink}",
        arguments = listOf(navArgument("emailLink") {
            type = NavType.StringType
            nullable = true
            defaultValue = null
        })
    ) { backStackEntry ->
        val emailLink = backStackEntry.arguments?.getString("emailLink")
        Log.i("TEST", "[sample] navigate - emailLink: $emailLink")
        HomeScreen(
            vm = hiltViewModel(),
            emailLink = emailLink
        )
    }
}

问题现象

原始完整的emailLink:

https://email-link-auth-sample-95a4a.firebaseapp.com/__/auth/action?apiKey=AIzaSyD2w6bRHiqEXaSx9W0N5Mq5obydIjRk_mw&mode=signIn&oobCode=dj8M6b4Rq6dwM81ziExyw_3-gXiExQY8FvHNAZsPDxMAAAGETZgg0w&continueUrl=https://emaillinkauthsample.page.link&lang=en

通过backStackEntry.arguments?.getString("emailLink")获取到的内容却被截断为:

{https://email-link-auth-sample-95a4a.firebaseapp.com/__/auth/action?apiKey=AIzaSyD2w6bRHiqEXaSx9W0N5Mq5obydIjRk_mw

本质原因是Compose Navigation基于URL系统设计,当参数包含&、?这类URL特殊字符时,会导致参数解析出错,出现截断。

已实现的解决方案(使用savedStateHandle)

修改后的动态链接处理代码

Firebase.dynamicLinks
    .getDynamicLink(intent)
    .addOnSuccessListener(this@MainActivity) { pendingDynamicLinkData: PendingDynamicLinkData? ->
        if (pendingDynamicLinkData != null) {
            val emailLink = intent?.data?.toString()
            if (emailLink != null && firebaseAuth.isSignInWithEmailLink(emailLink)) {
                intent = null

                // 注释掉原路由参数传递方式
                // navController.navigate("${Home.route}?emailLink={$emailLink}")

                /**
                 * 使用savedStateHandle传递参数
                 */
                navController.currentBackStackEntry?.savedStateHandle?.apply {
                  set("emailLink", emailLink)
                }
                navController.navigate(Home.route)
            }
        }
    }
}

修改后的NavHost配置代码

NavHost(
    navController = navController,
    startDestination = Home.route,
) {
    composable(
        route = "${Home.route}?emailLink={emailLink}",
        arguments = listOf(navArgument("emailLink") {
            type = NavType.StringType
            nullable = true
            defaultValue = null
        })
    ) { backStackEntry ->
        // 注释掉原参数获取方式
        // val emailLink = backStackEntry.arguments?.getString("emailLink")

        /**
         * 从savedStateHandle获取参数
         */
        val emailLink = navController.previousBackStackEntry?.savedStateHandle?.get<String>("emailLink")
        HomeScreen(
            vm = hiltViewModel(),
            emailLink = emailLink
        )
    }
}

内容的提问来源于stack exchange,提问作者dev.farmer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 16:21:51