一、js和Android調(diào)用的前提
在講js和Android的互調(diào)之前,我們要先設(shè)置好webview的一些基本配置
WebSettings settings = mWebView.getSettings();
settings.setJavaScriptEnabled(true);
當(dāng)然,我們還可以設(shè)置webview的客戶端,并且重寫其方法(方法有好多,以下只重寫了兩個,大家可根據(jù)自己的需求去重寫)
//設(shè)置默認的web瀏覽器
mWebView.setWebViewClient(new WebViewClient(){
//頁面開始加載的時候調(diào)用
@Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
//網(wǎng)頁加載完后調(diào)用
try {
JSONObject json = new JSONObject();
json.put("name", "android");
json.put("message", "你好,我是安卓,加個好友唄!");
//調(diào)用js方法:webview.loadUrl(javascript:方法名(參數(shù)));
mWebView.loadUrl("javascript:showMsg("+ json.toString()+")");
} catch (JSONException e) {
e.printStackTrace();
}
}
//頁面加載結(jié)束的時候調(diào)用
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
super.onPageStarted(view, url, favicon);
}
});
//設(shè)置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的調(diào)用的三種方法
1. Android調(diào)用js
2. js調(diào)用Android
3. js使用callback調(diào)用Android,基礎(chǔ)第二種方式的升級
1、Android調(diào)用js
webview調(diào)用js的基本格式為:
webview.loadUrl(javascript:方法名(參數(shù)))
相信看到這段代碼,大家都覺得很簡單吧!對,就是那么簡單!
如果是無參,就不要寫參數(shù);
如果參數(shù)是json數(shù)據(jù),必須轉(zhuǎn)換成String在傳入
webview調(diào)用js中有返回值的方法
Android4.4之前,并沒有提供直接調(diào)用js函數(shù)并獲取值的方法,所以在此之前,常用的思路就是Androida調(diào)用js方法,js方法執(zhí)行完畢,再次調(diào)用Android代碼將值返回
1.1. java調(diào)用js(和上面上一樣的)
webview.loadUrl(javascript:方法名(參數(shù)))
2.1. js函數(shù)處理,并將結(jié)果通過java方法返回
function sumToJava(num1,num2) {
window.control.onSumResult(num1+num2)
}
3. java在回調(diào)方法中獲取js函數(shù)的返回值
@JavascriptInterface
public void onSumResult(int result) {
//邏輯處理
}
4.4之后,使用evaluateJavaScript就可以調(diào)用并獲取到j(luò)s方法中的返回值
1.1. js中的函數(shù)
function getMsg() {
return 5;
}
2.1. java代碼,用evaluatejavascript方法
//第一個參數(shù)為js中的方法名
mWebView.evaluateJavascript("getMsg()", new ValueCallback() {
@Override
public void onReceiveValue(String value) {
Toast.makeText(CallJsActivity.this,value,Toast.LENGTH_SHORT).show();
}
});
注意:第二種方法返回結(jié)果限定了為String,如果是簡單類型的數(shù)據(jù)可以轉(zhuǎn)換成String在返回,如果是復(fù)雜的數(shù)據(jù)類型,建議以字符串形式的json返回;evaluateJavascript方法必須在ui線程調(diào)用,因此onReceiveValue也執(zhí)行在主線程中
二、js調(diào)Android
js調(diào)用Android方法之前,我們需要設(shè)置一個js和Android之間的橋梁
JavaScriptMethod js = new JavaScriptMethod(this);
//設(shè)置js和Android之間的通信橋梁
//第一個參數(shù)是對象,第二個參數(shù)是第一個參數(shù)的別名(對象的映射字符串)
mWebView.addJavascriptInterface(js,"jsInterface");
創(chuàng)建一個JavaScriptMethod類,類中創(chuàng)建一個js需要調(diào)用的方法,方法上必須添加注解(4.2開始強制要求的,為了安全性考慮)
public class JavaScriptMethod {
private Context mContext;
public JavaScriptMethod(Context context) {
mContext = context;
}
@JavascriptInterface
public void showToast() {
Toast.makeText(mContext,"js調(diào)用Android中的方法",Toast.LENGTH_SHORT).show();
}
}
在js中調(diào)用showToast()方法,window.別名(Android中對象的映射字符串).方法名 ——jAndroid中必須添加這句代碼:mWebView.addJavascriptInterface(js,"jsInterface");
$("#btn1").click(function() {
window.jsInterface.showToast();
})
三、js調(diào)用Android callback
先舉個例子,假設(shè)頁面是用html5實現(xiàn),頁面上要使用一筆數(shù)據(jù),需要通過Android連網(wǎng)獲取后返回過來,請用代碼實現(xiàn)這個需求?(假設(shè),設(shè)置好了webview的配置)
首先,Android中代碼如下
//獲取酒店詳情頁數(shù)據(jù)
@JavascriptInterface
public void getHotelData(){
Toast.makeText(mContext, "android接受到j(luò)s:"+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();
}
}
/**
* 統(tǒng)一管理android調(diào)用js:android調(diào)用js必須在主線程
* @param json
*/
private void invokeJsMethod(final String callback, final String json) {
mHandler.post(new Runnable() {
@Override
public void run() {
//數(shù)據(jù)返回給js,調(diào)用js方法
mWebView.loadUrl("javascript:"+callback+"("+json+")");
}
});
}
private Handler mHandler = new Handler();
HTML5中,代碼如下
$("#btn2").on("click", function(){
//1.js先調(diào)用android
window.jsInterface.getHotelData();
});
function hao(json){
alert("js接受到酒店數(shù)據(jù):" + JSON.stringify(json));
};
上訴方法雖然能夠?qū)崿F(xiàn)需求,但是invokeJsMethod("hao", backJson.toString())調(diào)用js中的方法名是固定的,耦合性高,一旦出了問題,到底是Android端方法名寫錯了?還是前段的妹子報復(fù)Android端的哥們故意改了方法名?這就不知道了。所以為了解決這個問題,就有了下面要將的內(nèi)容了---callback
在html5代碼中,將Android需要調(diào)用js中的方法名封裝成json數(shù)據(jù)傳遞給Android的方法
$("#btn2").on("click", function(){
var json={"callback":"hao"};
//1.js先調(diào)用android
window.jsInterface.getHotelData(JSON.stringify(json));
});
function hao(json){
alert("js接受到酒店數(shù)據(jù):" + JSON.stringify(json));
};
在Android的getHotelData方法中,只需要將json數(shù)據(jù)中的方法名解析出來,傳遞給接下來要調(diào)用js的代碼中
//獲取酒店詳情頁數(shù)據(jù)
@JavascriptInterface
public void getHotelData(String json){
try {
//通過傳過來的json數(shù)據(jù)解析獲取方法名
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();
}
....(其他與上面代碼一樣)