使用参数深度链接到另一个模块

sty*_*972 10 android android-architecture-navigation androidx android-deep-link

我正在尝试使用深层链接进行跨模块用户导航,并且我需要传递一些参数。由于它位于另一个模块中,因此我无权访问id,因此所有navigate(@IdRes int resId, ...)方法都不适用。

使用 Android Jetpack 的导航组件导航具有键值对的Uri深层链接的最佳方法是什么?Bundle

navigation.xml(:应用程序模块)

<?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>
Run Code Online (Sandbox Code Playgroud)

feature_one.xml(:一个模块)

<?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>
Run Code Online (Sandbox Code Playgroud)

feature_two.xml(:两个模块)

<?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>
Run Code Online (Sandbox Code Playgroud)

OneFragment.kt(:一个模块)

    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
    )
Run Code Online (Sandbox Code Playgroud)

TwoFragment.kt(:两个模块)

    private val args: TwoFragmentArgs by navArgs()

    ...
    
        val myId: Long = args.myId // never set, so how?
Run Code Online (Sandbox Code Playgroud)

ces*_*nha 5

tldr仔细检查确保在创建请求时正确编码所有内容,特别是如果您使用包含多个单词、空格或特殊字符的参数,则需要使用已经为您编码的 Uri.Builder 方法或事先自己对它们进行编码

您的 xml 定义正确,问题在于您如何构建 URI。

我做的几乎和你一样,但是使用

    val myId = 123L
    val uri =  Uri.Builder().path("myapp://my.app/$myId")
        .build()
    val request = NavDeepLinkRequest.Builder
        .fromUri(uri)
        .build()
    findNavController().navigate(request)
Run Code Online (Sandbox Code Playgroud)

并且深层链接无法匹配此 URI,并给出此异常 java.lang.IllegalArgumentException: Navigation destination that matches request NavDeepLinkRequest{...

我可以通过改变 URI 的构建方式来解决这个问题

像这样构建它

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)
Run Code Online (Sandbox Code Playgroud)

或像这样(如@SUR4IDE答案)

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)
Run Code Online (Sandbox Code Playgroud)

这两种方法都避免了路径 String 的编码有些不同的问题,特别是如果参数具有在 URI 中以不同方式编码的空格或特殊字符,并且与我的场景中feature_two.xml中定义的深层链接不匹配。URI 字符串被编码为"myapp%3A//my.app/123",这种:编码差异导致匹配不起作用,所以就像我没有使用定义的深层链接一样。

当匹配成功时,导航类会将 URI 中的参数与 .xml 中定义的参数进行匹配(它们的名称必须与您所做的完全相同),并使用它们作为参数创建一个 Bundle 并将其传递给它将导航到的片段或活动。