Status Update
Comments
il...@google.com <il...@google.com>
il...@google.com <il...@google.com>
il...@google.com <il...@google.com> #2
From the other issue:
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 anon 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 implicit deep link <intent-filter>
or by adding the<deeplink>
to the start destination of a nav host in that second activity).
A lint error saying as such when a <deepLink>
element is added in Navigation XML would go a really long way to avoiding this case. Our navigation-runtime-lint
artifact that would contain this check.
li...@gmail.com <li...@gmail.com> #3
We have some
tu...@gmail.com <tu...@gmail.com> #5
Branch: androidx-main
commit cd77b4bbe312dd8892dfbb3c662344d13a96c82d
Author: Julia McClellan <juliamcclellan@google.com>
Date: Thu Apr 14 15:31:46 2022
Deep link in activity destination in navigation lint
Test: Included tests of API version and the lint rule
Bug: 178403185
Change-Id: Ic15a5ec165620b7ef5b3f03538cc83b5576add8d
A navigation/navigation-runtime-lint/src/main/java/androidx/navigation/runtime/lint/DeepLinkInActivityDestinationDetector.kt
A navigation/navigation-runtime-lint/src/test/java/androidx/navigation/runtime/lint/ApiLintVersionsTest.kt
M settings.gradle
A navigation/navigation-runtime-lint/build.gradle
M navigation/navigation-runtime/build.gradle
A navigation/navigation-runtime-lint/src/main/java/androidx/navigation/runtime/lint/NavigationRuntimeIssueRegistry.kt
A navigation/navigation-runtime-lint/src/test/java/androidx/navigation/runtime/lint/DeepLinkInActivityDestinationDetectorTest.kt
A navigation/navigation-runtime-lint/src/main/resources/META-INF/services/com.android.tools.lint.client.api.IssueRegistry
pa...@gmail.com <pa...@gmail.com> #6
su...@gmail.com <su...@gmail.com> #7
ma...@gmail.com <ma...@gmail.com> #8
NavDestination node = i == 0 ? mGraph : graph.findNode(destinationId);
if deepLink.length == 1 node never will be null and this will cause IllegalStateException
Bug demo:
get NavigationAdvancedSample from github
on R.id.about_btn click
NavDeepLinkBuilder(it.context)
.setGraph(R.navigation.list)
.setDestination(R.id.leaderboard)
.createTaskStackBuilder()
.startActivities()
will crash because R.id.leaderboard is start destination (findInvalidDestinationDisplayNameInDeepLink will have deepLink length == 1)
NavDeepLinkBuilder(it.context)
.setGraph(R.navigation.list)
.setDestination(R.id.userProfile)
.createTaskStackBuilder()
.startActivities()
will work because findInvalidDestinationDisplayNameInDeepLink will return NOT null
[Deleted User] <[Deleted User]> #9
It still crash with the latest version 2.2.1. I think the problem lies somewhere around this code
NavDestination node = i == 0 ? mGraph : graph.findNode(destinationId);
When i
is 0
, just return mGraph
itself. When the deep link destination is a root of bottom_nav tab, the deeplink.length
becomes 1. Which means this function still says there's no invalid Destination in deep link even if deepLink[0]
is totally irrelevant tomGraph
.
So this step passes and when findDestination() is actually triggered down the road, it won't find any destination and thus lead to unknown destination
crash.
All NavControllers of bottom nav automatically call handleDeepLink()
as part of onGraphCreated()
. The problem arises the moment NavController whose graph is irrelevant to the root deep link destination calls handleDeepLink()
.
dr...@gmail.com <dr...@gmail.com> #10
It still crashes with 2.3.0-alpha03 version but only if you try to deeplink to startDestination fragment inside navigation graph. Repro steps (described in #8, but lets repeat it in hope issue will be reopened):
- download NavigationAdvancedSample
- send pending intent to any startDestination screen, e.g.
val pendingIntent = NavDeepLinkBuilder(applicationContext)
.setGraph(R.navigation.list)
.setDestination(R.id.leaderboard)
.setArguments(bundle) // no matter if it is empty in this use case
.createPendingIntent()
pendingIntent.send()
Exception:
Caused by: java.lang.IllegalStateException: unknown destination during deep link: com.example.android.navigationadvancedsample:id/list
at androidx.navigation.NavController.handleDeepLink(NavController.java:689)
at androidx.navigation.NavController.onGraphCreated(NavController.java:602)
at androidx.navigation.NavController.setGraph(NavController.java:563)
at androidx.navigation.NavController.setGraph(NavController.java:528)
at androidx.navigation.fragment.NavHostFragment.onCreate(NavHostFragment.java:246)
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.FragmentTransition.addToFirstInLastOut(FragmentTransition.java:1255)
at androidx.fragment.app.FragmentTransition.calculateFragments(FragmentTransition.java:1138)
at androidx.fragment.app.FragmentTransition.startTransitions(FragmentTransition.java:136)
at androidx.fragment.app.FragmentManager.executeOpsTogether(FragmentManager.java:1989)
at androidx.fragment.app.FragmentManager.removeRedundantOperationsAndExecute(FragmentManager.java:1947)
at androidx.fragment.app.FragmentManager.execSingleAction(FragmentManager.java:1818)
at androidx.fragment.app.BackStackRecord.commitNow(BackStackRecord.java:297)
at com.example.android.navigationadvancedsample.NavigationExtensionsKt.obtainNavHostFragment(NavigationExtensions.kt:269)
at com.example.android.navigationadvancedsample.NavigationExtensionsKt.setupWithNavController(NavigationExtensions.kt:61)
at com.example.android.navigationadvancedsample.MainActivity.setupBottomNavigationBar(MainActivity.kt:121)
at com.example.android.navigationadvancedsample.MainActivity.onCreate(MainActivity.kt:54)
Reopening would be a good sign that issue is recognized.
dr...@gmail.com <dr...@gmail.com> #11
Just in a case Reopen feature is not implemented in IssueTracker :), new ticket is created:
mi...@gmail.com <mi...@gmail.com> #12
ne...@gmail.com <ne...@gmail.com> #13
il...@google.com <il...@google.com> #14
Filing a new bug with a sample project that reproduces the issue you're still seeing is indeed the correct behavior. We don't support bug necromancy, particularly 30 releases after the original fix was shipped.
Description
Version used: 1.0.0-alpha09
Devices/Android versions reproduced on: Android 9 emulator
In our app, we use multiple NavHostFragment in one Activity, few of them have their own navGraph set in xml, say nav_subgraph_1, nav_subgraph_2.
In code, we use NavDeepLinkBuilder to navigate to a specified page.
NavDeepLinkBuilder(it)
.setGraph(R.navigation.nav_subgraph_1)
.setDestination(R.id.dest_in_subgraph1)
.createTaskStackBuilder()
.startActivities()
It leads a crash in setContentView since the dest_in_subgraph1 couldn't be found in nav_subgraph_2 (while parsing the second NavHostFragment in the same Activity)
Crash log:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.testapp.mobile.android.staging.debug, PID: 12615
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.testapp.mobile.android.staging.debug/com.testapp.mobile.android.ui.HomeActivity}: android.view.InflateException: Binary XML file line #85: Binary XML file line #85: Error inflating class fragment
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2913)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3048)
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:1808)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6669)
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 #85: Binary XML file line #85: Error inflating class fragment
Caused by: android.view.InflateException: Binary XML file line #85: Error inflating class fragment
Caused by: java.lang.IllegalStateException: unknown destination during deep link: com.testapp.mobile.android.staging.debug:id/an_id_set_in_graph
at androidx.navigation.NavController.onHandleDeepLink(NavController.java:546)
at androidx.navigation.NavController.onGraphCreated(NavController.java:466)
at androidx.navigation.NavController.setGraph(NavController.java:421)
at androidx.navigation.fragment.NavHostFragment.onCreate(NavHostFragment.java:221)
at android.support.v4.app.Fragment.performCreate(Fragment.java:2414)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1418)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1684)
at android.support.v4.app.FragmentManagerImpl.addFragment(FragmentManager.java:1930)
at android.support.v4.app.FragmentManagerImpl.onCreateView(FragmentManager.java:3745)
at android.support.v4.app.FragmentController.onCreateView(FragmentController.java:120)
at android.support.v4.app.FragmentActivity.dispatchFragmentsOnCreateView(FragmentActivity.java:405)
at android.support.v4.app.FragmentActivity.onCreateView(FragmentActivity.java:387)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:780)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:730)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:863)
at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:824)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:866)
at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:824)
at android.view.LayoutInflater.inflate(LayoutInflater.java:515)
at android.view.LayoutInflater.inflate(LayoutInflater.java:423)
at android.view.LayoutInflater.inflate(LayoutInflater.java:374)
at android.support.v7.app.AppCompatDelegateImpl.setContentView(AppCompatDelegateImpl.java:469)
at android.support.v7.app.AppCompatActivity.setContentView(AppCompatActivity.java:140)
at com.testapp.mobile.android.ui.HomeActivity.onCreate
at android.app.Activity.performCreate(Activity.java:7136)
at android.app.Activity.performCreate(Activity.java:7127)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1271)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2893)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3048)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
E/AndroidRuntime: 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:1808)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6669)
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)