當前的Android開發中,會使用大量的h5(html5+css+js)
,甚至出現了混合開發模式(Hybrid),使用Hybrid開發,h5頁面開發效率高和移植便利性為主。
但在一些地方使用h5開發的確會不太容易實現,這個時候就需要呼叫Java原生方法來完成,就會遇到JavasSript和Java相互呼叫,用Java原生方法實現那些Javascript程式碼不容易實現的功能,比如,非同步執行緒,呼叫資料庫等..... 然後再暴露給JavaScript呼叫。
JavascriptInterface
在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是如何通訊的。
載入本地html
為了方便使用,下面使用的示例,不會使用server,所以就需要在webview
中使用本地的html檔案,為了方便把html檔案都放在assets
資料夾中,使用本地載入的方式,這樣就不需要伺服器的支援了。
先定義一個html
檔案:
<!DOCTYPE html>
<html>
<body>
<h1>this is html</h1>
</body>
</html>複製程式碼
使用file:///android_asset/index.html
載入到webview中:
private void initView() {
webView = (WebView) findViewById(R.id.webView);
webView.loadUrl("file:///android_asset/index.html");
}複製程式碼
下面就可以在index.html
中試用Java和JavaScript的呼叫了。
Javascript呼叫Java方法
以Android的Toast
的為例,下面看下如何從Javascript程式碼中呼叫系統的Toast
。
先定義一個AndroidToast
的Java類,它有一個show的方法用來顯示Toast:
public class AndroidToast {
@JavascriptInterface
public void show(String str) {
Toast.makeText(MainActivity.this, str, Toast.LENGTH_SHORT).show();
}
}複製程式碼
再對WebView進行設定,開啟JavaScipt
,註冊JavascriptInterface
的方法:
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程式碼:
function toastClick(){
window.AndroidToast.show('from js');
}複製程式碼
通過window屬性
可以找到對映的物件AndroidToast
,直接呼叫它的show方法即可。
注意這裡傳輸的資料只能是基本資料型別和string
,可以傳輸string就意味著可以使用json
傳輸結構化資料。
這裡呼叫的方法並沒有返回值,如果需要在JavaScript中需要得到返回值怎麼辦呢?
JavaScript呼叫Java有返回值
如果想從Javascript調的方法裡面獲取到返回值,只需要定義一個帶返回值的@JavascriptInterface
方法即可:
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方法
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執行緒
中執行,不然會會報錯。