-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Fix for BlazorWebView Back Navigation Issues on Android 13+ After Predictive Back Gesture Changes #33213
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR fixes BlazorWebView back navigation on Android 13+ by implementing an OnBackPressed lifecycle event handler that checks for WebView navigation history before allowing page navigation. The fix extends the predictive back gesture support introduced in PR #32461 to include BlazorWebView components, and adds a cleanup mechanism for lifecycle event handlers to prevent memory leaks.
Key Changes
- Adds OnBackPressed handler registration in BlazorWebViewHandler.ConnectHandler that checks WebView.CanGoBack() before allowing page pop
- Implements RemoveEvent method in LifecycleEventService to support proper handler cleanup in DisconnectHandler
- Updates public API surface to track the new ConnectHandler override
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 7 comments.
| File | Description |
|---|---|
| src/Core/src/LifecycleEvents/LifecycleEventService.cs | Adds internal RemoveEvent method to enable lifecycle event handler cleanup |
| src/BlazorWebView/src/Maui/Android/BlazorWebViewHandler.Android.cs | Implements ConnectHandler/DisconnectHandler overrides to register/unregister OnBackPressed handler for WebView back navigation |
| src/BlazorWebView/src/Maui/PublicAPI/net-android/PublicAPI.Unshipped.txt | Tracks new ConnectHandler override as public API surface change |
| var lifecycleService = services.GetService<ILifecycleEventService>(); | ||
| if (lifecycleService is LifecycleEventService concreteService) | ||
| { | ||
| concreteService.AddEvent(nameof(AndroidLifecycle.OnBackPressed), handler); | ||
| _onBackPressedHandler = handler; | ||
| } |
Copilot
AI
Dec 18, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The code casts ILifecycleEventService to LifecycleEventService to call AddEvent, but RemoveEvent is also internal and requires the same cast. Consider either: (1) Making RemoveEvent part of ILifecycleEventService or ILifecycleBuilder interface for better API design, or (2) Adding a comment explaining why this internal cast is necessary. The current approach creates coupling to the concrete implementation.
| if (_onBackPressedHandler != null && MauiContext?.Services != null) | ||
| { | ||
| var lifecycleService = MauiContext.Services.GetService<ILifecycleEventService>(); | ||
| if (lifecycleService is LifecycleEventService concreteService) | ||
| { | ||
| concreteService.RemoveEvent(nameof(AndroidLifecycle.OnBackPressed), _onBackPressedHandler); | ||
| _onBackPressedHandler = null; | ||
| } | ||
| } |
Copilot
AI
Dec 18, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The compound null check can be simplified for better readability. Consider checking MauiContext?.Services first and storing it in a local variable, then checking _onBackPressedHandler separately. This makes the code flow clearer and avoids repeated null-conditional access.
| var lifecycleService = MauiContext.Services.GetService<ILifecycleEventService>(); | ||
| if (lifecycleService is LifecycleEventService concreteService) | ||
| { | ||
| concreteService.RemoveEvent(nameof(AndroidLifecycle.OnBackPressed), _onBackPressedHandler); | ||
| _onBackPressedHandler = null; | ||
| } |
Copilot
AI
Dec 18, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The same cast pattern (ILifecycleEventService to LifecycleEventService) is repeated in both ConnectHandler and DisconnectHandler. Consider extracting this to a helper method or property to reduce code duplication and make the intent clearer. For example, a private method like TryGetLifecycleEventService() that returns the concrete service or null.
Co-authored-by: Copilot <[email protected]>
Issue Description
BlazorWebView back navigation stopped working in .NET 10 on Android. When the user presses the back button while viewing a BlazorWebView with navigable history, the entire page is popped instead of navigating back within the WebView content
RootCause
The AndroidLifecycle.OnBackPressed lifecycle event system introduced for Android 13+ predictive back gesture support intercepts back navigation. Since BlazorWebView doesn't register a handler to check WebView.CanGoBack(), the system pops the entire page instead of allowing the WebView to navigate its internal history first, breaking the back navigation behavior that worked in .NET 9.
Description of Change
PR #32461 introduced distributed back navigation handling for Android 13+ predictive back gesture support. This PR extends that implementation to include BlazorWebView
BlazorWebViewHandler.Android.cs:
Added an
AndroidLifecycle.OnBackPressedhandler in ConnectHandler. The handler checksWebView.CanGoBack()to determine whether the BlazorWebView maintains internal navigation history. If history exists, it callsWebView.GoBack()and returns true, ensuring the user navigates backwards within the WebView instead of closing the page. If no internal history exists, it returns false, allowing the standard MAUI navigation stack to handle the back action.LifecycleEventService.cs:
Added
RemoveEvent<TDelegate>method to properly cleanup lifecycle event handlers and prevent memory leaks when handlers are disconnected.Issues Fixed
Fixes #32767
Tested the behaviour on the following platforms
Output Screenshot
Screen.Recording.2025-12-18.at.7.21.48.PM.mov
Screen.Recording.2025-12-18.at.7.13.08.PM.mov