androidandroid-jetpack-composebranch.iojetpack-compose-navigation

Jetpack compose deeplink handling branch.io


I'm using branch.io for handling deep links. Deep links can contain custom metadata in a form of JsonObject. The data can be obtained by setting up a listener, inside MainActivity#onStart() which is triggered when a link is clicked.

   override fun onStart() {
    super.onStart()
    Branch
        .sessionBuilder(this)
        .withCallback { referringParams, error ->
            if (error == null) {
                val eventId = referringParams?.getString("id")
                    
                //Here I would like to navigate user to event screen
            } else {
                Timber.e(error.message)
            }
        }
        .withData(this.intent?.data).init()
}

When I retrieve eventId from referringParams I have to navigate the user to the specific event. When I was using Navigation components with fragments I could just do:

findNavController(R.id.navHost).navigate("path to event screen")

But with compose is different because I can't use navController outside of Composable since its located in MainActivity#onCreate()

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContent {
        
        //I cant access navController outside of composable function
        val navController = rememberNavController()

        NavHost(
            navController = navController,
            startDestination = "HomeScreen",
        ) {
            
        }
    }
}

My question is, how can I navigate the user to a specific screen from MainActivity#onStart() when using jetpack compose navigation


Solution

  • rememberNavController has pretty simple implementation: it creates NavHostController with two navigators, needed by Compose, and makes sure it's restored on configuration change.

    Here's how you can do the same in your activity, outside of composable scope:

    private lateinit var navController: NavHostController
    private val navControllerBundleKey = "navControllerBundleKey"
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
    
        navController = NavHostController(this).apply {
            navigatorProvider.addNavigator(ComposeNavigator())
            navigatorProvider.addNavigator(DialogNavigator())
        }
    
        savedInstanceState
            ?.getBundle(navControllerBundleKey)
            ?.apply(navController::restoreState)
    
        setContent {
            // pass navController to NavHost
        }
    }
    
    override fun onSaveInstanceState(outState: Bundle) {
        outState.putBundle(navControllerBundleKey, navController.saveState())
        super.onSaveInstanceState(outState)
    }