11using System ;
22using System . Threading . Tasks ;
3+ using Android . Window ;
34using Android . Webkit ;
45using Android . Widget ;
56using Microsoft . Extensions . DependencyInjection ;
@@ -23,6 +24,7 @@ public partial class BlazorWebViewHandler : ViewHandler<IBlazorWebView, AWebView
2324 private AndroidWebKitWebViewManager ? _webviewManager ;
2425 internal AndroidWebKitWebViewManager ? WebviewManager => _webviewManager ;
2526 private AndroidLifecycle . OnBackPressed ? _onBackPressedHandler ;
27+ BlazorWebViewPredictiveBackCallback ? _predictiveBackCallback ;
2628
2729 private ILogger ? _logger ;
2830 internal ILogger Logger => _logger ??= Services ! . GetService < ILogger < BlazorWebViewHandler > > ( ) ?? NullLogger < BlazorWebViewHandler > . Instance ;
@@ -127,12 +129,28 @@ protected override void ConnectHandler(AWebView platformView)
127129 lifecycleService . AddEvent ( nameof ( AndroidLifecycle . OnBackPressed ) , handler ) ;
128130 _onBackPressedHandler = handler ;
129131 }
132+
133+ if ( OperatingSystem . IsAndroidVersionAtLeast ( 33 ) && _predictiveBackCallback is null )
134+ {
135+ if ( Microsoft . Maui . ApplicationModel . Platform . CurrentActivity is not null )
136+ {
137+ _predictiveBackCallback = new BlazorWebViewPredictiveBackCallback ( this ) ;
138+ Microsoft . Maui . ApplicationModel . Platform . CurrentActivity ? . OnBackInvokedDispatcher ? . RegisterOnBackInvokedCallback ( 0 , _predictiveBackCallback ) ;
139+ }
140+ }
130141 }
131142
132143 private const string AndroidFireAndForgetAsyncSwitch = "BlazorWebView.AndroidFireAndForgetAsync" ;
133144
134145 protected override void DisconnectHandler ( AWebView platformView )
135146 {
147+ if ( OperatingSystem . IsAndroidVersionAtLeast ( 33 ) && _predictiveBackCallback is not null )
148+ {
149+ Microsoft . Maui . ApplicationModel . Platform . CurrentActivity ? . OnBackInvokedDispatcher ? . UnregisterOnBackInvokedCallback ( _predictiveBackCallback ) ;
150+ _predictiveBackCallback . Dispose ( ) ;
151+ _predictiveBackCallback = null ;
152+ }
153+
136154 // Clean up lifecycle event handler to prevent memory leaks
137155 if ( _onBackPressedHandler != null )
138156 {
@@ -262,5 +280,43 @@ public virtual async Task<bool> TryDispatchAsync(Action<IServiceProvider> workIt
262280
263281 return await _webviewManager . TryDispatchAsync ( workItem ) ;
264282 }
283+
284+ sealed class BlazorWebViewPredictiveBackCallback : Java . Lang . Object , IOnBackInvokedCallback
285+ {
286+ WeakReference < BlazorWebViewHandler > _weakBlazorWebViewHandler ;
287+
288+ public BlazorWebViewPredictiveBackCallback ( BlazorWebViewHandler handler )
289+ {
290+ _weakBlazorWebViewHandler = new WeakReference < BlazorWebViewHandler > ( handler ) ;
291+ }
292+
293+ public void OnBackInvoked ( )
294+ {
295+ // KeyDown for Back button is handled in BlazorAndroidWebView.
296+ // Here we just need to check if it was handled there.
297+ // If not, we propagate the back press to the Activity's OnBackPressedDispatcher.
298+ if ( _weakBlazorWebViewHandler is not null && _weakBlazorWebViewHandler . TryGetTarget ( out var handler ) )
299+ {
300+ var webView = handler . PlatformView as BlazorAndroidWebView ;
301+ if ( webView is not null )
302+ {
303+ var wasBackNavigationHandled = webView . BackNavigationHandled ;
304+ // reset immediately for next back event
305+ webView . BackNavigationHandled = false ;
306+
307+ if ( ! wasBackNavigationHandled )
308+ {
309+ if ( webView . CanGoBack ( ) ) // If we can go back in WeView, Navigate back
310+ {
311+ webView . GoBack ( ) ;
312+ return ;
313+ }
314+ // Otherwise propagate back press to Activity
315+ ( Microsoft . Maui . ApplicationModel . Platform . CurrentActivity as AndroidX . AppCompat . App . AppCompatActivity ) ? . OnBackPressedDispatcher ? . OnBackPressed ( ) ;
316+ }
317+ }
318+ }
319+ }
320+ }
265321 }
266322}
0 commit comments