Hello all, I am running into a race condition when trying to use a deep link into my application to ...
b
Hello all, I am running into a race condition when trying to use a deep link into my application to share a file. In short in onCreate I check the incoming intent and if a file share I create and send a deep link to my app. However in my NavHost setup I also setup a startDestination. navController.handleDeepLink(…) is called in the activity before the nav host / controller has navigated to the main/home route. So my deeplink creates the compose view, then the main view is show on top of that. Any ideas? Code in thread.
Copy code
override fun onCreate(savedInstanceState: Bundle?) {
   super.onCreate(savedInstanceState)

   // handle the file share intent
   viewModel.intent.observe(this) { intent ->
      navController.handleDeepLink(intent)
   }

   // This will check the incoming intent for a file share
   viewModel.setIntent(intent)

   setContent {
      val bottomSheetState = rememberModalBottomSheetState(
         initialValue = ModalBottomSheetValue.Hidden,
         skipHalfExpanded = true
      )

      val bottomSheetNavigator = remember {
         BottomSheetNavigator(sheetState = bottomSheetState)
      }

      navController = rememberNavController(bottomSheetNavigator)
      MainScreen(
         navController = navController,
         bottomSheetNavigator = bottomSheetNavigator
      )
   }
}
Copy code
ModalBottomSheetLayout(bottomSheetNavigator) {
   Scaffold(...) { paddingValues ->
         NavHost(
            navController = navController,
            startDestination = "main",  // Start at main, this will happen after deep link handler from MainActivity
            modifier = Modifier.padding(paddingValues)
         ) {
            ...
         }
      }
Is there a “recipe” for this? Maybe only handle deep links in this fashion if the app is running, and if not running just pass the intent to the MainScreen on construction? Feels wrong
i
Why are you doing anything here at all? Navigation will handle the deep link for you, redirecting you to the right screen if you add a deep link with your correct action and/or mime type. Deep links aren't just for URLs
b
Well that is good question, something I did not realize 🙂. Guess I am not sure how to setup compose navigation to handle incoming file share.
Copy code
<intent-filter>
    <action android:name="android.intent.action.VIEW" />
    <action android:name="android.intent.action.SEND" />
    <category android:name="android.intent.category.DEFAULT" />

    <data android:scheme="content" />
    <data android:mimeType="application/octet-stream" />
</intent-filter
I know how handle that in my MainActivity, however getting the nav controller to handle a content uri sounds like what I am missing
i
Just like any other deep link: https://developer.android.com/jetpack/compose/navigation#deeplinks Just use
action
and
mimeType
instead of
uriPattern
b
Thanks, makes sense!
Do you per chance know where the content uri coming in is stored?
i
It could be anywhere - it could be directly streamed from a server or from an encrypted file or just a regular file another app owns that you don't have access to...except via that Uri.
ContentResolver.openInputStream
works to read the contents of that file in every case though
b
Sorry, I think I confused the issue. From onCreate or onNewIntent one can get incoming content uri via intent.data. Is that uri stored in the backstackEntry in the composable navigation route?
Looks like maybe:
Copy code
val intent = backstackEntry.arguments?.getParcelable(NavController.KEY_DEEP_LINK_INTENT, Intent::class.java)
i
Ah, yes
KEY_DEEP_LINK_INTENT
is sent along through arguments