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