當前的Android開發(fā)中,會使用大量的h5(html5+css3+js)
,甚至出現(xiàn)了混合開發(fā)模式(Hybrid)否淤,使用Hybrid開發(fā),h5頁面開發(fā)效率高和移植便利性為主。
但在一些地方使用h5開發(fā)的確會不太容易實現(xiàn)先紫,這個時候就需要調(diào)用Java原生方法來完成,就會遇到JavasSript和Java相互調(diào)用筹煮,用Java原生方法實現(xiàn)那些Javascript代碼不容易實現(xiàn)的功能遮精,比如,異步線程败潦,調(diào)用數(shù)據(jù)庫等..... 然后再暴露給JavaScript調(diào)用本冲。
JavascriptInterface
在Android 4.2
之前使用addjavascriptinterface
可以把原生的Java方法,給JavaScript調(diào)用,但是這種方案卻存在安全風險,在頁面中執(zhí)行一些不可信的Javascript代碼即有可能控制用戶的手機,詳情見:WebView中接口隱患與手機掛馬利用
Android 4.2
之后提供了@JavascriptInterface
對象注解的方式建立Javascript對象和android原生對象的綁定,提供給JavaScript調(diào)用的方法必須帶有@JavascriptInterface
劫扒。
當前4.0及4.0之前的系統(tǒng)市場占有量已經(jīng)很低了檬洞,因此可以考慮使用minSdkVersion
為17,只支持4.2版本以上的手機沟饥,低版本的系統(tǒng)不再支持了添怔。
下面就看下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的調(diào)用了县遣。
Javascript調(diào)用Java方法
以Android的Toast
的為例糜颠,下面看下如何從Javascript代碼中調(diào)用系統(tǒng)的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中調(diào)用Java中的方法了夸政。
在Javascript中調(diào)用Java代碼:
function toastClick(){
window.AndroidToast.show('from js');
}
通過window屬性
可以找到映射的對象AndroidToast
,直接調(diào)用它的show方法即可元旬。
注意這里傳輸?shù)臄?shù)據(jù)只能是基本數(shù)據(jù)類型和string
,可以傳輸string就意味著可以使用json
傳輸結構化數(shù)據(jù)。
這里調(diào)用的方法并沒有返回值,如果需要在JavaScript中需要得到返回值怎么辦呢匀归?
JavaScript調(diào)用Java有返回值
如果想從Javascript調(diào)的方法里面獲取到返回值坑资,只需要定義一個帶返回值的@JavascriptInterface
方法即可:
public class AndroidMessage {
@JavascriptInterface
public String getMsg() {
return "form java";
}
}
添加Javascript的映射:
webView.addJavascriptInterface(new AndroidMessage(), "AndroidMessage");
在JavaScript直接調(diào)用:
function showAlert(){
var str=window.AndroidMessage.getMsg();
console.log(str);
}
這樣就完成了有返回值的方法調(diào)用。還有一種場景是穆端,在Java中主動觸發(fā)JavaScript方法袱贮,就需要在Java中調(diào)用JavaScript方法了。
Java調(diào)用JavaScript方法
Java在調(diào)用JavaScript方法的時候体啰,需要使用WebView.loadUrl()
方法攒巍,它可以直接在頁面里執(zhí)行JavaScript方法。
首先定義一個JavaScript方法給Java調(diào)用:
function callFromJava(str){
console.log(str);
}
在Java中直接調(diào)用該方法:
public void javaCallJS(){
webView.loadUrl("javascript:callFromJava('call from java')");
}
可以在loadUrl
中給Javascript方法直接傳參荒勇,如果JavaScript方法有返回值柒莉,使用WebView.loadUrl()
是無法獲取到返回值的,需要JavaScript返回值給Java的話沽翔,可以定義一個Java方法提供給JavaScript調(diào)用兢孝,然后Java調(diào)用JavaScript之后,JavaScript觸發(fā)該方法把返回值再傳遞給Java仅偎。
注意WebView.loadUrl()
必須在Ui線程
中運行跨蟹,不然會會報錯。