I'm trying to navigate using a deep-link for cross-module user navigation, and I need to pass some parameters. Since it's in another module, I don't have access to the id, so all of the navigate(@IdRes int resId, ...) methods are off the table.
What's the best way to navigate a deep link with a Uri and a Bundle of key-value-pairs using Android Jetpack's Navigation component?
navigation.xml (:app module)
<?xml version="1.0" encoding="utf-8"?>
<navigation
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/navGraph"
app:startDestination="@id/feature_one">
<include app:graph="@navigation/feature_one" />
<include app:graph="@navigation/feature_two />
</navigation>
feature_one.xml (:one module)
<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/feature_one"
app:startDestination="@id/oneFragment">
<fragment
android:id="@+id/oneFragment"
android:name="my.app.OneFragment"
android:label="OneFragment" />
</navigation>
feature_two.xml (:two module)
<?xml version="1.0" encoding="utf-8"?>
<navigation
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/feature_two"
app:startDestination="@id/twoFragment">
<fragment
android:id="@+id/twoFragment"
android:name="my.app.TwoFragment"
android:label="TwoFragment">
<deepLink app:uri="myapp://my.app/?myId={myId}" />
<argument android:name="myId" app:argType="long" />
</fragment>
</navigation>
OneFragment.kt (:one module)
val bundle = bundleOf("myId" to 123L)
val request = NavDeepLinkRequest.Builder
.fromUri("myapp://my.app?myId={myId}")
.build()
// No place to bundle the args
findNavController().navigate(
request,
navOptions
)
TwoFragment.kt (:two module)
private val args: TwoFragmentArgs by navArgs()
...
val myId: Long = args.myId // never set, so how?
tldr: double check make sure you are encoding everything correctly while creating the request, especially if you are using parameters with more than one word, whitespaces or special character, you will need to use the Uri.Builder methods that already encode things for you or encode them yourself beforehand
Your xmls are defined correctly, the problem is how you are building the URI.
I was doing almost the same as you but using
val myId = 123L
val uri = Uri.Builder().path("myapp://my.app/$myId")
.build()
val request = NavDeepLinkRequest.Builder
.fromUri(uri)
.build()
findNavController().navigate(request)
And the deep link couldn't match this URI and it gives this Exception
java.lang.IllegalArgumentException: Navigation destination that matches request NavDeepLinkRequest{...
I was able to solve it by changing the way the URI was built
Building it like this
val myId = 123L
val uri = Uri.Builder().scheme("myapp")
.authority("my.app")
.path("/$myId")
.build()
val request = NavDeepLinkRequest.Builder
.fromUri(uri)
.build()
findNavController().navigate(request)
or like this (as in @SUR4IDE answer)
val myId = 123L
val correctyEncodedId = URLEncoder.encode(myId, "utf-8")
val request = NavDeepLinkRequest.Builder
.fromUri(Uri.parse("myapp://my.app/$correctyEncodedId"))
.build()
findNavController().navigate(request)
Both approaches avoid a problem where the path String was being encoded somewhat different, especially if the argument has whitespaces or special characters that are differently encoded in a URI, and was not matching the deep link defined within feature_two.xml in my scenario. The URI string was being encoded as "myapp%3A//my.app/123" and this : encoding difference was making the match not work and so it was like I wasn't using the defined deep link.
When the match works, the Navigation classes will match the arguments from your URI to the ones defined in the .xml (they have to be named exactly the same, as you did) and will create a Bundle with them as args and pass it to the Fragment or Activity it will navigate to.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With