Jetpack Compose - How to Identify user is coming via back navigation - android

I come across requirement where I have to do certain task when user is coming via back navigation flow.
Suppose : Currently user is on A Screen and on button click it got navigated to B Screen.
On B Screen I'm using BackHandler to navigate user to back screen using navController.navigateUp() as this code working perfectly to navigate user to back screen.
But I'm unable to identify is user coming via back navigation or initial launch flow.
Already Tried Solution : val isFromBackNavigation = parentNavController.currentBackStackEntryAsState().value?.destination?.route == AppNav.Wishlist.route
This returns true for initial launch also.

Related

How to go back and forth between 2 destinations in compose navigation

I am implementing a login system with Jetpack Compose and I'm using Compose Navigation. I have an "onboarding" screen where the user can choose whether they want to login or sign up. Fromn both the login and sign up screen the user can navigate to the other one, but let's say they keep navigating back and forth, then the back stack is full of those screens.
How should I handle the back stack in this case? I thought about checking if the destination is already present in the back stack and pop to that, but it looks like this has some pitfalls (the user could have visited one of those pages before and pop several destinations for example).
I'd also like to pop the whole login flow when done but I don't get how
How should I handle the back stack in this case? I thought about
checking if the destination is already present in the back stack and
pop to that
In a way you're right, but you don't need to do much of it yourself if you have circular navigation (this is what you describe). You can just use popUpTo from the signup page (if the login is supposed to be the "default" like such:
navController.navigate(loginRoute) {
popUpTo(loginRoute) {
inclusive = true
}
}
The inclusive = true is necessary because you also want to pop the login from the stack itself:
If your stack looks like AB and you navigate back to A, you would pop just B and be left with AA (thus able to navigate back to A again while you're at A).
I'd also like to pop the whole login flow when done but I don't get how
Similar to your initial idea, just pop the entire backstack after you're done using navController.navigate(yourRoute) { popUpTo(0) }

How to exit the app when the user press back button in navigation component?

I'm trying to implement this scenario. I have a sign in screen with a sign in button. When the user clicks the button and gets authenticated, I send the user to the profile screen. The problem comes when the user hits the back button. Instead of existing the app, it goes back to the sign in screen, which is bad. If I have had activities, I have called finish() in the sign in activity when going forward to profile activity, and when the user pressed back, it quits the app. How to do the same thing using navigation?
You need to clear the navigation stack. You can do it in many ways.
For example, if you know that you only have a single item in your back stack, you can use popBackStack:
navController.popBackStack()
navController.navigate(Destinations.Profile)
Or you can use popUpTo and specify the first destination you wanna pop up, and add inclusive parameter:
navController.navigate(Destinations.Profile) {
popUpTo(Destinations.Login) {
inclusive = true
}
}
For creating viewModel instance every time when composable is started you need do this:
val viewModel= remember { MyViewModel() }
That's it. No need in popBackStack and e.t.c.
But i recommend you to found way to listen changes of data in your viewModel.
That will be more clear. JetPack Compose gives you another way how to write code and make Android application, so use it)

Deep Linking with pin screen and firebase push notification

My goal: I want to send push notification to users. When user tap on that notification, user should navigate to a specific fragment named HitoryDetailsFragment.
What I did: I implemented FirebaseInstanceIdService & FirebaseMessagingService and I'm able to catch Firebase message which is sent from a backend server. I implemented the deep link by an "implicit deeplink". I implemented the navigation using nested navigation graphs. History related screens are placed in a separate navigation graph, graph_history.xml.
What is the issue: When the application is open, everything works fine. I tap on the notification -> I get redirected to HistoryDetailFragment, and when I press the back button, it returns me to the HistoryListFragment. But when the app is closed (not in the recent apps tray), instead of HistoryDetailsFragment, the SplashFragment is opened, and after that I get redirected to the HomeFragment (which is correct, because that's how the flow should work). But, how can I redirect the user to the HistoryDetails, when the app is closed? Also, I should show a Pin screen, where the user should input his pin, if he did not before, before showing the HistoryDetailsFragment.
My code is like below.
private fun createPendingIntent(history: History?) = NavDeepLinkBuilder(this).run {
setGraph(R.navigation.graph_main)
history?.let {
//todo when the app is not open (not in tray of recent apps), this destination does not work
//this instead navigates to SplashFragment
//which is correct, because we have not entered the pin, so we are not entitled to open the history detail screen
//but how do I handle this case?
setDestination(if (it.type.isNews) R.id.nav_history_news else R.id.nav_history_detail)
setArguments(if (it.type.isNews) HistoryNewsFragmentArgs(it.link).toBundle() else HistoryDetailFragmentArgs(it.id).toBundle())
}
createPendingIntent()
}
The main nav graph:
History graph:

Back button closes app after navigation but not before

I've got an xamarin forms/prism app, and my hardware back button does nothing on the initial page.
If I navigate to another page, it closes the app as expected. If I navigate to the initial page again, it also closes the app - but not if the app just started.
Is there something I'm missing?
My class App mainly has an OnInitialized that navigates to the initial page:
protected override void OnInitialized()
{
NavigationService.NavigateAsync( "MyMasterDetail/MyNavigationPage/StartPage", animated: false );
}
On MyMasterDetail, there are buttons that navigate to MyNavigationPage/SettingsPage and other pages like that.
It doesn't matter if I use Android 5 in Emulator or Android 6 on a real device, the behaviour is the same.
When using a MasterDetail as your root, you are not actually navigating anywhere else. You are simply changing the Detail property of the MasterDetail to another Page. This is not a navigation action. So you are not really navigating. If you want to fake it, you need to add the INavigationPageOptions to your MyNavigationPage and set the ClearNavigationStackOnNavigation property to false. This will continuously push new pages onto the MasterDetailPage.Detail MyNavigationPage without clearing the stack (PopToRoot). Then this will allow your bac button to behave like you are wanting.

How do I manipulate the Android activity stack?

Here's my two scenarios.
1 -
User opens app for the first time ever from android home screen
User is presented with "first time" screen (backed by first time activity, lets call it A)
User hits back button
user is returned to android home screen
2 -
User opens app for second time
User is presented with the main list screen of the application (backed by a list activity, let's call it B)
User hits back button
User is returned to android home screen
I'm already aware of numerous ways to detect whether it's the first time opening the app or not.
The problem is in having the back button return to the home screen rather than a routing activity that decides which screen to forward to.
Currently My app has an activity to decide where to route (lets call it R) the problem is, My stack either looks like R -> A or R -> B
I want A or B to replace R on the stack when they open, and if the user hits back, then they go to the android home screen, not back to R.
Having a collaborator that sets the view for A and B is also not really workable as B extends androids concrete implementation of a list Activity to get most of its functionality.
Any ideas?
I want A or B to replace R on the
stack when they open, and if the user
hits back, then they go to the android
home screen, not back to R.
Call finish() in R after it calls startActivity() to trigger the opening of A or B.

Categories

Resources