Я разрабатываю образец аутентификации Firebase Email Link с использованием Jetpack Compose & Navigation.
Если пользователь вводит адрес электронной почты и пытается выполнить аутентификацию, на адрес электронной почты отправляется сообщение. Когда пользователь открывает и щелкает ссылку электронной почты, приложение снова открывается.
Он использует динамическую ссылку Firebase.
Итак, когда приложение снова открывается, я могу получить emailLink
из динамической ссылки.
И я передаю его на целевую страницу (Главная).
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:
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")
,
emailLink
это:
{https://email-link-auth-sample-95a4a.firebaseapp.com/__/auth/action?apiKey=AIzaSyD2w6bRHiqEXaSx9W0N5Mq5obydIjRk_mw
Я думаю, что система составления навигации была разработана на основе системы 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}")
/**
* my workaround code using the `savedStateHandle`
*/
navController.currentBackStackEntry?.savedStateHandle?.apply {
set("emailLink", emailLink)
}
navController.navigate(Home.route)
}
}
}
}
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")
/**
* my workaround code using the `savedStateHandle`
*/
val emailLink = navController.previousBackStackEntry?.savedStateHandle?.get<String>("emailLink")
HomeScreen(
vm = hiltViewModel(),
emailLink = emailLink
)
}
}
Вы можете найти код здесь: https://github.com/yoonhok524/Email-Link-Auth-Sample
Я решил эту проблему. Если я закодирую URL-ссылку, а затем передам ее, она будет работать нормально!
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}")
/**
* my workaround code using the `savedStateHandle`
*/
// navController.currentBackStackEntry?.savedStateHandle?.apply {
// set("emailLink", emailLink)
// }
// navController.navigate(Home.route)
/**
* my solution code
*/
val encodedEmailLink = withContext(Dispatchers.IO) {
URLEncoder.encode(it, StandardCharsets.UTF_8.toString())
}
navController.navigate(Home.getRoute(encodedEmailLink))
}
}
}
}