You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 18:33:20