为什么 .NET MAUI WebView 无法打开非其来源网站的链接?

问题描述 投票:0回答:3

我正在使用 Visual Studio 2022 开发一个包含 WebView 对象的 NET MAUI 移动应用程序。 源网站 mywebsite.com 已正确加载,并且其所有内部链接均有效。

我的目标是确保当单击指向不同网站(例如 microsoft.com)的链接时,该网站会在用户手机的默认浏览器中打开。

问题是,当我单击 microsoft.com(或任何其他外部链接)时,没有任何反应。

无论 HTML 中的目标是否设置为 _blank,这些外部链接都不会触发导航事件;此处提供的解决方案(MAUI Webview target =“_blank”href重定向不适用于android)和此处(拦截用户在WebView(.NET Maui)中点击的所有链接)对我不起作用。

单击 mywebsite.com 内部链接时会定期触发导航事件。

我的 MainPage.xaml.cs 包含:

public MainPage()
{
    InitializeComponent();
    // Subscribe to the Navigating event
    proteoWebView.Navigating += OnNavigating;
    // Subscribe to the Navigated event
    proteoWebView.Navigated += OnNavigated;
}

private void OnNavigating(object sender, WebNavigatingEventArgs e)
{
    // Check if the URL is external
    if (!e.Url.StartsWith("https://mywebsite.com"))
    {
        // Cancel the navigation in the WebView
        e.Cancel = true;
        // Open the URL in the default browser of the user's phone
        Launcher.TryOpenAsync(e.Url);
    }
}

我的 MainPage.xaml 包含:

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="ProteoApp.MainPage"
             NavigationPage.HasNavigationBar="False">
    <Grid>
        <WebView 
                 x:Name="proteoWebView"
                 Source="https://mywebsite.com"
                 Grid.Row="0"
                 Grid.Column="0"
                 VerticalOptions="FillAndExpand"
                 HorizontalOptions="FillAndExpand"/>
    </Grid>
</ContentPage>

其他信息:我正在使用 Visual Studio 2022、.NET 7.0 进行开发,并且我在 Pixel 5 – API 33 (13.0 Android) 模拟器上遇到了该问题。

c# android webview maui visual-studio-2022
3个回答
1
投票

我应该纠正自己。

具有 target="_blank" 属性的外部链接不会触发 OnNavigating 事件。 没有 target="_blank" 属性的外部链接会触发 OnNavigating 事件。

此外,为了打开用户手机的默认浏览器,必须执行异步调用:

private void OnNavigating(object sender, WebNavigatingEventArgs e)
    {
        if (!e.Url.StartsWith("https://mywebsite.com"))
        {
            e.Cancel = true;
            Task.Run(async () =>
            {
                await Launcher.OpenAsync(e.Url);
            });
        }

正如我所提到的,上面的代码仅适用于没有 target="_blank" 属性的外部链接。 为了使其也适用于具有 target="_blank" 属性的外部链接,需要将此代码添加到 OnNaviged 事件中:

private void OnNavigated(object sender, WebNavigatedEventArgs e)
    {
        //The following code changes the target of all the links in _self
        proteoWebView.EvaluateJavaScriptAsync(@"(function() {
            var links = document.getElementsByTagName('a');
            for (var i = 0; i < links.length; i++)
            {
                links[i].setAttribute('target', '_self');
            }
        })()");
    }

这解决了我的问题。


0
投票

就我而言,无论链接的目标如何定义,在 Android 中我永远无法导航到外部链接(使用

Navigating
WebView
事件)。

我解决了这个问题,就像我为 Xamarin.Forms 项目所做的那样:

创建自定义

WebChromeClient
:

/// <summary>
/// External links tapped in a WebView don't open in .Net MAUI.
/// In order to be able to open links in Android in the web view, a <see cref="ExtendedWebViewChrome"/>
/// can be set to intercept taps on external links and open the default browser.
/// </summary>
internal class ExtendedWebViewChrome : WebChromeClient
{
    /// <inheritdoc/>
    public override bool OnCreateWindow(WebView view, bool isDialog, bool isUserGesture, Message resultMsg)
    {
        // Get information on where the user tapped in the web view.
        var result = view.GetHitTestResult();

        if (result == null)
        {
            return base.OnCreateWindow(view, isDialog, isUserGesture, resultMsg);
        }

        // Extract the external link URL of the link from the hit result Extra property.
        var externalLinkUrl = result.Extra;

        try
        {
            var externalLinkUri = Uri.Parse(externalLinkUrl);

            Context context = view.Context;
            Intent browserIntent = new Intent(Intent.ActionView, externalLinkUri);
            context.StartActivity(browserIntent);

            return false;
        }
        catch (Exception exception)
        {
            System.Diagnostics.Debug.WriteLine(
                $"There was an error trying to open the following link: {externalLinkUrl}.\n " +
                $"Exception occurred: {exception.Message} at {exception.StackTrace}");
        }

        // Something went wrong, return what parent would return.
        return base.OnCreateWindow(view, isDialog, isUserGesture, resultMsg);
    }
}

然后您可以在自定义渲染器中使用它(仍然没有迁移到 MAUI 处理程序):

/// <summary>
/// Sets the AllowFileAccess flag to true and sets horizontal scroll to the right for RTL locales.
/// </summary>
public class ExtendedWebViewRenderer : WebViewRenderer
{
    /// <summary>
    /// Default constructor.
    /// </summary>
    public ExtendedWebViewRenderer(Context context) : base(context) { }

    /// <summary>
    /// Fires on element changed.
    /// </summary>
    protected override void OnElementChanged(ElementChangedEventArgs<WebView> e)
    {
        base.OnElementChanged(e);

        if (Control == null)
        {
            return;
        }

        // Enables or disables file system access within WebView.
        // This setting was by default true before API level 30 but now it is needed to be set explicitly.
        // It needs to be set before the attempt to load the HTML is made.
        Control.Settings.AllowFileAccess = true;

        // External links tapped in a WebView  don't open in .NET MAUI.
        // In order to solve the issue, a custom web client can be set to intercept link taps.
        Control.SetWebChromeClient(new ExtendedWebViewChrome());

        ...            
    }
}

奇怪的是,这个问题只发生在 Android 中,并且如果您使用

WebView
设置
UrlWebViewSource
源。如果使用
HtmlWebViewSource
,则可以使用
Navigating
事件处理程序打开外部链接。


0
投票

当我在 MAUI 中工作时,我注意到一些 XAML 操作(例如附加到事件然后在后面的代码中处理)似乎是错误的。这也不例外。不要在 XAML 中附加事件,而是在 InitializeComponent 之后的 C# 页面构造函数中附加事件。

webView.Navigating += WebView_Navigating;

这使得我的活动可以毫无问题地启动。 XAML 有问题,如果它不能按预期工作,请尝试使用 C#。

© www.soinside.com 2019 - 2024. All rights reserved.