一、js和Android调用的前提
在讲js和Android的互调之前,我们要先设置好webview的一些基本配置
WebSettings settings = mWebView.getSettings();
settings.setJavaScriptEnabled(true);
当然,我们还可以设置webview的客户端,并且重写其方法(方法有好多,以下只重写了两个,大家可根据自己的需求去重写)
//设置默认的web浏览器
mWebView.setWebViewClient(new WebViewClient(){
//页面开始加载的时候调用
@Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
//网页加载完后调用
try {
JSONObject json = new JSONObject();
json.put("name", "android");
json.put("message", "你好,我是安卓,加个好友呗!");
//调用js方法:webview.loadUrl(javascript:方法名(参数));
mWebView.loadUrl("javascript:showMsg("+ json.toString()+")");
} catch (JSONException e) {
e.printStackTrace();
}
}
//页面加载结束的时候调用
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
super.onPageStarted(view, url, favicon);
}
});
//设置chrome浏览器
mWebView.setWebChromeClient(new WebChromeClient(){
@Override
public void onProgressChanged(WebView view, int newProgress) {
super.onProgressChanged(view, newProgress);
}
@Override
public void onReceivedTitle(WebView view, String title) {
super.onReceivedTitle(view, title);
}
});
*最后,可不能忘记加载地址
mWebView.loadUrl(url);
二、下面进入正文,说说js和Android的调用的三种方法
1. Android调用js
2. js调用Android
3. js使用callback调用Android,基础第二种方式的升级
1、Android调用js
webview调用js的基本格式为:
webview.loadUrl(javascript:方法名(参数))
相信看到这段代码,大家都觉得很简单吧!对,就是那么简单!
如果是无参,就不要写参数;
如果参数是json数据,必须转换成String在传入
webview调用js中有返回值的方法
Android4.4之前,并没有提供直接调用js函数并获取值的方法,所以在此之前,常用的思路就是Androida调用js方法,js方法执行完毕,再次调用Android代码将值返回
1.1. java调用js(和上面上一样的)
webview.loadUrl(javascript:方法名(参数))
2.1. js函数处理,并将结果通过java方法返回
function sumToJava(num1,num2) {
window.control.onSumResult(num1+num2)
}
3. java在回调方法中获取js函数的返回值
@JavascriptInterface
public void onSumResult(int result) {
//逻辑处理
}
4.4之后,使用evaluateJavaScript就可以调用并获取到js方法中的返回值
1.1. js中的函数
function getMsg() {
return 5;
}
2.1. java代码,用evaluatejavascript方法
//第一个参数为js中的方法名
mWebView.evaluateJavascript("getMsg()", new ValueCallback() {
@Override
public void onReceiveValue(String value) {
Toast.makeText(CallJsActivity.this,value,Toast.LENGTH_SHORT).show();
}
});
注意:第二种方法返回结果限定了为String,如果是简单类型的数据可以转换成String在返回,如果是复杂的数据类型,建议以字符串形式的json返回;evaluateJavascript方法必须在ui线程调用,因此onReceiveValue也执行在主线程中
二、js调Android
js调用Android方法之前,我们需要设置一个js和Android之间的桥梁
JavaScriptMethod js = new JavaScriptMethod(this);
//设置js和Android之间的通信桥梁
//第一个参数是对象,第二个参数是第一个参数的别名(对象的映射字符串)
mWebView.addJavascriptInterface(js,"jsInterface");
创建一个JavaScriptMethod类,类中创建一个js需要调用的方法,方法上必须添加注解(4.2开始强制要求的,为了安全性考虑)
public class JavaScriptMethod {
private Context mContext;
public JavaScriptMethod(Context context) {
mContext = context;
}
@JavascriptInterface
public void showToast() {
Toast.makeText(mContext,"js调用Android中的方法",Toast.LENGTH_SHORT).show();
}
}
在js中调用showToast()方法,window.别名(Android中对象的映射字符串).方法名 ——jAndroid中必须添加这句代码:mWebView.addJavascriptInterface(js,"jsInterface");
$("#btn1").click(function() {
window.jsInterface.showToast();
})
三、js调用Android callback
先举个例子,假设页面是用html5实现,页面上要使用一笔数据,需要通过Android连网获取后返回过来,请用代码实现这个需求?(假设,设置好了webview的配置)
首先,Android中代码如下
//获取酒店详情页数据
@JavascriptInterface
public void getHotelData(){
Toast.makeText(mContext, "android接受到js:"+json, Toast.LENGTH_SHORT).show();
try {
JSONObject backJson = new JSONObject();
backJson.put("hotel_name", "8天连锁酒店");
backJson.put("hotel_price", "88");
backJson.put("hotel_phone", "0755-888888888");
invokeJsMethod("hao", backJson.toString());
} catch (JSONException e) {
e.printStackTrace();
}
}
/**
* 统一管理android调用js:android调用js必须在主线程
* @param json
*/
private void invokeJsMethod(final String callback, final String json) {
mHandler.post(new Runnable() {
@Override
public void run() {
//数据返回给js,调用js方法
mWebView.loadUrl("javascript:"+callback+"("+json+")");
}
});
}
private Handler mHandler = new Handler();
HTML5中,代码如下
$("#btn2").on("click", function(){
//1.js先调用android
window.jsInterface.getHotelData();
});
function hao(json){
alert("js接受到酒店数据:" + JSON.stringify(json));
};
上诉方法虽然能够实现需求,但是invokeJsMethod("hao", backJson.toString())调用js中的方法名是固定的,耦合性高,一旦出了问题,到底是Android端方法名写错了?还是前段的妹子报复Android端的哥们故意改了方法名?这就不知道了。所以为了解决这个问题,就有了下面要将的内容了---callback
在html5代码中,将Android需要调用js中的方法名封装成json数据传递给Android的方法
$("#btn2").on("click", function(){
var json={"callback":"hao"};
//1.js先调用android
window.jsInterface.getHotelData(JSON.stringify(json));
});
function hao(json){
alert("js接受到酒店数据:" + JSON.stringify(json));
};
在Android的getHotelData方法中,只需要将json数据中的方法名解析出来,传递给接下来要调用js的代码中
//获取酒店详情页数据
@JavascriptInterface
public void getHotelData(String json){
try {
//通过传过来的json数据解析获取方法名
JSONObject jsonObject = new JSONObject(json);
String callback = jsonObject.optString("callback");
JSONObject backJson = new JSONObject();
backJson.put("hotel_name", "8天连锁酒店");
backJson.put("hotel_price", "88");
backJson.put("hotel_phone", "0755-888888888");
invokeJsMethod(callback, backJson.toString());
} catch (JSONException e) {
e.printStackTrace();
}
....(其他与上面代码一样)