[FIXED] Unable to get the trigger button event call back from Web view for Xamarin using hybridWebView

Issue

I have my mobile application build using Xamarin forms, which consist of a webView loaded into my application. The WebView Consist of buttons and icons being loaded. I have a requirement to trigger the button event Listener , so that I can do the corresponding functionality. Can anyone help me in how to get the button events being called in Xamarin forms. I have used HybridWebView as mentioned in the documents and sample ,but nothing seems to be working for me. Below is the code I have used for the same.

code:
HybridWebViewRenderer

using System;
using Android.Content;
using TestProject.Droid;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;

[assembly: ExportRenderer(typeof(Vinspector.HybridWebView), typeof(HybridWebViewRenderer))]

namespace TestProject.Droid
{
    public class HybridWebViewRenderer : WebViewRenderer
    {
       
        const string JavascriptFunction = "function invokeCSharpAction(data){jsBridge.invokeAction(data);};";
        Context _context;

        public HybridWebViewRenderer(Context context) : base(context)
        {
            _context = context;
        }

        protected override void OnElementChanged(ElementChangedEventArgs<WebView> e)
        {
            base.OnElementChanged(e);
            if (Control == null)
            {
                Console.WriteLine("print inside  control is null!!!");
                var webView = new Android.Webkit.WebView(_context);
                webView.Settings.JavaScriptEnabled = true;
                webView.Settings.DatabaseEnabled = true;
                webView.Settings.DomStorageEnabled = true;
                SetNativeControl(webView);


            }
            if (e.OldElement != null)
            {
                Control.RemoveJavascriptInterface("jsBridge");
                var hybridWebView = e.OldElement as HybridWebView;
                hybridWebView.Cleanup();
            }
            if (e.NewElement != null)
            {
                Control.Settings.JavaScriptEnabled = true;
                Control.Settings.DatabaseEnabled = true;
                Control.Settings.DomStorageEnabled = true;
                Control.SetWebViewClient(new JavascriptWebViewClient("javascript:(function getCloseCa(){var btns = document.getElementById('dvCloseBtn');})()"));
                Control.AddJavascriptInterface(new JSBridge(this), "jsBridge");
                Control.LoadUrl(“www.google.com”);


            }
        }
   

        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                ((HybridWebView)Element).Cleanup();
            }
            base.Dispose(disposing);
        }
    }
}

Code For JavascriptWebViewClient

namespace TestProject.Droid
{
    public class JavascriptWebViewClient : WebViewClient
    {
        string _javascript;

        public JavascriptWebViewClient(string javascript)
        {
            _javascript = javascript;
        }

        public override void OnPageFinished(Android.Webkit.WebView view, string url)

        {
            base.OnPageFinished(view, url);

            if (Build.VERSION.SdkInt >= BuildVersionCodes.Kitkat)
            {


                view.EvaluateJavascript(_javascript, null);

            }
            else {

                view.LoadUrl(_javascript);

            }


        }
    }
}

Code For JsBridge

namespace TestProject.Droid
{
    public class JSBridge : Java.Lang.Object
    {
        readonly WeakReference<HybridWebViewRenderer> hybridWebViewRenderer;

        public JSBridge(HybridWebViewRenderer hybridRenderer)
        {
            hybridWebViewRenderer = new WeakReference<HybridWebViewRenderer>(hybridRenderer);
        }

        [JavascriptInterface]
        [Export("invokeAction")]
        public void InvokeAction(string data)
        {
            HybridWebViewRenderer hybridRenderer;

            if (hybridWebViewRenderer != null && hybridWebViewRenderer.TryGetTarget(out hybridRenderer))
            {
                ((HybridWebView)hybridRenderer.Element).InvokeAction(data);
            }
        }
    }
}

WebPage.xaml

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:local="clr-namespace:TestProject."
             x:Class="TestProject..WebPage">

    <StackLayout>
        <ProgressBar Progress="0.2"  
                 HorizontalOptions="FillAndExpand"  
                 x:Name="progress"
                 IsVisible="True"/>

        <local:HybridWebView
            x:Name="hybridWebView"  
             HeightRequest="1000"  
             WidthRequest="1000"
              Navigating="OnNavigating"  
             Navigated="OnNavigated"  
             VerticalOptions="FillAndExpand"
           >

        </local:HybridWebView>

    </StackLayout>

</ContentPage>

WebPage.Xaml.cs

 using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Net;
    using System.Net.Http;
    using System.Net.Http.Headers;
    using System.Text;
    using System.Threading.Tasks;
    using Vinspector.Droid;
    using Xamarin.Forms;
    using Xamarin.Forms.Xaml;
    using Newtonsoft.Json;
    using TestProject.Models;
    
    namespace TestProject
    {
        [XamlCompilation(XamlCompilationOptions.Compile)]
        public partial class WebPage : ContentPage
        {
    
            public WebPage()
            {
                InitializeComponent();
    
                hybridWebView.RegisterAction(data => Console.WriteLine("value of data is" + data));
    
    
            }
            protected async override void OnAppearing()
            {
                base.OnAppearing();
    
                await progress.ProgressTo(0.9, 900, Easing.SpringIn);
            }
    
            protected void OnNavigating(object sender, WebNavigatingEventArgs e)
            {
                progress.IsVisible = true;
                Console.WriteLine(" Result OnNavigating....");
    
            }
    
            protected void OnNavigated(object sender, WebNavigatedEventArgs e)
            {
                progress.IsVisible = false;
                Console.WriteLine(" Result OnNavigated....");
                var retorno = hybridWebView.EvaluateJavaScriptAsync("common.GetCurrentUserID();");
    
                covertAsync(retorno);
            }
    
            private async Task covertAsync(Task<string> retorno)
            {
                string userID = await retorno;
    
    
                string AccessToken = LoadApplicationProperty<string>("access_token");
                Console.WriteLine(" Result UserID...." + userID + " " + AccessToken);
    
            }
    
            private T LoadApplicationProperty<T>(string key)
            {
                return (T)Xamarin.Forms.Application.Current.Properties[key];
            }
    
    
    
    
        }
    
    }

Solution

You can use the javascript function like the below code to access the buttons and events clicked from webview:

using System;
using Android.Content;
using TestProject.Droid;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;

[assembly: ExportRenderer(typeof(Vinspector.HybridWebView), typeof(HybridWebViewRenderer))]

namespace TestProject.Droid
{
    public class HybridWebViewRenderer : WebViewRenderer
    {
       
    const string JavascriptFunction= "document.getElementById('btnId').onclick= function(data){jsBridge.submissionAction(data);}";`

        Context _context;

        public HybridWebViewRenderer(Context context) : base(context)
        {
            _context = context;
        }

        protected override void OnElementChanged(ElementChangedEventArgs<WebView> e)
        {
            base.OnElementChanged(e);
            if (Control == null)
            {
                Console.WriteLine("print inside  control is null!!!");
                var webView = new Android.Webkit.WebView(_context);
                webView.Settings.JavaScriptEnabled = true;
                webView.Settings.DatabaseEnabled = true;
                webView.Settings.DomStorageEnabled = true;
                SetNativeControl(webView);
            }
            if (e.OldElement != null)
            {
                Control.RemoveJavascriptInterface("jsBridge");
                var hybridWebView = e.OldElement as HybridWebView;
                hybridWebView.Cleanup();
            }
            if (e.NewElement != null)
            {
                Control.Settings.JavaScriptEnabled = true;
                Control.Settings.DatabaseEnabled = true;
                Control.Settings.DomStorageEnabled = true;
               webView.SetWebViewClient(new `JavascriptWebViewClient(this,string.Format("javascript: {0}", JavascriptFunction)));`
                Control.AddJavascriptInterface(new JSBridge(this), "jsBridge");
                Control.LoadUrl(“www.google.com”);
            }
        }
   
        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                ((HybridWebView)Element).Cleanup();
            }
            base.Dispose(disposing);
        }
    }
}

Answered By – I'm Coder

Answer Checked By – Pedro (Easybugfix Volunteer)

Leave a Reply

(*) Required, Your email will not be published