maui
maui copied to clipboard
NavigationPage BackButtonPressed sent ignores Android OnBackPressed
Description
Android has a global handler for when the Hardware back button is pressed. This is separate from the visual back in the NavigationBar of a NavigationPage. Currently NavigationPage.OnBackButtonPressed() is executed prior to the Android Lifecycle Event handler for OnBackPressed. It also has no arguments passed to know whether the event is related to the NavigationBar or a device back button.
As a result there is no way to prevent a NavigationPage from executing it's back and then overriding the back behavior from the Lifecycle Event handler.
Steps to Reproduce
- Create an app
- Create a custom NavigationPage. Override OnBackButtonPressed so you can see when this is invoke.
- Create two sample pages
ViewA&ViewB - Push ViewA and ViewB in the NavigationPage
- Set the NavigationPage as the MainPage in the Application
- Launch app on Android
- Press the hardware back button on the Android device/emulator
Link to public reproduction project repository
https://github.com/dansiegel/MauiBackBug
Version with bug
7.0.86
Last version that worked well
Unknown/Other
Affected platforms
Android
Affected platform versions
All android versions
Did you find any workaround?
No response
Relevant log output
No response
It looks like all lifecycle.AddAndroid+android.OnBackPressed handlers in any module of MAUI app are called one by one and this chain cannot be interrupted by returning true from android.OnBackPressed (I guess a better mechanism is needed anyway, please see below).
In my case it is Mopups+Prism+MAUI. I would expect that Mopups handles Back button click first and then everything stops. But in fact we have this:
- MAUI handler is called and page navigates back (MAUI handler is always called first as it is registered in MauiAppBuilder constructor, order of these calls does not matter much ConfigureMopups, UsePrism, UseMauiApp);
- Mopups handler is called and popup is about to be closed (it is async);
- Prism handler is called and page navigates back one more time (or we go to Android home screen if it is the main page);
- Quite often it all just randomly crashes or freezes as neither module expects such behaviour.
Above behaviour seems to be wrong and cannot be fixed without patching all 3 modules, and overall looks like a massive showstopper for now.
Any news on this? This is a serious drawback that prevents the use of MAUI in a production app.
Verified this on Visual Studio Enterprise 17.7.0 Preview 3.0. Repro on Android 13.0-API33 .NET 8 with below Project: MauiBackBug.zip
@jfversluis This is a blocker migrating to MAUI.
I'm not entirely sure if I understand what the issue is here and maybe even more: this is then a difference comparing to Xamarin.Forms? How did this behave in Forms and how is that different from .NET MAUI?
In the application output I notice a Android warning as well that suggests adding android:enableOnBackInvokedCallback="true" to your AndroidManifest.xml, that does seem to change the behavior, does that seem to do what you expect more?
Hi @dansiegel. We have added the "s/needs-info" label to this issue, which indicates that we have an open question for you before we can take further action. This issue will be closed automatically in 7 days if we do not hear back from you by then - please feel free to re-open it if you come back to this issue after that time.
@jfversluis in Xamarin.Forms when user click back button it triggers OnBackButtonPressed, but in MAUI it doesn't. You can check with this branch https://github.com/albilaga/MauiPlayground/tree/back_button. As you can see I already added android:enableOnBackInvokedCallback="true" in here
But whenever user hit back button hardware in android, this line is never triggered
@jfversluis Can you think of a workaround on that one, or is MAUI adapted to behave like we were used to in Xamarin.Forms?
if you want to interrupt either back navigation (hardware back or nav bar), you can override OnNavigating, and check the ShellNavigatingEventArgs.Source to see if it is a ShellNavigationSource.Pop or not.
@s4jc we are not using shell. is that still working even when we are not using shell?
This is happening to me as well, I am using Mopups to display a dialog box but when I press Android hardware back button both popup and page is popped. This is a blocker for me as well..
@albilaga Sorry, I think you're right, my proposal will only work for a shell application. Now that I think about it, we might have switched to the shell application approach specifically because of this problem. (We absolutely needed to interrupt the back navigation to do data validations)
I've just came up against this issue when trying to stop users closing pages they shouldn't. Since I am using Prism I was able to workaround using this code.
private bool _backPressed;
protected override bool OnBackButtonPressed()
{
_backPressed = true;
return true; //true or false does not make any difference.
}
public bool CanNavigate(INavigationParameters parameters)
{
if (!_backPressed)
{
return true;
}
_backPressed = false;
return false;
}
android:enableOnBackInvokedCallback="true"
Removing this makes the backbuttonpressed work actually.