在带有深层链接的导航图中打开 activity 导致崩溃

Opening activity inside a navgraph with a deeplink causing a crash

我在导航图中有一个activity,我可以直接通过下面的代码导航到它

Navigation.findNavController(requireView())?.navigate(R.id.sampleActivity)

请找到下面的导航图

<navigation xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/home_nav_graph"
    app:startDestination="@id/appFirstFragment">

    <fragment
        android:id="@+id/appFirstFragment"
        android:name="com.example.deeplinkpoc.AppFirstFragment"
        android:label="fragment_app_first"
        tools:layout="@layout/fragment_app_first" >
    </fragment>
    <activity
        android:id="@+id/sampleActivity"
        android:name="com.example.deeplinkpoc.SampleActivity"
        android:label="activity_sample"
        tools:layout="@layout/activity_sample">
        <deepLink
            android:id="@+id/deepLink2"
            app:uri="https://www.abcdxyz.com/test" />
    </activity>
     </navigation>

但如果我尝试使用深度链接导航到它,它就会崩溃

Process: com.example.deeplinkpoc, PID: 12805
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.deeplinkpoc/com.example.deeplinkpoc.HomeActivity}: android.view.InflateException: Binary XML file line #8: Binary XML file line #8: Error inflating class androidx.fragment.app.FragmentContainerView
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2914)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3049)
    at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
    at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
    at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1809)
    at android.os.Handler.dispatchMessage(Handler.java:106)
    at android.os.Looper.loop(Looper.java:193)
    at android.app.ActivityThread.main(ActivityThread.java:6692)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
 Caused by: android.view.InflateException: Binary XML file line #8: Binary XML file line #8: Error inflating class androidx.fragment.app.FragmentContainerView
 Caused by: android.view.InflateException: Binary XML file line #8: Error inflating class androidx.fragment.app.FragmentContainerView
 Caused by: android.content.res.Resources$NotFoundException: Unable to find resource ID #0x0
    at android.content.res.ResourcesImpl.getResourceTypeName(ResourcesImpl.java:271)
    at android.content.res.Resources.getResourceTypeName(Resources.java:1986)
    at androidx.navigation.ActivityNavigator.navigate(ActivityNavigator.java:200)
    at androidx.navigation.ActivityNavigator.navigate(ActivityNavigator.java:44)
    at androidx.navigation.NavController.navigate(NavController.java:1057)
    at androidx.navigation.NavController.handleDeepLink(NavController.java:732)
    at androidx.navigation.NavController.onGraphCreated(NavController.java:633)
    at androidx.navigation.NavController.setGraph(NavController.java:590)
    at androidx.navigation.NavController.setGraph(NavController.java:555)
    at androidx.navigation.NavController.setGraph(NavController.java:537)
    at androidx.navigation.fragment.NavHostFragment.onCreate(NavHostFragment.java:248)
    at androidx.fragment.app.Fragment.performCreate(Fragment.java:2684)
    at androidx.fragment.app.FragmentStateManager.create(FragmentStateManager.java:280)
    at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1175)
    at androidx.fragment.app.FragmentManager.addAddedFragments(FragmentManager.java:2224) 

更新 请查找navhost activity xml

<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".HomeActivity">
<androidx.fragment.app.FragmentContainerView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/my_nav_host_fragment"
    android:name="androidx.navigation.fragment.NavHostFragment"
    app:navGraph="@navigation/home_nav_graph"
    /></androidx.constraintlayout.widget.ConstraintLayout>

如何使用深度链接在导航图中打开 activity?

确保遵循以下步骤:

  1. NavGraph 添加到 Application class 在 AndroidManifesto.xml.
  2. ACTION_VIEW 添加到 DeepLink

如果没有别的办法,那么下面的解决方案肯定有效:

  1. AndroidManifesto 中为 sampleActivity 添加 <activity> 标签。
  2. 向此 sampleActivity 标签添加一个 implicit intent,使用 ACTION_VIEW
  3. sampleActivityonCreate 生命周期事件中收集这个 implicit intent

您不必依赖 Navigation ComponentdeepLink 导航到 simpleActivity。您可以通过 implicit intent 自己注册深层链接,它会正常工作。

NavigationComponent 的作用是检测 Graph 中存在的 DeepLinks,并将它们添加到 AndroidManifesto。您的问题可能源于您想要接触的 activity,即 sampleActivity 生活在 nestedGraph 中。在这种情况下,不会创建 deepLink。但是,sampleActivitydestionationId 仍然会被 NavController 知道。因此解释了为什么您能够从 destinationId 到达 sampleActivity 而不是从 deepLink.

要让您的应用程序知道 sampleActivity deepLink,您必须将此 deepLink 设置传播到 parentGraph。只需在 parentGraph.

中初始化以下 deepLink
 <activity
        android:id="@+id/sampleActivity"
        android:name="com.example.deeplinkpoc.SampleActivity"
        android:label="activity_sample"
        tools:layout="@layout/activity_sample">
        <deepLink
            android:id="@+id/deepLink2"
            app:uri="https://www.abcdxyz.com/test" />

根据 this issue,这是 Navigation 2.3.2 的一个已知问题,已标记为已在即将发布的 Navigation 2.3.3 版本中修复。

但是:

note that it is never the right approach to attach a <deeplink> to an <activity> destination as that will never give you the right behavior when using an implicit deep link on another app's task (where the system back should immediately take the user back to the app that triggered your deep link). Instead, you should attach your deep link directly to your second activity (either by manually writing the appropriate <intent-filter> or by adding the <deeplink> to the start destination of a nav host in that second activity).

所以真的,你应该把你的 <deeplink> 移出你的 activity 目的地,这将修复你的崩溃(在每个版本的导航上)并且实际上给你正确的行为。您需要做的任何验证都需要在实际正确的 activity.

上完成