Using WebViewRenderer and WebViewClient causes cancel navigation not working

ChristianKroesChristianKroes USMember ✭✭
edited November 2018 in Xamarin.Android

Hi guys,

im using a custom WebViewRenderer, in OnElementChanged I call this.Control.SetWebViewClient(new FormsWebViewClient(this));

Everything works fine, OnReceivedSslError is fired when using untrusted ssl. But when I want to cancel the navigation like this:

private async void Wv_Navigating(object sender, WebNavigatingEventArgs e)
{
    e.Cancel = true;
}

it is not working, the navigation goes on. Do I need another function in my WebViewClient or Renderer to check for cancel=true and stop loading?

BTW: Everything works fine without using a WebViewClient class and checking SSL error... Any help? Please? :smiley:

Best regards
Chris

Best Answer

Answers

  • BillyLiuBillyLiu Member, Xamarin Team Xamurai

    @ChristianKroes

    I have tested your code, but I can't reproduce your issue. You need to check your WebViewRenderer.
    If you want to stop navigation, you could try to create a class base FormsWebViewClient and override ShouldOverrideUrlLoading method.
    https://stackoverflow.com/questions/19426742/dont-navigate-to-other-pages-in-webview-disable-links-and-references

    Or could you share a demo project that could reproduce this issue?

  • ChristianKroesChristianKroes USMember ✭✭

    Here is my Renderer and WebViewClient:

    [assembly: ExportRenderer(typeof(Xamarin.Forms.WebView), typeof(ExtendedWebViewRenderer))]
    namespace MyNameSpace.Droid.Custom
    {
    public class ExtendedWebViewRenderer : WebViewRenderer
    {
    public ExtendedWebViewRenderer(Context context) : base(context)
    {

        }
    
        protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.WebView> e)
        {
            base.OnElementChanged(e);
    
            this.Control.Settings.BuiltInZoomControls = true;
            this.Control.Settings.DisplayZoomControls = false;
    
            if (e.OldElement == null)
                this.Control.SetWebViewClient(new FormsWebViewClient(this));
        }
    }
    
    internal class FormsWebViewClient : WebViewClient
    {
        ExtendedWebViewRenderer _renderer;
    
        public FormsWebViewClient()
        {
    
        }
    
        public FormsWebViewClient(ExtendedWebViewRenderer renderer)
        {
            _renderer = renderer;
        }
    
        public override void OnReceivedSslError(Android.Webkit.WebView view, SslErrorHandler handler, SslError error)
        {
            AlertDialog.Builder builder = new AlertDialog.Builder((Activity)Forms.Context);
            AlertDialog ad = builder.Create();
            string message = "Zertifikat Fehler";
            switch (error.PrimaryError)
            {
                case SslErrorType.Untrusted:
                    message = "Zertifikat ist nicht vertrauenswürdig."; break;
                case SslErrorType.Expired:
                    message = "Zertifikat ist abgelaufen."; break;
                case SslErrorType.Idmismatch:
                    message = "Zertifikat ID ist fehlerhaft."; break;
                case SslErrorType.Notyetvalid:
                    message = "Zertifikat ist noch nicht gültig."; break;
            }
            message += " Möchten Sie trotzdem fortfahren?";
            ad.SetTitle("SSL Zertifikat Fehler");
            ad.SetMessage(message);
            ad.SetButton("OK", (sender, args) =>
            {
                handler.Proceed();
            });
            ad.SetButton2("Cancel", (sender, args) =>
            {
                handler.Cancel();
            });
            ad.SetIcon(Android.Resource.Drawable.IcDialogAlert);
            ad.Show();
        }
    }
    

    }

    In my view I use the navigating event and it depends if I want the view to load or stop, I want to stop if I show the view in a new page like this:

    private async void Wv_Navigating(object sender, WebNavigatingEventArgs e)
    {
    if (showinnewpage)
    {
    // THIS IS NOT WORKING
    e.Cancel = true;

        await Navigation.PushAsync(new InAppBrowser(header, e.Url, false), true);
    }
    else if ((!_root && e.Url.StartsWith("http")) || e.Url.StartsWith("mailto:"))
    {
        // THIS IS NOT WORKING
        e.Cancel = true;
    
        try
        {
            var uri = new Uri(e.Url);
            Device.OpenUri(uri);
        }
        catch (Exception)
        {
        }
    }
    

    }

    If I click a MAILTO: link I want the current page stay and open the mail client. The mail client opens, but the first page does not stay showing the link...

  • ChristianKroesChristianKroes USMember ✭✭

    Hi BillyLiu,

    thank you very much, now it's working...

    internal class MyFormsWebViewClient : FormsWebViewClient

    AND

    public MyFormsWebViewClient(MyWebViewRenderer renderer) : base(renderer)

    was the problem... :smiley:

  • wagenheimerwagenheimer Member ✭✭

    Just for future reference!

    It works, here is the full code I used. It also fixes another bug where the Scroll of the WebView is not working anymore when using Xamarin Shell.

    using System;
    using Android.Content;
    using Android.Views;
    using Mobile.Droid.Render;
    using Xamarin.Forms;
    using Xamarin.Forms.Platform.Android;
    
    [assembly: ExportRenderer(typeof(WebView), typeof(MyWebViewRenderer))]
    namespace Mobile.Droid.Render
    {
        public class MyWebViewRenderer : WebViewRenderer
        {
            public MyWebViewRenderer(Context context) : base(context)
            {
            }
    
            public override bool DispatchTouchEvent(MotionEvent e)
            {
                Parent.RequestDisallowInterceptTouchEvent(true);
                return base.DispatchTouchEvent(e);
            }
    
    
            protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.WebView> e)
            {
                base.OnElementChanged(e);
    
                // Setting the background as transparent
                this.Control.SetBackgroundColor(Android.Graphics.Color.Transparent);
                if (e.OldElement == null)
                {
                    Control.SetWebViewClient(new MyFormsWebViewClient(this));
                }
            }
    
            internal class MyFormsWebViewClient : FormsWebViewClient
            {
                MyWebViewRenderer _renderer;
    
                public MyFormsWebViewClient(MyWebViewRenderer renderer) : base(renderer)
                {
                    _renderer = renderer;
                }
    
                public override void OnReceivedSslError(Android.Webkit.WebView view, Android.Webkit.SslErrorHandler handler, Android.Net.Http.SslError error)
                {
                    handler.Proceed();
                }
    
                public override void OnPageFinished(Android.Webkit.WebView view, string url)
                {
                    base.OnPageFinished(view, url);
                }
    
                public override void OnLoadResource(Android.Webkit.WebView view, string url)
                {
                    base.OnLoadResource(view, url);
                }
            }
        }
    }
    
  • Mateus.3025Mateus.3025 USMember ✭✭

    And for iOS? I need a solution

Sign In or Register to comment.