如果“target=_blank”,Xamarin Android WebView 不会触发导航

Posted

技术标签:

【中文标题】如果“target=_blank”,Xamarin Android WebView 不会触发导航【英文标题】:Xamarin Android WebView don't fire navigating if "target=_blank" 【发布时间】:2021-12-17 16:57:45 【问题描述】:

我在 xamarin 中使用 webview,我遵循了许多教程来处理导航,并且一切正常。 我的问题是:当一个锚标签有一个 target="_blank" 时,导航事件永远不会被触发。

我看到周围有人给出了一个 javascript 解决方案,该解决方案删除了​​ target=_blank 并将其附加在 href 链接的末尾。

这真的是正确的方法吗?看有线..

谢谢

这是 xamarin.android 渲染器中的初始化

        protected override void OnElementChanged(ElementChangedEventArgs<WebView> e)
    
        base.OnElementChanged(e);
        global::Android.Webkit.WebView.SetWebContentsDebuggingEnabled(true);
        if (e.OldElement != null)
        
            Control.RemoveJavascriptInterface("jsBridge");
            ((HybridWebView)Element).Cleanup();
                    
        if (e.NewElement != null)
        
            Control.Settings.JavaScriptEnabled = true;
            Control.Settings.DomStorageEnabled = true;
            Control.Settings.JavaScriptCanOpenWindowsAutomatically = true;
            Control.Settings.SetSupportMultipleWindows(true);
            Control.Settings.AllowFileAccessFromFileURLs = true;
            Control.Settings.AllowUniversalAccessFromFileURLs = true;
            Control.Settings.UserAgentString = Control.Settings.UserAgentString  + " crmvw";                
            Android.Webkit.WebChromeClient xCC = new CustChromeWebViewClient(_context);
            Control.SetWebChromeClient(xCC);
            Control.SetWebViewClient(new CrmWebViewClient(this, $"javascript: JavascriptFunction"));     
            Control.AddJavascriptInterface(new JSBridge(this), "jsBridge");     
            Control.LoadUrl(((HybridWebView)Element).Uri);
        
    

这是我的导航事件,当锚点有 target=_blank 时从未触发

        private void webv_Navigating(object sender, WebNavigatingEventArgs e)
    
        if (IsFirstLoad)  
            IsBusy = true;
            IsFirstLoad = false;
        

        if (e.Url.ToLower().StartsWith("tel:") || e.Url.ToString().StartsWith("wtai:") || e.Url.ToLower().StartsWith("sms:") || e.Url.ToLower().StartsWith("mailto:"))
        
            e.Cancel = true;
        
    

这里是我的自定义 WEBView 中 URL 的覆盖函数

        public override bool ShouldOverrideUrlLoading(Android.Webkit.WebView view, Android.Webkit.IWebResourceRequest request)
    
        Android.Net.Uri url = request.Url;            
        if (url.ToString().StartsWith("tel:") || url.ToString().StartsWith("wtai:"))
        
            Xamarin.Essentials.PhoneDialer.Open(UtilityXam.Contact.GetPhoneFromhtml(url.ToString()));
            return true;
        else if (url.ToString().StartsWith("mailto:"))
        
            UtilityXam.Contact xE = new UtilityXam.Contact();
            string xEmail = UtilityXam.Contact.GetEmailFromHTML( url.ToString());
            var xTask = xE.SendEmail("","",new System.Collections.Generic.List<string>() xEmail );
            return true;
        
        else if (url.ToString().StartsWith("sms:"))
        
            UtilityXam.Contact xE = new UtilityXam.Contact();
            string xPh = UtilityXam.Contact.GetPhoneFromHTML(url.ToString());
            var xTask = xE.SendSMS("", "", new System.Collections.Generic.List<string>()  xPh );
        
        else
        
            view.LoadUrl(url.ToString());
        
        view.SetDownloadListener(new CrmDownloadListener(_context));
        return true;
    

【问题讨论】:

这solution 是否回答了您的问题。检测url并检查是否有target=blank。 我已经找到并且我已经尝试过这个解决方案,但它对我不起作用。我在导航事件中添加了 JS 函数并通过 webview 对其进行评估。当我单击目标 _blank 锚时,不会触发事件导航。我的问题是,为什么事件没有被触发? 您使用的是 Xamarin.forms 还是 Xamarin.Android? 点击其他 url 而不是目标 _blank 锚点时是否触发事件。 是的,另一个 URL 非目标 _blank 被触发,并且导航事件在 Xamarin.Forms 中。我在 Xamarin.Android 中也有一个渲染器,我在 Element changed 事件中初始化了 webview,我启用了对多个窗口的支持,我还添加了一个自定义 chromeclient 和一个自定义 webview,以便添加 javascript 函数来调用 c#。 【参考方案1】:

在 Jack Hua 的大力帮助下,我能够解决问题。 在混合渲染器的 OnElementChanged 中,我设置了对多个窗口的支持。

Control.Settings.SetSupportMultipleWindows(true);

接下来我必须在自定义 chrome webview 中管理 onCreateWindow 事件。 这里是从 Jack 建议的链接中转换为 c# 的代码。

        public override bool OnCreateWindow(Android.Webkit.WebView view, bool isDialog, bool isUserGesture, Android.OS.Message resultMsg)
    
        Android.Webkit.WebView newWebView = new Android.Webkit.WebView(_context);
        view.AddView(newWebView);
        Android.Webkit.WebView.WebViewTransport transport = (Android.Webkit.WebView.WebViewTransport) resultMsg.Obj;
        transport.WebView = newWebView;
        resultMsg.SendToTarget();
        return true;
    

【讨论】:

您能否稍后接受这个答案(点击这个答案左上角的☑️),以便我们可以帮助更多有同样问题的人:)。 这会在 chrome 中打开新窗口,而不是在应用内浏览器中【参考方案2】:

这是自 v4.8.0.1364 以来 Xamarin Forms 中引入的错误(至少根据错误报告)

您现在可以通过从 url 中删除 target="_blank" 或设置属性来解决它

webView.Settings.SetSupportMultipleWindows(true);

我已经为我们的应用程序修复了它,方法是在一些已经在内容上运行的替换逻辑中剥离 target="_blank"target='_blank'

Xamarin Forms github 报告了多个未解决的问题

[Bug] Cannot open URLs with WebView android when the target is _blank #12917

[Bug] Android WebView's Navigating and Navigated events not fired #12852

【讨论】:

那些指向 GitHub 问题的链接非常宝贵;而不是 SetSupportMultipleWindows(true),将其设置为 false 使所有 target="_blank" 链接开始通过我的 Navigating 事件触发【参考方案3】:

我尝试了一种完全不同的方法,因为上述答案并没有真正帮助(我的目标 _blank 链接将始终在新的 chrome 实例中打开,而不是在应用内浏览器中打开)。

首先,您需要将 SetSupportMultipleWindows 设置为 false。一旦你这样做了,所有的窗口都会在同一个 webView 中打开:

Control.Settings.SetSupportMultipleWindows(false);

有关如何设置这些设置的更多信息:https://docs.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/custom-renderer/hybridwebview

接下来,我所做的只是更改后退按钮的行为,以确保后退按钮不会关闭应用程序而是导航 webview 页面(HybridWebView 是我在第一步中创建的自定义 webview)。

    HybridWebView _browser;
    public MainPage()
    
        _browser = new HybridWebView
        
            Source = "https://brandschutzplaner-stahltragwerke.promat.ch"
        ;

        Content = _browser;
    

    protected override bool OnBackButtonPressed()
    

        base.OnBackButtonPressed();

        if (_browser.CanGoBack)
        
            _browser.GoBack();
            return true;
        
        else
        
            base.OnBackButtonPressed();
            return true;
        
    

【讨论】:

以上是关于如果“target=_blank”,Xamarin Android WebView 不会触发导航的主要内容,如果未能解决你的问题,请参考以下文章

将 target=_blank 添加到 react 按钮中的链接标签不会打开新页面但会禁用它?

target=_blank攻击

target='_blank' 安全漏洞

selenium IDE 回放时出现的问题: Link has target '_blank', which is not supported in Selenium!

目标 =“_blank” 在 IOS 中不起作用

如何在 PyQtWebEngine 中使用 target="_blank" 打开超链接?