In my app, I'm using a Single Activity with multiple Fragments Architecture and I navigate between them using the Navigation Library. Within one of the fragments, I have multiple categories, each associated with an ID. When a category is clicked, I take the user to that respective category explainer screen with the code below.
val directions = MainNavGraphDirections.launchFragmentWithThisCategoryId(categoryId!!)
onRoute(AppRoute.Directions(directions))
The above code sends them to the explainer screen associated with the associated categoryId
. All is well until this point, the right explainer screen gets launched based on the categoryId
. Within this explainer screen, I have a deep-link with a tag chatbot://fragment/wizardintro
that is supposed to let the main activity know the specific follow-up fragment to send the user to. I denote all the fragments that can receive this deep-link with the code below.
companion object{
const val DEEP_LINK = "chatbot://fragment/wizardintro"
}
In the MainActivity, I have a method that receives all the different deep linking intents and matches them to the tags that will launch the respective category fragment with the code below.
override fun onNewIntent(intent: Intent?) {
super.onNewIntent(intent)
intent?.data?.toString().also { deepLink ->
when (deepLink) {
IntroductionFragment.DEEP_LINK ->{
val categoryId = intent?.getLongExtra("categoryId", 0L)
val directions = MainNavGraphDirections.actionGlobalGoalWizard(categoryId)
navController.popBackStack()
navController.navigate(directions)
}
}
Now my problem arises when I try to retrieve this categoryId
in the Main Activity and pass it to the next fragment. I don't get anything and only the default Long gets passed along. I think the function override fun onNewIntent(intent: Intent?) { } in the MainActivity recieve any intent. To be clear, these intents are sent from the explainer fragment which is technically a fragment that loads a json. Within the json there is a "route": {"type": "route", "url": "chatbot:///fragment/wizardintro"
In the MainActivity, the onNewIntent functions receive these intents unpacks them with this line intent?.data?.toString().also ...
then in the when statement picks a fragment that has a matching chatbot:///fragment/wizardintro
I said all this to say that the main activity doesn't actually gets the categoryId, it simply picks launching the neccessary fragment without actually having anything associated with the categoryId
This makes me think that the first clicked categoryId doesn't actually get passed to the MainActivity. Although, to me, this seems like it shouldn't be this hard to pass objects/data from a fragment to an activity. What am I missing? What can I read to educate myself more on this? Thanks for your time and responses!
Since we already got to the conclusion that MainActivity
is not getting categoryId
, you just need to pass that categoryId
with the deep-link
.
However, there is no need for any communication from Fragment
to Activity
.
You could achieve the same result through communication only between Fragment
to Fragment
, and Activity
to Fragment
.
What you want to do is to look more closely on deep-links
and android navigation
in the AndroidDocs, click here.
As you can tell, there are different ways to go around this, starting with arguments
for each fragment. Assigning categoryId
as an argument
to the Fragment would help you use the navigationController
and navigate
to the new Fragment
, while passing the categoryId
to it.
Now, I am aware that you also wish to launch it with a deep-link
; there's also a good explanation on here. According to the docs, you can place arguments
in deep-links
in the following manner...
Placeholders in the form of
{placeholder_name}
match one or more characters. For example,http://www.example.com/users/{id}
matcheshttp://www.example.com/users/4
. The Navigation component attempts to parse the placeholder values into appropriate types by matching placeholder names to the defined arguments that are defined for the deep link destination. If no argument with the same name is defined, a default String type is used for the argument value.
The navigation
is something amazing and capable, you just need to be aware of everything it can actually do. You can even bind it to a BottomNavBar
, with extremely minimal amount of code.
Try going over the AndroidDocs about it, and it'll grow on you for sure.