前言
本篇講解Java
代碼和Javascript
代碼的相互調(diào)用以及JS
代碼在Java
中是如何動(dòng)態(tài)的注入WebView
中。一些通用配置在第一部分中說明。
一缎谷、Java 調(diào)用 JS 中函數(shù)
1.添加權(quán)限(這里使用資源目錄下寫好的html文件)
<uses-permission android:name="android.permission.INTERNET"/>
2.webView配置
...
// 省略掉findView..webview
mWebView.getSettings().setJavaScriptEnabled(true);
3.利用webView
的loadUrl()
方法調(diào)用JS中函數(shù)
注意調(diào)用的函數(shù)前面添加javascript:
...
btn_invoke_js1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
// 調(diào)用JS中無參數(shù)的函數(shù)
mWebView.loadUrl("javascript:javacalljs()");
mWebView.loadUrl("javascript:javacalljswith(\"JAVA調(diào)用了JS的有參函數(shù)\")");
}
});
...
二、JS 調(diào)用 Java 中方法
1.添加js的回調(diào)接口
第一個(gè)參數(shù)是接收回調(diào)的類,這里寫成當(dāng)前的類杖小,接下來會(huì)在當(dāng)前類中添加被js
調(diào)用的方法。obj
為別名愚墓,和js
中保持一致予权。
mWebView.addJavascriptInterface(this, "obj");
2.java中添加被js調(diào)用的方法。
<font color="red">注意一定不要忘記添加@JavascriptInterface</font>這里的方法和web.html中的window.obj.localMethods('Incoming parameters')
保持一致浪册。
...
@JavascriptInterface
public void localMethods(String arg) {
Log.i(TAG, "This method is called!");
Toast.makeText(this, "This method is called!", Toast.LENGTH_SHORT).show();
}
三扫腺、(重點(diǎn))Java 中動(dòng)態(tài)注入 JS
1.注入JS方法
這里注入時(shí)機(jī)是onPageFinished()
后;注入的JS是一個(gè)alert
為例村象。
public class JsInjectionActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
...
InsideWebViewClient mInsideWebViewClient = new InsideWebViewClient();
mWebView.setWebChromeClient(new WebChromeClient());
mWebView.setWebViewClient(mInsideWebViewClient);
WebSettings webSettings = mWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
mWebView.addJavascriptInterface(JsInjectionActivity.this, "obj");
mWebView.loadUrl("file:///android_asset/web.html");
...
}
private class InsideWebViewClient extends WebViewClient {
@Override
public void onPageFinished(WebView view, String url) {
mWebView.loadUrl("javascript:" + "window.alert('Js injection success')" );
super.onPageFinished(view, url);
}
}
}
...
注意:以上注入的js
包含一個(gè)alert
笆环,寫完后可能會(huì)發(fā)現(xiàn)alert
沒有彈出來。這時(shí)要去檢查myWebView.setWebChromeClient(new WebChromeClient());
是否設(shè)置了厚者。
2.(重點(diǎn))注入的js導(dǎo)致的問題或可能出現(xiàn)的問題
- 注入
js
可能會(huì)導(dǎo)致加載的html5
頁面總是一直在加載中躁劣,加載很慢或干脆加載不出來,這個(gè)問題不是針對(duì)所有的html5
可能在某些網(wǎng)頁上會(huì)遇到這個(gè)問題库菲; - 注入JS后回調(diào)函數(shù)沒有執(zhí)行到账忘;
解決方法:
@Override
protected void onPause(){
super.onPause();
mWebView.pauseTimers();
if(isFinishing()){
mWebView.loadUrl("about:blank");
setContentView(new FrameLayout(this));
}
}
@Override
protected void onResume(){
super.onResume();
mWebView.resumeTimers();
}
調(diào)用webView.loadUrl("about:blank");
該方法使得webView只回執(zhí)一個(gè)白色背景,并且釋放之前加載頁面時(shí)使用的資源,并停止之前javascript的執(zhí)行闪萄。
pauseTimers
, onPause
停止解析,javascript
執(zhí)行等操作.區(qū)別是 onPause
只作用于調(diào)用它的WebView,而 pauseTimers 作用于當(dāng)前應(yīng)用中所有的WebView
resumeTimers
, onResume
恢復(fù)解析,javascript
執(zhí)行等操作.區(qū)別是 onResume
只作用于調(diào)用它的WebView
,而 resumeTimers
作用于當(dāng)前應(yīng)用中所有的WebView梧却。
3.當(dāng)壓縮后的JS注入到webView中時(shí),注入沒有生效
我的解決方式:
把JS
格式化后或是非壓縮狀態(tài)注入成功败去,不知道別人有沒有遇到過類似問題放航,或者是其它原因,這里有疑問圆裕,如果有遇到相同問題的广鳍,歡迎一起交流。
在線js格式化吓妆,縮進(jìn)方式選擇:4個(gè)空格縮進(jìn)
http://tool.oschina.net/codeformat/js
四赊时、完整代碼
完整代碼,不包含js注入遇到的問題部分行拢,自行加入祖秒。
1. web.html
文件
文件路徑:..src/main/assets/web.html
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=gb2312">
<script type="text/javascript">
function javacalljs(){
document.getElementById("content").innerHTML = "<br>JAVA調(diào)用了JS的無參函數(shù)";
}
function javacalljswith(arg){
document.getElementById("content").innerHTML = ("<br>"+arg);
}
</script>
</head>
<body>
HTML 內(nèi)容顯示 <br/>
<h1>
<div id="content">內(nèi)容顯示</div>
</h1>
<br/>
<input type="button" value="點(diǎn)擊調(diào)用java代碼" onclick="window.obj.localMethods('Incoming parameters')"/><br/>
</body>
</html>
2. JsInjectionActivity.java
文件
public class JsInjectionActivity extends Activity {
private static final String TAG = JsInjectionActivity.class.getSimpleName();
private WebView mWebView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button btn_invoke_js1 = (Button) findViewById(R.id.btn_invoke_js1);
Button btn_invoke_js2 = (Button) findViewById(R.id.btn_invoke_js2);
mWebView = (WebView) findViewById(R.id.webview);
InsideWebViewClient mInsideWebViewClient = new InsideWebViewClient();
mWebView.setWebChromeClient(new WebChromeClient());
mWebView.setWebViewClient(mInsideWebViewClient);
WebSettings webSettings = mWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
mWebView.addJavascriptInterface(JsInjectionActivity.this, "obj");
mWebView.loadUrl("file:///android_asset/web.html");
btn_invoke_js1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
mWebView.loadUrl("javascript:javacalljs()");
}
});
btn_invoke_js2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
mWebView.loadUrl("javascript:javacalljswith(\"JAVA調(diào)用了JS的有參函數(shù)\")");
}
});
}
@JavascriptInterface
public void localMethods(String arg) {
Log.i(TAG, "This method is called!");
Toast.makeText(this, "This method is called!", Toast.LENGTH_SHORT).show();
}
private class InsideWebViewClient extends WebViewClient {
@Override
public void onPageFinished(WebView view, String url) {
mWebView.loadUrl("javascript:" + "window.alert('Js injection success')" );
super.onPageFinished(view, url);
}
}
}
最后
不懂得地方歡迎私信我,我會(huì)在第一時(shí)間給予回復(fù)舟奠,如閱讀中發(fā)現(xiàn)寫錯(cuò)的地方竭缝,歡迎糾正。