I have 3 Activities: Main, Login, Wizard.
For each Activity I have separate Navigation Graph with fragment destinations.
Main Nav Graph has also Login Activity destination to launch Login screen on logout.
App seems to work correctly when launched from Action.MAIN launcher intent.
BUT I experience problem when using Deep Link. I would like to add URI to Login Nav Graph (Change Password Fragment). This Nav Graph uses separate NavHostFragment. I have used 2 approaches.
Directly add Deep Link to Change Password Fragment Destination in Login Nav Graph -> Deep Links navigate only to START DESTINATION (Login Fragment Destination). Here also Back button does NOT work correctly, i.e. finishing app instead returning to Main Nav Graph Main Destination.
Add Deep Link to Login Activity Destination in Main Nav Graph and again and here Back button does work correctly, I as expected landed on Login Fragment Destination. BUT here I want to manually navigate to Change Password Fragment Destination and I experience another problem, i.e. the Intent Action.View with Uri data is not delivered into this Login Activity destination. It is only delivered to Main Activity which host Main Nav Graph.
To sum up. I think this Deep link behaviour between multiple Nav Graphs connected by Activity Destinations does NOT work as it should. I do not know whether there are any solutions to this.
Can I retrieve Deep Link Arguments (Uri data) from NavController somehow? Or the only solution is to get it from getIntent().data? Here as I say this Intent is not forwarded to final destination Activity, but only to first Activity in the created stack of Activities.
Now I returned to manually handling Deep Links without Android Navigation Architecture as it seems useless if there is more complex navigation structure than single Nav Graph with single Activity and only inner Fragment navigation.
Related
So for example I have two fragments:
start fragment which is used as start destination of my nav grapth
fragment for a deep link
When I open link from email it opens my app activity (recreats it if was already opened), then opens start destionation fragment and then opens deep link fragment and when I press back button it returns to start destionation fragment but I don't want such behaviour, I want it to close app instead, so fragment deep link behave as a start destination fragment
You can do this in several ways:
If you can change your start destination, use the deeplink fragment as start destination, but I guess you have some logic in your start destination and want to navigate to the deeplink programmatically under specified conditions. In that case this solution is not applicable.
by popping the backstack before navigating programmatically to the deeplink:
// remove start destination fragment
findNavController().popBackStack()
findNavController().navigate(Uri.parse(<your_deeplink>))
By killing the activity from the deeplink fragment. Listen for onBackPressDispatcher in the fragment, and call requireActivity().finish() from the fragment to kill the Activity. This medium post explains in the detail the onBackPressDispatcher callback.
I have single activity and multiple fragments using android navigation component. I am using implicit deep link of navigation component. The uri I get from email, when clicked, creates another app instance so the app stack looks like
My app (Instance1)
|
Email app(eg gmail)(clicked on link)
|
My app (Instance2)
What I want is to have single instance and cleared fragment backstack. I have already tried activity launchModes as "singleTop" and "singleInstance". They do keep the single app instance but my deeplink navigation didn't work in that case. Even after clicking the link, app was on top but there was no navigation, I am still seeing the fragment from where I left and not the destination of deeplink.
im currently working on an app, and i want to be able to share images to my app.
with multiple activities this doesn't seem to be a problem, since you define your activity as intent receiver.
however how would i do this, with the single activity architecture google is pushing with its navigation api ?
should the single main activity handle it or does it make sense to create a second activity in this scenario.
i couldn't really find anything on that topic in the android dev docs
Pass Uri to your navController instead of navigating manually by fragment id.
val deeplink = Uri.parse("android-app://androidx.navigation.app/yourFragmentId")
findNavController().navigate(deeplink)
Unlike navigation using action or destination IDs, you can navigate to any URI in your graph, regardless of whether the destination is visible. You can navigate to a destination on the current graph or a destination on a completely different graph.
When navigating using URI, the back stack is not reset. This is unlike other deep link navigation, where the back stack is replaced when navigating. popUpTo and popUpToInclusive, however, still remove destinations from the back stack just as though you had navigated using an ID.
I'm trying to implement session expiry in my app. So when the user token has expired, I want to navigate to the Login Fragment and clear all existing destinations on the back stack. I know this is achievable with popUpTo and popUpToInclusive but a lot of conditional navigation is going on and the destination to popUpTo can't be determined at the point of navigating to the Login Fragment. Is there a way to simply navigate to a new fragment and clear every other destination on the back stack?
You can use app:launchSingleTop="true" in fragment action in navigation graph xml file.
When I open the app from a deeplink (user clicks on URL) and press back button I expect user to navigate to a previous fragment in my navigation graph but it just exits the app.
The documentation says that back navigation should work the same way as if it the user got to that screen naturally.
Can I somehow specify the desired backstack in my navigation graph? Or can be backstack formed automatically after a deeplink? For older version of the library I found out that after back press it should navigate to the root of my navigation graph but that does not happen.
I’m using the navigation library from Android architecture components (version 1.0.0-beta01).
I found out what's going on here, for explicit deep links its supposed to go to a new back stack which is what you app would have if a user had naturally navigated to the view not the existing back stack (existing stack is cleared.
When a user opens your app via an explicit deep link, the task back stack is cleared and replaced with the deep link destination. When nesting graphs, the start destination from each level of nesting—that is, the start destination from each element in the hierarchy—is also added to the stack. This means that when a user presses the Back button from a deep link destination, they navigate back up the navigation stack just as though they entered your app from its entry point.
For implicit its a bit strange. You can make it do what explicit does but setting Intent.FLAG_ACTIVITY_NEW_TASK otherwise the back button and the navigation up button do two separate things:
The back button will do as you might expect, it will go back in your apps existing back stack and load that fragment.
The up button however will clear the a back stack and make a new one as if it was an explicit link.
If the flag is not set, you remain on the task stack of the previous app where the implicit deep link was triggered. In this case, the Back button takes you back to the previous app, while the Up button starts your app's task on the hierarchical parent destination within your navigation graph.kquote
Source: Android Documentation
As describe here back button should return to the previous fragment, you can set it manually in Java like this: button.setOnClickListener(Navigation.createNavigateOnClickListener(R.id.next_fragment, null));
In Kotlin like that: button.setOnClickListener(Navigation.createNavigateOnClickListener(R.id.next_fragment, null))
The Android system maintains a back stack containing the last visited destination. The first destination of your app is placed on the stack when the user opens the app. Each call to the navigate() method puts another destination on the top of the stack. Conversely, pressing the Up or Back button calls the NavController.navigateUp() and NavController.popBackStack() methods, respectively, to pop the top destination off of the stack.
Make sure that you are using NavHostFragment and not <fragment> in your hosting fragment activity.