当前的Android开发中,会使用大量的h5(html5+css3+js)
,甚至出现了混合开发模式(Hybrid),使用Hybrid开发,h5页面开发效率高和移植便利性为主。
但在一些地方使用h5开发的确会不太容易实现,这个时候就须要调用Java原生方法来完成,就会遇到JavasSript和Java相互调用,用Java原生方法实现那些Javascript代码不容易实现的功能,好比,异步线程,调用数据库等..... 而后再暴露给JavaScript调用。javascript
在Android 4.2
以前使用addjavascriptinterface
能够把原生的Java方法,给JavaScript调用,可是这种方案却存在安全风险,在页面中执行一些不可信的Javascript代码即有可能控制用户的手机,详情见:WebView中接口隐患与手机挂马利用Android 4.2
以后提供了@JavascriptInterface
对象注解的方式创建Javascript对象和android原生对象的绑定,提供给JavaScript调用的方法必须带有@JavascriptInterface
。
当前4.0及4.0以前的系统市场占有量已经很低了,所以能够考虑使用minSdkVersion
为17,只支持4.2版本以上的手机,低版本的系统再也不支持了。
下面就看下Java和Javascript是如何通讯的。css
为了方便使用,下面使用的示例,不会使用server,因此就须要在webview
中使用本地的html文件,为了方便把html文件都放在assets
文件夹中,使用本地加载的方式,这样就不须要服务器的支持了。
先定义一个html
文件:html
<!DOCTYPE html> <html> <body> <h1>this is html</h1> </body> </html>
使用file:///android_asset/index.html
加载到webview中:html5
private void initView() { webView = (WebView) findViewById(R.id.webView); webView.loadUrl("file:///android_asset/index.html"); }
下面就能够在index.html
中试用Java和JavaScript的调用了。java
以Android的Toast
的为例,下面看下如何从Javascript代码中调用系统的Toast
。
先定义一个AndroidToast
的Java类,它有一个show的方法用来显示Toast:android
public class AndroidToast { @JavascriptInterface public void show(String str) { Toast.makeText(MainActivity.this, str, Toast.LENGTH_SHORT).show(); } }
再对WebView进行设置,开启JavaScipt
,注册JavascriptInterface
的方法:css3
private void initView() { webView = (WebView) findViewById(R.id.webView); WebSettings webSettings = webView.getSettings(); webSettings.setJavaScriptEnabled(true); webSettings.setDefaultTextEncodingName("UTF-8"); webView.addJavascriptInterface(new AndroidToast(), "AndroidToast"); webView.loadUrl("file:///android_asset/index.html"); }
addJavascriptInterface
的做用是把AndroidToast
类映射为Javascript中的AndroidToast
。这样就能够在JavaScript中调用Java中的方法了。
在Javascript中调用Java代码:git
function toastClick(){ window.AndroidToast.show('from js'); }
经过window属性
能够找到映射的对象AndroidToast
,直接调用它的show方法便可。
注意这里传输的数据只能是基本数据类型和string
,能够传输string就意味着可使用json
传输结构化数据。
这里调用的方法并无返回值,若是须要在JavaScript中须要获得返回值怎么办呢?github
若是想从Javascript调的方法里面获取到返回值,只须要定义一个带返回值的@JavascriptInterface
方法便可:web
public class AndroidMessage { @JavascriptInterface public String getMsg() { return "form java"; } }
添加Javascript的映射:
webView.addJavascriptInterface(new AndroidMessage(), "AndroidMessage");
在JavaScript直接调用:
function showAlert(){ var str=window.AndroidMessage.getMsg(); console.log(str); }
这样就完成了有返回值的方法调用。还有一种场景是,在Java中主动触发JavaScript方法,就须要在Java中调用JavaScript方法了。
Java在调用JavaScript方法的时候,须要使用WebView.loadUrl()
方法,它能够直接在页面里执行JavaScript方法。
首先定义一个JavaScript方法给Java调用:
function callFromJava(str){ console.log(str); }
在Java中直接调用该方法:
public void javaCallJS(){ webView.loadUrl("javascript:callFromJava('call from java')"); }
能够在loadUrl
中给Javascript方法直接传参,若是JavaScript方法有返回值,使用WebView.loadUrl()
是没法获取到返回值的,须要JavaScript返回值给Java的话,能够定义一个Java方法提供给JavaScript调用,而后Java调用JavaScript以后,JavaScript触发该方法把返回值再传递给Java。
注意WebView.loadUrl()
必须在Ui线程
中运行,否则会会报错。