Skip to content

Conversation

@SuthiYuvaraj
Copy link
Contributor

@SuthiYuvaraj SuthiYuvaraj commented Dec 18, 2025

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.OnBackPressed handler in ConnectHandler. The handler checks WebView.CanGoBack() to determine whether the BlazorWebView maintains internal navigation history. If history exists, it calls WebView.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

  • Android
  • Windows
  • iOS
  • Mac

Output Screenshot

Before Issue Fix After Issue Fix
Screen.Recording.2025-12-18.at.7.21.48.PM.mov
Screen.Recording.2025-12-18.at.7.13.08.PM.mov

@dotnet-policy-service dotnet-policy-service bot added the partner/syncfusion Issues / PR's with Syncfusion collaboration label Dec 18, 2025
@vishnumenon2684 vishnumenon2684 added the community ✨ Community Contribution label Dec 18, 2025
@sheiksyedm sheiksyedm added area-blazor Blazor Hybrid / Desktop, BlazorWebView platform/android labels Dec 18, 2025
@SuthiYuvaraj SuthiYuvaraj changed the title Fix for Back navigation different between .net 9 and .net 10 blazor hybrid Fix for BlazorWebView Back Navigation Issues on Android 13+ After Predictive Back Gesture Changes Dec 18, 2025
@sheiksyedm sheiksyedm marked this pull request as ready for review December 18, 2025 15:27
Copilot AI review requested due to automatic review settings December 18, 2025 15:27
Copy link
Contributor

Copilot AI left a 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

Comment on lines 90 to 95
var lifecycleService = services.GetService<ILifecycleEventService>();
if (lifecycleService is LifecycleEventService concreteService)
{
concreteService.AddEvent(nameof(AndroidLifecycle.OnBackPressed), handler);
_onBackPressedHandler = handler;
}
Copy link

Copilot AI Dec 18, 2025

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.

Copilot uses AI. Check for mistakes.
Comment on lines 104 to 112
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;
}
}
Copy link

Copilot AI Dec 18, 2025

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.

Copilot uses AI. Check for mistakes.
Comment on lines 106 to 111
var lifecycleService = MauiContext.Services.GetService<ILifecycleEventService>();
if (lifecycleService is LifecycleEventService concreteService)
{
concreteService.RemoveEvent(nameof(AndroidLifecycle.OnBackPressed), _onBackPressedHandler);
_onBackPressedHandler = null;
}
Copy link

Copilot AI Dec 18, 2025

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.

Copilot uses AI. Check for mistakes.
@jfversluis jfversluis added this to the .NET 10.0 SR3 milestone Dec 19, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area-blazor Blazor Hybrid / Desktop, BlazorWebView community ✨ Community Contribution partner/syncfusion Issues / PR's with Syncfusion collaboration platform/android

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Back navigation different between .net 9 and .net 10 blazor hybrid

4 participants