MAUI中捕获Blazor WASM页面WebView导航URL的问题
解决MAUI Android中WebView自定义WebViewClient不触发及捕获导航URL的问题
问题根源
在.NET MAUI的WebViewHandler中,base.ConnectHandler()方法会内部设置默认的MauiWebViewClient,覆盖你在CreatePlatformView()中手动设置的自定义WebViewClient,导致自定义类的方法无法触发。
解决方案
1. 正确替换自定义WebViewClient
修改MyWebViewRenderer,在ConnectHandler()中替换Handler的默认WebViewClient属性,确保自定义客户端生效:
[assembly: ExportRenderer(typeof(Microsoft.Maui.Controls.WebView), typeof(MyWebViewRenderer))] namespace MiniApp.Platforms.Android { public class MyWebViewRenderer : WebViewHandler { private CustomWebViewClient _customWebViewClient; public MyWebViewRenderer() : base(WebViewMapper) { _customWebViewClient = new CustomWebViewClient(); _customWebViewClient.UrlChanged += OnUrlChanged; } private void OnUrlChanged(string url) { // 存储最新URL,示例用Preferences持久化 Preferences.Set("LastVisitedUrl", url); // 如需通知MAUI层视图模型,可使用MessagingCenter或绑定属性 // MessagingCenter.Send(this, "UrlUpdated", url); } protected override void ConnectHandler(global::Android.Webkit.WebView platformView) { // 替换默认WebViewClient为自定义实例 WebViewClient = _customWebViewClient; // 启用JavaScript并注册桥接(用于捕获Blazor内部导航) platformView.Settings.JavaScriptEnabled = true; platformView.AddJavascriptInterface(new JsBridge(), "mauiInterop"); base.ConnectHandler(platformView); } protected override void DisconnectHandler(global::Android.Webkit.WebView platformView) { _customWebViewClient.UrlChanged -= OnUrlChanged; base.DisconnectHandler(platformView); } } }
2. 完善自定义WebViewClient捕获URL
修改CustomWebViewClient,添加URL捕获逻辑,覆盖关键导航方法:
public class CustomWebViewClient : WebViewClient { // 定义事件传递URL变更 public event Action<string>? UrlChanged; // 处理外部链接点击导航 public override bool ShouldOverrideUrlLoading(global::Android.Webkit.WebView? view, IWebResourceRequest? request) { var url = request?.Url?.ToString(); if (!string.IsNullOrEmpty(url)) { UrlChanged?.Invoke(url); } // 返回false让WebView处理导航,如需拦截可返回true自行处理 return base.ShouldOverrideUrlLoading(view, request); } // 处理页面开始加载时的URL public override void OnPageStarted(global::Android.Webkit.WebView? view, string? url, Bitmap? favicon) { if (!string.IsNullOrEmpty(url)) { UrlChanged?.Invoke(url); } base.OnPageStarted(view, url, favicon); } // 处理历史记录更新时的URL public override void DoUpdateVisitedHistory(global::Android.Webkit.WebView? view, string? url, bool isReload) { if (!string.IsNullOrEmpty(url)) { UrlChanged?.Invoke(url); } base.DoUpdateVisitedHistory(view, url, isReload); } }
3. 捕获Blazor内部路由导航
由于Blazor WebAssembly是单页应用,内部路由跳转不会触发WebView的URL加载事件,需通过JS桥接捕获:
步骤1:在Blazor项目中添加导航监听
在MainLayout.razor中监听路由变化并通知原生端:
@inject NavigationManager NavigationManager @inject IJSRuntime JSRuntime @implements IDisposable @code { private IDisposable? _navigationSubscription; protected override async Task OnInitializedAsync() { _navigationSubscription = NavigationManager.LocationChanged += async (_, e) => { await JSRuntime.InvokeVoidAsync("notifyUrlChanged", e.Location); }; } public void Dispose() { _navigationSubscription?.Dispose(); } }
步骤2:在Blazor的index.html中添加JS桥接代码
在wwwroot/index.html的<body>末尾添加:
<script> window.notifyUrlChanged = function(url) { // 调用原生MAUI方法存储URL window.mauiInterop.saveLastUrl(url); }; </script>
步骤3:在Android项目中实现JS桥接类
添加JsBridge类,接收Blazor传递的URL:
public class JsBridge : Java.Lang.Object { [JavascriptInterface] [Export("saveLastUrl")] public void SaveLastUrl(string url) { Preferences.Set("LastVisitedUrl", url); // 如需通知视图模型,可使用MessagingCenter // MessagingCenter.Send(this, "UrlUpdated", url); } }
注意事项
- 确保WebView启用JavaScript,否则Blazor内部路由的JS桥接无法生效。
- 对于.NET 8,
ExportRenderer仍可正常使用,后续可按需迁移到MAUI官方推荐的Handler映射扩展方式。
内容的提问来源于stack exchange,提问作者boss
相关产品推荐
相关产品推荐

