Xamarin.Forms HybridWebview callback function after redirect

CapzyelCapzyel TRMember

I have a hybridwebview with:

webview.RegisterAction(data => Executefrombrowser(data));

      public void Executefrombrowser(string data) {
            if (data == "loaded") {
                Task.Run(() =>
                  StopLoading()
                     );
            }
            if (data == "success") {
                Task.Run(async () =>
                {              
                    Device.BeginInvokeOnMainThread(() =>
                    {
                        Application.Current.MainPage = new SocialTab();
                    });
                });
            }
        }

It is working for first loaded url but doesn't work after redirect.

I have a button on the first loaded page that redirects the page,

and i have the same javascript functions for calling C# on the second page but it is not working.

My hybridwebview structure: OHWebChromeClient.cs (in .Android)

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;

    using Android.App;
    using Android.Content;
    using Android.OS;
    using Android.Runtime;
    using Android.Views;
    using Android.Widget;
    using Android.Webkit;
    using Mono;
    namespace App101.Droid
    {
        public class OHWebChromeClient : WebChromeClient
        {

            private IValueCallback mUploadMessage;
            private static int FILECHOOSER_RESULTCODE = 1;

            public override bool OnJsAlert(Android.Webkit.WebView view, string url, string message, JsResult result)
            {
                return base.OnJsAlert(view, url, message, result);
            }

            public override void OnReceivedTitle(Android.Webkit.WebView view, string title)
            {
                base.OnReceivedTitle(view, title);
            }
            public override bool OnCreateWindow(Android.Webkit.WebView view, bool isDialog, bool isUserGesture, Message resultMsg)
            {
                return true;
            }

            private void OnActivityResult(int requestCode, Result resultCode, Intent data)
            {
                if (requestCode == FILECHOOSER_RESULTCODE)
                {
                    if (null == mUploadMessage)
                        return;
                    mUploadMessage.OnReceiveValue(WebChromeClient.FileChooserParams.ParseResult((int)resultCode, data));
                    mUploadMessage = null;


                }
            }

            [Android.Runtime.Register("onShowFileChooser", "(Landroid/webkit/WebView;Landroid/webkit/ValueCallback;Landroid/webkit/WebChromeClient$FileChooserParams;)Z", "GetOnShowFileChooser_Landroid_webkit_WebView_Landroid_webkit_ValueCallback_Landroid_webkit_WebChromeClient_FileChooserParams_Handler")]
            public override bool OnShowFileChooser(Android.Webkit.WebView webView, IValueCallback filePathCallback, FileChooserParams fileChooserParams)
            {
                var appActivity = Xamarin.Forms.Forms.Context as MainActivity;
                mUploadMessage = filePathCallback;
                Intent chooserIntent = fileChooserParams.CreateIntent();
                appActivity.StartActivity(chooserIntent, FILECHOOSER_RESULTCODE, OnActivityResult);
                //return base.OnShowFileChooser (webView, filePathCallback, fileChooserParams);
                return true;
            }

            protected void openFileChooser(IValueCallback uploadMsg, String acceptType)
            {
                mUploadMessage = uploadMsg;
                Intent i = new Intent(Intent.ActionGetContent);
                i.AddCategory(Intent.CategoryOpenable);
                i.SetType("image/*");
                startActivityForResult(Intent.CreateChooser(i, "File Browser"), FILECHOOSER_RESULTCODE);
            }

            private void startActivityForResult(object p, int fILECHOOSER_RESULTCODE)
            {
                throw new NotImplementedException();
            }





        }
    }

HybridWebViewRenderer.cs (in .Android)

    using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Xamarin.Forms;
using App101;
using App101.Droid;
using Xamarin.Forms.Platform.Android;
using Android.Webkit;
using Java.Interop;

[assembly: ExportRenderer(typeof(HybridWebView), typeof(HybridWebViewRenderer))]
namespace App101.Droid
{
    public class HybridWebViewRenderer : ViewRenderer<HybridWebView, Android.Webkit.WebView>
    {
        const string JavaScriptFunction = "function invokeCSharpAction(data){jsBridge.invokeAction(data);}";

        protected override void OnElementChanged(ElementChangedEventArgs<HybridWebView> e)
        {
            base.OnElementChanged(e);

            if (Control == null)
            {
                var webView = new Android.Webkit.WebView(Forms.Context);
                webView.Settings.JavaScriptEnabled = true;
                webView.Settings.AllowFileAccess = true;
                webView.Settings.AllowContentAccess=true;
                webView.SetWebChromeClient(new OHWebChromeClient());
                SetNativeControl(webView);
            }
            if (e.OldElement != null)
            {
                Control.RemoveJavascriptInterface("jsBridge");
                var hybridWebView = e.OldElement as HybridWebView;
                hybridWebView.Cleanup();
            }
            if (e.NewElement != null)
            {
                Control.AddJavascriptInterface(new JSBridge(this), "jsBridge");
                Control.LoadUrl(string.Format(e.NewElement.Uri, Element.Uri));
                InjectJS(JavaScriptFunction);
            }


        }


        void InjectJS(string script)
        {
            if (Control != null)
            {
                Control.LoadUrl(string.Format("javascript: {0}", script));
            }
        }
    }

    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))
            {
                hybridRenderer.Element.InvokeAction(data);
            }
        }
    }
}

HybridWebViewRenderer.cs (in .İOS):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Foundation;
using UIKit;
using System.IO;
using Xamarin.Forms;
using App101;
using App101.iOS;
using Xamarin.Forms.Platform.iOS;
using WebKit;

[assembly: ExportRenderer(typeof(HybridWebView), typeof(HybridWebViewRenderer))]
namespace App101.iOS
{
    public class HybridWebViewRenderer : ViewRenderer<HybridWebView, WKWebView>, IWKScriptMessageHandler
    {
        const string JavaScriptFunction = "function invokeCSharpAction(data){window.webkit.messageHandlers.invokeAction.postMessage(data);}";
        WKUserContentController userController;

        protected override void OnElementChanged(ElementChangedEventArgs<HybridWebView> e)
        {
            base.OnElementChanged(e);

            if (Control == null)
            {
                userController = new WKUserContentController();
                var script = new WKUserScript(new NSString(JavaScriptFunction), WKUserScriptInjectionTime.AtDocumentEnd, false);
                userController.AddUserScript(script);
                userController.AddScriptMessageHandler(this, "invokeAction");

                var config = new WKWebViewConfiguration { UserContentController = userController };
                var webView = new WKWebView(Frame, config);
                SetNativeControl(webView);
            }
            if (e.OldElement != null)
            {
                userController.RemoveAllUserScripts();
                userController.RemoveScriptMessageHandler("invokeAction");
                var hybridWebView = e.OldElement as HybridWebView;
                hybridWebView.Cleanup();
            }
            if (e.NewElement != null)
            {
                string fileName = Path.Combine(NSBundle.MainBundle.BundlePath, string.Format("Content/{0}", Element.Uri));
                Control.LoadRequest(new NSUrlRequest(new NSUrl(fileName, false)));
            }
        }

        public void DidReceiveScriptMessage(WKUserContentController userContentController, WKScriptMessage message)
        {
            Element.InvokeAction(message.Body.ToString());
        }
    }
}

HybridWebView.cs (in PCL):

using System;
using System.Collections.Generic;
using System.Text;
using Xamarin.Forms;

namespace App101
{
    public class HybridWebView : View
    {
        Action<string> action;
        public static readonly BindableProperty UriProperty = BindableProperty.Create(
          propertyName: "Uri",
          returnType: typeof(string),
          declaringType: typeof(HybridWebView),
          defaultValue: default(string));

        public string Uri
        {
            get { return (string)GetValue(UriProperty); }
            set { SetValue(UriProperty, value); }
        }

        public void RegisterAction(Action<string> callback)
        {
            action = callback;
        }

        public void Cleanup()
        {
            action = null;
        }

        public void InvokeAction(string data)
        {
            if (action == null || data == null)
            {
                return;
            }
            action.Invoke(data);
        }
    }
}

What to do for working HybridWebView callback function after redirect?

Sign In or Register to comment.