Posting the solution that I came to here in case anyone else has the same requirements.
It was actually pretty simple in the end! In the splash screen activity, catch the pendingDynamicLinkData as below:
private fun decideNextDestination() {
FirebaseDynamicLinks.getInstance()
.getDynamicLink(intent)
.addOnSuccessListener(this) { pendingDynamicLinkData ->
val deepLink = pendingDynamicLinkData?.link
if (deepLink == null) navigateToMain() else deepLinkToDestination(deepLink)
}
.addOnFailureListener(this) { navigateToMain() }
}
Then in the deepLinkToDestination method, build an intent and add a bundle with the deeplink URI to pass along (Android Uri implements parcelable so can pass with no issues):
private fun deepLinkToDestination(deepLink: Uri) {
val bundle = Bundle().apply { putParcelable(DEEP_LINK_PARAM_KEY, deepLink) }
val intent = Intent(this, NavHostActivity::class.java).apply { putExtras(bundle) }
startActivity(intent)
finish()
}
Then in onCreate of the destination activity, grab the deep link, cast to Uri and navigate using implicit deep links (see docs https://developer.android.com/guide/navigation/navigation-deep-link#implicit) as below:
private fun handleDeepLink() {
val deepLink = intent.extras?.getParcelable(DEEP_LINK_PARAM_KEY) as? Uri
deepLink?.let { navController.safeNavigateToDeepLink(deepLink) }
}
I created an extension function for NavController, safeNavigateToDeepLink(deepLink), to check if the navGraph has reference to that deep link (as suggested in the navigation component source code), then if this can't be found, to navigate to a default destination:
fun NavController.safeNavigateToDeepLink(uri: Uri) {
if (graph.hasDeepLink(uri)) navigate(uri)
else safeNavigateTo(R.id.home)
}
If it helps anyone else, the other extension function in there is the below, which just checks that an action to navigate to that destination can be found before navigating:
fun NavController.safeNavigateTo(id: Int) {
val action = currentDestination?.getAction(id)
action?.let { navigate(id) }
}