Rob
Rob

Reputation: 61

Jetpack compose typesafe navigation crash

Restoring the Navigation back stack failed: destination 30355061 cannot be found from the current destination mj0(0x0) startDestination={oj0(0x2e873c) route=x.x.x.x.composeNavigation.MenuScreen}

I have a jetpack compose project where I'm using the type-safe navigation, and I see many crashes in Firebase.

import kotlinx.serialization.Serializable

@Serializable
object QrCodeScreenScanner

@Serializable
data class OtpScreen(val otpCode: String)

@Serializable
data class SignatureDataOverviewScreen(val transactionId: String, val payload: String)

@Serializable
data class SignatureHashOverlayScreen(val otpCode: String)

@Serializable
object MenuScreen

@Serializable
object AskForNotificationPermissionScreen

@Serializable
data class UpdateNeededScreen(val cancellable: Boolean)

 

    class MenuActivity : ComponentActivity() {

    companion object {
        const val ENROLMENT_COMPLETED = "ENROLMENT_COMPLETED"
    }

    private val navigator: Navigator by inject { parametersOf(this@MenuActivity) }
    private val menuViewModel: MenuViewModel by viewModel()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            val navController = rememberNavController()
            var permissionDialogScreenAlreadyShowed = remember { false }

            Theme {
                NavHost(navController = navController, startDestination = MenuScreen) {
                    composable<MenuScreen> {
                        val uiState by menuViewModel.uiState.collectAsStateWithLifecycle()
                        MenuScreen(
                            uiState = uiState,
                            navigator = navigator,
                            navigateToAskForNotificationPermission = {
                                navController.navigate(AskForNotificationPermissionScreen)
                            },
                            enrolmentStates = menuViewModel.subscribeToEnrolmentState(),
                            permissionDialogScreenAlreadyShowed = permissionDialogScreenAlreadyShowed,
                            uiEvents = menuViewModel.uiEvent,
                            isOnline = menuViewModel.isOnline,
                            menuItemIntentAction = menuViewModel::setMenuViewModelIntent,
                            appUpdateCheckNeeded = menuViewModel.appUpdateCheckNeeded,
                            navigateToShowUpdateScreen = { cancellable ->
                                navController.navigate(UpdateNeededScreen(cancellable))
                            },
                        )
                    }
                    composable<AskForNotificationPermissionScreen> {
                        RequestNotificationPermissionScreen(
                            navigateToMenuScreen = {
                                permissionDialogScreenAlreadyShowed = true
                                navController.navigate(MenuScreen)
                            }
                        )
                    }
                    composable<UpdateNeededScreen> {
                        ShowAppUpdateScreen(
                            cancellable = true,
                            navigateToMenuScreen = {
                                navController.navigate(MenuScreen)
                            }
                        )
                    }
                }
            }
        }
    }

    override fun onNewIntent(intent: Intent) {
        super.onNewIntent(intent)

        intent.extras?.let { extras ->
            val confirmationToken =
                extras.getString(this.getString(R.string.ENROLMENT_CHALLENGE), "")
            val deviceName =
                extras.getString(this.getString(R.string.ENROLMENT_DEVICENAME), "")

            Timber.d("Confirmation token: %s", confirmationToken ?: "(empty)")
            Timber.d("DeviceName: %s", deviceName ?: "(empty)")
            if (!confirmationToken.isNullOrBlank() && !deviceName.isNullOrBlank()) {
                menuViewModel.setMenuViewModelIntent(
                    MenuViewModelIntent.ProcessEnrolment(
                        confirmationToken = confirmationToken,
                        deviceName = deviceName
                    )
                )
                return
            }
            val isEnrolmentCompleted = extras.getBoolean(ENROLMENT_COMPLETED, false)
            if (isEnrolmentCompleted) {
                navigator.navigateTo(NavigatorRoute.ENROLMENT_COMPLETED)
            }
        }
    }
}

I have a multi-module architecture where every module has its navigation graph.

Anyone faced this issue before? I'm using the new type-safety way to navigate. Locally, everything works as expected, but I see many errors in firebase crashlytics. Why?

Upvotes: 1

Views: 100

Answers (0)

Related Questions