Xamarin.Form中WebView调用JS代码和JS代码调用客户端程序

    由于在项目中使用了WebView容器来加载网页对某些信息进行编辑处理,中间需要用到拍照/图片库上传图片,在iOS中网页代码可以正常调用拍照功能和选择图库图片功能,但是在Android下面怎么都调不到拍照功能,百度了下在原生程序下面也是同样的调用不到,要自己去处理,有几种处理办法,我这里选择了用JS调用原生代码来实现拍照和图片选择功能。在Xamarin.Forms下面我们要自己写Renderer来实现。这里同样是参考Xamarin官网的例子来实现的,下面是个小例子来理解原生代码和JS代码之间的互相调用。

1.在Form中定义HybridWebView,继承于WebView,代码如下:

  1     public class HybridWebView:WebView
  2     {
  3         public event EventHandler<EventArgs> CallAction;
  4         public void SendClick(string data)
  5         {
  6             CallAction?.Invoke(this,new EventArgs());
  7         }
  8     }

2.在Android项目下面自定义Renderer:

  1     public class HybridWebViewRenderer:WebViewRenderer
  2     {
  3         const string JavaScriptFunction = "function invokeCSharpAction(data){jsBridge.invokeAction(data);}";
  4 
  5         public HybridWebView webView;
  6 
  7         protected override void OnElementChanged(ElementChangedEventArgs<WebView> e)
  8         {
  9             base.OnElementChanged(e);
 10             if (e.OldElement != null)
 11             {
 12                 Control.RemoveJavascriptInterface("jsBridge");
 13             }
 14             if (e.NewElement != null)
 15             {
 16                 webView = e.NewElement as HybridWebView;
 17 
 18                 Control.AddJavascriptInterface(new JSBridge(this), "jsBridge");
 19                 InjectJS(JavaScriptFunction);
 20             }
 21 
 22             void InjectJS(string script)
 23             {
 24                 if (Control != null)
 25                 {
 26                     Control.LoadUrl(string.Format("javascript: {0}", script));
 27                 }
 28             }
 29         }
 30     }

3.定义jsbridge

  1     public class JSBridge : Java.Lang.Object
  2     {
  3         readonly WeakReference<HybridWebViewRenderer> hybridWebViewRenderer;
  4 
  5         public JSBridge(HybridWebViewRenderer hybridRenderer)
  6         {
  7             hybridWebViewRenderer = new WeakReference<HybridWebViewRenderer>(hybridRenderer);
  8         }
  9 
 10         [JavascriptInterface]
 11         [Export("invokeAction")]
 12         public void InvokeAction(string data)
 13         {
 14             HybridWebViewRenderer hybridRenderer;
 15 
 16             if (hybridWebViewRenderer != null && hybridWebViewRenderer.TryGetTarget(out hybridRenderer))
 17             {
 18                 hybridRenderer.webView.SendClick(data);
 19             }
 20         }
 21     }

4.要注意的是我们要在Android项目中引入程序集Mono.Android.Export,不然程序会报错。

5.定义html文件中的js代码:

  1 <html>
  2 <head />
  3 <body>
  4     <script src="http://code.jquery.com/jquery-2.1.4.min.js"></script>
  5     <h1>HybridWebView Test</h1>
  6     <br />
  7     Enter name: <input type="text" id="name">
  8     <br />
  9     <br />
 10     <button type="button" onclick="javascript:invokeCSCode($('#name').val());">Invoke C# Code</button>
 11     <br />
 12     <p id="result">Result:</p>
 13 
 14     <script type="text/javascript">
 15         //调用C#代码
 16         function invokeCSCode(data) {
 17             invokeCSharpAction(data);
 18         }
 19 
 20         //C#调用此js方法
 21         function print(url) {
 22             alert(url);
 23         }
 24     </script>
 25 </body>
 26 </html>
 27 

6.在程序中调用

  1 public MainPage()
  2 		{
  3 			InitializeComponent();
  4 		    webView.Source = string.Format("file:///android_asset/Content/{0}", "index.html");
  5             webView.CallAction += WebView_CallAction;
  6         }
  7 
  8         private void WebView_CallAction(object sender, EventArgs e)
  9         {
 10             object test = "http://www.baidu.com";
 11             webView.Eval(string.Format("print('" + test + "')"));
 12         }

 代码地址:https://github.com/zjmsky/HybridWebViewTest

posted @ 2017-07-27 22:10  古韵古风  阅读(2926)  评论(0编辑  收藏  举报