12

it looks like it isn't possible to process a deeplink with query parameters in the new Jetpack Navigation library. If you put the following to the navigation.xml: <deepLink app:uri="scheme://host/path?query1={query_value}" /> then the deeplink does not open the fragment.

After some digging I found that the culprit is probably in the NavDeepLink when it transforms the url from xml to a Pattern regex. Looks like the problem is a question mark that is not excaped.

I wrote a test which fails:

@Test
fun test() {
    val navDeepLink = NavDeepLink("scheme://host/path?query1={query_value}")
    val deepLink = Uri.parse("scheme://host/path?query1=foo_bar")
    assertEquals(true, navDeepLink.matches(deepLink))
}

To make the test pass all I have to do is to escape the ? as following:

@Test
fun test() {
    val navDeepLink = NavDeepLink("scheme://host/path\\?query1={query_value}")
    val deepLink = Uri.parse("scheme://host/path?query1=foo_bar")
    assertEquals(true, navDeepLink.matches(deepLink))
}

Am I missing something really basic here to pass query values to my Fragment or is this not supported feature at the moment?

Phantômaxx
  • 36,442
  • 21
  • 78
  • 108
bakua
  • 12,144
  • 4
  • 37
  • 59

2 Answers2

11

You need to add DeepLink Navigation to AndroidManifest.xml ( special Activity that handles the fragment) so when deeplink clicked your app can receive the DeepLink and pass it to that navigation and fragment & can read it as argument:

I'll put Kotlin codes here :

In your navigation file, your fragment that gonna handle the deeplink with arguements must be like this:

<fragment
        android:id="@+id/menu"
        android:name="ir.hamplus.fragments.MainFragment"
        android:label="MainFragment">

    <action android:id="@+id/action_menu_to_frg_messenger_main" 
     app:destination="@id/frg_messenger_main"/>

    <deepLink app:uri="http://hamplus.ir/request/?key={key}&amp;id={id}" />

    <argument android:name="key" app:argType="string"/>
    <argument android:name="id" app:argType="string"/>

</fragment>

read deeplink arguments in frasgment /Activity :

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
  //Or in activity read the intent?.data
       arguments?.let {
            Log.i("TAG", "Argument=$arguments")

            var key = it.getString("key")
            Log.i("TAG", "key=$key")

            var id = it.getString("id")
            Log.i("TAG", "id=$id")

        }
}

Also add the nav-graph on AndroidManifest.xml in related Activity :

 <activity
        android:name=".MainActivity"
        android:theme="@style/AppTheme.NoActionBar" >

    <nav-graph android:value="@navigation/main_navigation"/>

</activity>
Hamed Jaliliani
  • 2,177
  • 20
  • 29
0
package androidx.navigation

import android.net.Uri
import androidx.test.runner.AndroidJUnit4
import org.junit.Assert.assertTrue
import org.junit.Test
import org.junit.runner.RunWith

@RunWith(AndroidJUnit4::class)
class NavTest {
    @Test
    fun test() {
        val navDeepLink = NavDeepLink("scheme://host/path\\?query1={query_value1}&query2={query_value2}")
        val deepLink = Uri.parse("scheme://host/path?query1=foo_bar&query2=baz")

        val bundle = navDeepLink.getMatchingArguments(deepLink)!!
        assertTrue(bundle.get("query_value1") == "foo_bar")
        assertTrue(bundle.get("query_value2") == "baz")
    }
}

In the end it looks like NavDeepLink treats non escaped as "?" match-zero-or-one quantifier. You need to escape it. In other words, we have a leak of non documented implementation detail.

It might be not related to the exactly this case, but there is some similar issues with escaping "&" with "\" when using add command.

The issue was also touched in the following channel.

Tom Koptel
  • 309
  • 1
  • 9