Android提供了一個很強(qiáng)大的WebView控件用來處理Web網(wǎng)頁,而在網(wǎng)頁中,JavaScript又是一個很舉足輕重的腳本。本文將介紹如何實(shí)現(xiàn)Java代碼和Javascript代碼的相互調(diào)用。
如何實(shí)現(xiàn)
實(shí)現(xiàn)Java和js交互十分便捷。通常只需要以下幾步。
1.WebView開啟JavaScript腳本執(zhí)行
2.WebView設(shè)置供JavaScript調(diào)用的交互接口。
3.客戶端和網(wǎng)頁端編寫調(diào)用對方的代碼。
本例代碼
為了便于講解,先貼出全部代碼
Java代碼
import android.annotation.SuppressLint;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.webkit.JavascriptInterface;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Toast;
public class MainActivity extends Activity {
private static final String LOGTAG = "MainActivity";
@SuppressLint("JavascriptInterface")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final WebView myWebView = (WebView) findViewById(R.id.myWebView);
WebSettings settings = myWebView.getSettings();
settings.setJavaScriptEnabled(true);
myWebView.addJavascriptInterface(new JsInteration(), "control");
myWebView.setWebChromeClient(new WebChromeClient() {});
myWebView.setWebViewClient(new WebViewClient() {
@Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
testMethod(myWebView);
}
});
myWebView.loadUrl("file:///android_asset/js_java_interaction.html");
}
private void testMethod(WebView webView) {
String call = "javascript:sayHello()";
call = "javascript:alertMessage(/"" + "content" + "/")";
call = "javascript:toastMessage(/"" + "content" + "/")";
call = "javascript:sumToJava(1,2)";
webView.loadUrl(call);
}
public class JsInteration {
@JavascriptInterface
public void toastMessage(String message) {
Toast.makeText(getApplicationContext(), message, Toast.LENGTH_LONG).show();
}
@JavascriptInterface
public void onSumResult(int result) {
Log.i(LOGTAG, "onSumResult result=" + result);
}
}
}
前端網(wǎng)頁代碼
function alertMessage(message) {
alert(message)
}
function toastMessage(message) {
window.control.toastMessage(message)
}
function sumToJava(number1, number2){
window.control.onSumResult(number1 + number2)
}
</script>
Java-Javascript Interaction In Android
</html>
調(diào)用示例
js調(diào)用Java
調(diào)用格式為window.jsInterfaceName.methodName(parameterValues) 此例中我們使用的是control作為注入接口名稱。
function sumToJava(number1, number2){
window.control.onSumResult(number1 + number2)
}
Java調(diào)用JS
webView調(diào)用js的基本格式為webView.loadUrl(“javascript:methodName(parameterValues)”)
調(diào)用js無參無返回值函數(shù)
調(diào)用js有參無返回值函數(shù)
注意對于字符串作為參數(shù)值需要進(jìn)行轉(zhuǎn)義雙引號。
調(diào)用js有參數(shù)有返回值的函數(shù)
Android在4.4之前并沒有提供直接調(diào)用js函數(shù)并獲取值的方法,所以在此之前,常用的思路是 java調(diào)用js方法,js方法執(zhí)行完畢,再次調(diào)用java代碼將值返回。
1.Java調(diào)用js代碼
2.js函數(shù)處理,并將結(jié)果通過調(diào)用java方法返回
3.Java在回調(diào)方法中獲取js函數(shù)返回值
4.4處理
Android 4.4之后使用evaluateJavascript即可。這里展示一個簡單的交互示例 具有返回值的js方法
java代碼時用evaluateJavascript方法調(diào)用
@Override
public void onReceiveValue(String value) {
Log.i(LOGTAG, "onReceiveValue value=" + value);
}});
}
輸出結(jié)果
注意
1.上面限定了結(jié)果返回結(jié)果為String,對于簡單的類型會嘗試轉(zhuǎn)換成字符串返回,對于復(fù)雜的數(shù)據(jù)類型,建議以字符串形式的json返回。
2.evaluateJavascript方法必須在UI線程(主線程)調(diào)用,因此onReceiveValue也執(zhí)行在主線程。
疑問解答
Alert無法彈出
你應(yīng)該是沒有設(shè)置WebChromeClient,按照以下代碼設(shè)置
問題出現(xiàn)原因,網(wǎng)頁的js代碼沒有加載完成,就調(diào)用了js方法。解決方法是在網(wǎng)頁加載完成之后調(diào)用js方法
@Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
//在這里執(zhí)行你想調(diào)用的js函數(shù)
}
});
Uncaught TypeError: Object [object Object] has no method
安全限制問題
如果只在4.2版本以上的機(jī)器出問題,那么就是系統(tǒng)處于安全限制的問題了。Android文檔這樣說的
解決方法
1.將targetSdkVersion設(shè)置成17或更高,引入@JavascriptInterface注釋
2.自己創(chuàng)建一個注釋接口名字為@JavascriptInterface,然后將其引入。注意這個接口不能混淆。這種方式不推薦,大概在4.4之后有問題。
注,創(chuàng)建@JavascriptInterface代碼
}
代碼混淆問題
如果在沒有混淆的版本運(yùn)行正常,在混淆后的版本的代碼運(yùn)行錯誤,并提示Uncaught TypeError: Object [object Object] has no method,那就是你沒有做混淆例外處理。 在混淆文件加入類似這樣的代碼
All WebView methods must be called on the same thread
過濾日志曾發(fā)現(xiàn)過這個問題。
在js調(diào)用后的Java回調(diào)線程并不是主線程。如打印日志可驗(yàn)證
解決上述的異常,將webview操作放在主線程中即可。
新聞熱點(diǎn)
疑難解答
圖片精選