Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Utilise Android Navigation component to handle deep links with a splash screen activity

I have an app with two activities, a splash screen activity and another that contains the main navgraph for the app.

I was wanting to utilise the new deep linking handling that comes with the Android Navigation Component. However following the Google tutorial, the Splash screen is skipped when clicking the link and dives straight into the navgraph for the app.

Is there any way to use these new features, whilst still forcing the splash screen to be shown first before navigating to the correct part of the app?

like image 906
dev2505 Avatar asked Sep 10 '19 21:09

dev2505


People also ask

What is deep link in Navigation component?

In Android, a deep link is a link that takes you directly to a specific destination within an app. The Navigation component lets you create two different types of deep links: explicit and implicit.

What are Navigation components in Android?

The Navigation component contains a default NavHost implementation, NavHostFragment , that displays fragment destinations. NavController : An object that manages app navigation within a NavHost . The NavController orchestrates the swapping of destination content in the NavHost as users move throughout your app.

What is Android deep linking?

A deep link is a URL that navigates to a specific destination in your app. When you click a deep link, Android: Opens the user's preferred app that can handle the link, if it's available. If the preferred app isn't available, it opens the only app that can handle the link.


1 Answers

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) }
}
like image 173
dev2505 Avatar answered Nov 14 '22 22:11

dev2505