重定向后的Xamarin.Forms HybridWebview回调函数

时间:2017-11-06 10:27:34

标签: c# redirect xamarin webview xamarin.forms

我有一个混合网络视图:

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();
                    });
                });
            }
        }

它适用于第一个加载的网址,但在重定向后无效。

我在第一个加载页面上有一个按钮,用于重定向页面,

我在第二页上调用C#具有相同的javascript函数,但它无法正常工作。

我的混合网络视图结构: OHWebChromeClient.cs(在.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(在.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(在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);
        }
    }
}

重定向后如何处理HybridWebView回调函数?

1 个答案:

答案 0 :(得分:0)

在ios上,这很有效:

    protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        base.OnElementPropertyChanged(sender, e);

        if (e.PropertyName == "Uri")
            Control.LoadRequest(new NSUrlRequest(new NSUrl(Element.Uri)));
    }

对于Android,以下作品:

protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
    base.OnElementPropertyChanged(sender, e);

    if (e.PropertyName == "Uri")
    {
        var webView = new Android.Webkit.WebView(_context);
        webView.Settings.JavaScriptEnabled = true;
        SetNativeControl(webView);

        Control.AddJavascriptInterface(new JSBridge(this), "jsBridge");
        Control.LoadUrl(Element.Uri);                
        InjectJS(JavaScriptFunction);                
    }
}