Android和js的混合開發

weixin_33797791發表於2017-03-15

一、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();

}

....(其他與上面程式碼一樣)

上訴第三種方式是比較重要的方式,大家需要記住;另外,第三步的程式碼只是大致的程式碼,還有一些基礎的配置在前面兩步已經講過,這裡就不再累贅了!

相關文章