android - 使用 Jetpack Compose 的深层链接导航到可组合项

标签 android kotlin android-jetpack-compose android-deep-link

当用户在我们的应用程序中输入地理围栏时,我们会向他们显示有关该区域的报价通知,单击该通知时,应将他们引导至名为 SingleNotification 的特定可组合屏幕.我关注了谷歌的codelab和他们的documentation但我还没有设法使导航到特定屏幕的工作。现在,点击通知或运行adb shell am start -d “eway://station_offers/date_str/www.test.com/TITLE/CONTENT” -a android.intent.action.VIEW命令,只需打开应用程序。
该 Activity 在 list 中声明如下:

    <activity
        android:name=".MainActivity"
        android:exported="true"
        android:label="@string/app_name"
        android:screenOrientation="portrait">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />

            <category android:name="android.intent.category.DEFAULT" />
            <category android:name="android.intent.category.BROWSABLE" />
        </intent-filter>

        <intent-filter>
            <action android:name="android.intent.action.VIEW" />

            <category android:name="android.intent.category.DEFAULT" />
            <category android:name="android.intent.category.BROWSABLE" />

            <data
                android:host="station_offers"
                android:scheme="eway" />
        </intent-filter>
    </activity>
我们的 MainNavController 类包含 NavHost,而 NavHost 又包含各种 NavGraphs。我只包括了下面的相关图表:
        NavHost(
            navController = navController,
            startDestination = NavigationGraphs.SPLASH_SCREEN.route
        ) {
....
            notificationsNavigation()
....    
    }
通知导航图定义如下:
fun NavGraphBuilder.notificationsNavigation() {
    navigation(
        startDestination = Screens.NOTIFICATION_DETAILS.navRoute,
        route = NavigationGraphs.NOTIFICATIONS.route
    ) {
        composable(
            route = "${Screens.NOTIFICATION_DETAILS.navRoute}/{date}/{imageUrl}/{title}/{content}",
            arguments = listOf(
                navArgument("date") { type = NavType.StringType },
                navArgument("imageUrl") { type = NavType.StringType },
                navArgument("title") { type = NavType.StringType },
                navArgument("content") { type = NavType.StringType }
            ),
            deepLinks = listOf(navDeepLink {
                uriPattern = "eway://${Screens.NOTIFICATION_DETAILS.navRoute}/{date}/{imageUrl}/{title}/{content}"
            })
        ) { backstackEntry ->
            val args = backstackEntry.arguments
            SingleNotification(
                date = args?.getString("date")!!,
                imageUrl = args.getString("imageUrl")!!,
                title = args.getString("title")!!,
                description = args.getString("content")!!
            )
        }
    }
}
Screes.NOTIFICATION_DETAILS.navRoute对应于 notification_details 的值.
在地理围栏广播接收器中,我按如下方式构造待处理的 Intent:
                        val deepLinkIntent = Intent(
                            Intent.ACTION_VIEW,
                            "eway://station_offers/${
                                offer.date
                            }/${
                                offer.image
                            }/${offer.title}/${offer.content}".toUri(),
                            context,
                            MainActivity::class.java
                        )
                        val deepLinkPendingIntent: PendingIntent =
                            TaskStackBuilder.create(context!!).run {
                                addNextIntentWithParentStack(deepLinkIntent)
                                getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT)!!
                            }
                        showNotification(offer.title, offer.content, deepLinkPendingIntent)
我无法弄清楚我在这里缺少什么。

最佳答案

更新 :请参阅下面@curioustechizen 的答案以获取实际解决方案,而不是这种解决方法!
好吧,经过大量测试并逐行运行谷歌相关代码实验室的解决方案,我想出了如何让它工作。
首先,它看起来像 host我们在 AndroidManifest.xml 中为 <data> 定义的 Intent 过滤器的标签需要很多可组合目的地的路线。所以在我的例子中,它被定义为:

        <intent-filter>
            <action android:name="android.intent.action.VIEW" />

            <category android:name="android.intent.category.DEFAULT" />
            <category android:name="android.intent.category.BROWSABLE" />

            <data
                android:host="notification_details"
                android:scheme="eway" />
        </intent-filter>
其次,深层链接的 uri 模式应该与可组合的路由格式相匹配。在这种情况下,由于可组合的路由定义为 route = "${Screens.NOTIFICATION_DETAILS.navRoute}/{date}/{imageUrl}/{title}/{content}" ,正确的深层链接uriPattern , 将会 :
deepLinks = listOf(navDeepLink {
                    uriPattern =
                        "eway://${Screens.NOTIFICATION_DETAILS.navRoute}/{date}/{imageUrl}/{title}/{content}"
                })
此外,可组合目的地似乎必须在 NavHost 中声明。本身而不是在 NavGraph 中。最初如您所见,我认为系统将能够通过嵌套的 NavGraph 找到目的地,但它不能(抛出一个相对异常),所以我得出结论必须以这种方式完成(如在代码实验室中完成)。如果我错了,请纠正我!
最后,我更改了 val uri相应地在我的 GeofenceBroadcastReceiver 中定义。现在看起来像这样:
val uri = "eway://${Screens.NOTIFICATION_DETAILS.navRoute}/${
                                    offer.date.replace(
                                        "/",
                                        "@"
                                    )
                                }/${
                                    offer.image.replace(
                                        "/",
                                        "@"
                                    )
                                }/${offer.title}/${offer.content.replace("/", "@")}".toUri()
回顾一下,就我的理解而言,这些是似乎可以解决这个问题的步骤:
  • 深层链接的可组合目标必须是主 NavHost
  • 的直接子级
  • AndroidManifest 的 android:host应该匹配目标可组合的路由,最后是
  • 深层链接的 Uri 模式应该与目标可组合的路由匹配(如果您使用格式 scheme://host/....,如果您遵循数字 2,则应该没问题)
  • 关于android - 使用 Jetpack Compose 的深层链接导航到可组合项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72316892/

    相关文章:

    java - 如何通过模型构造函数在 Spring boot 中进行查询

    android - 为什么我的可组合不会在更改 HashMap 的 MutableState 值时重新组合?

    android - 在 kotlin 文件中找不到可绘制对象

    android - 带有渐变背景的Jetpack Compose按钮?

    android - 将 Json 字符串解析为 Json 数组时出错

    java - 在运行时将 dex 添加到 Android 类路径

    java - 以下类无法实例化 : android. support.constraint.ConstraintLayout

    android - 将自定义指标附加到 Android Analytics v4 中的 HitBuilders.TransactionBuilder

    listener - Kotlin 推荐的使用 SAM 注销监听器的方法

    Android Material 下拉列表 : Selected dropdown item is presented like toString instead of defined View