WebView默认是不支持js的,要支持js,必须要添加如下设置:
WebSettings settings = webView.getSettings();
settings.setJavaScriptEnabled(true);
1.如何实现js页面通过WebView调用Android app写好的代码呢?
通过webView.addJavascriptInterface(Object, "name");方法可以实现,其中参数Object表示的是需要与js交互的Java代码所在的类的类名,而参数name则表示js页面用来调用Java代码时的别名.简单来说就是将Java对象和Js对象进行绑定,通过别名可以找到与之关联的Java对象.例如:
webView.addJavascriptInterface(this, "callByJs");
其中this代表当前类,那么js就可以通过callByJs这个别名来调用与之关联的这个类的某些方法了,为什么说是某些方法呢?而不是所有的方法呢?
因为安全问题,在Android4.2中(如果应用的android:targetSdkVersion数值为17+)JS只能访问带有 @JavascriptInterface注解的Java函数。
例如:
@JavascriptInterface
public void setValue(String content) {
Toast.makeText(TextCallJsActivity.this, "接收到的数据:"+content, Toast.LENGTH_SHORT).show();
}
这样,js要调用Android代码中的setValue方法的时候,就可以通过如下方式调用了.
javascript:window.callByJs.setValue("hello android!!");
通过WebView的loadUrl方法可以实现.在loadUrl方法中写入要执行的js代码.例如:
webView.loadUrl("javascript:alert('hello js')");
上面只是调用js的alert函数而已,弹出一个提示框显示hello js.当然如果调用其他函数也是可以的.
符合格式:javascript:函数名(有参数/无参数)即可.
除此之外,loadUrl传入的js函数还可以写的更加复杂一些,例如:
webView.loadUrl("javascript:window.GETHTML.getHtml(document.getElementsByTagName('html')[0].innerHTML);");
分别解释下:
1.javascript:window.GETHTML.getHtml();
这句话表示的是js页面通过GETHTML别名调用Java的getHtml()方法.
2.document.getElementsByTagName('html')[0].innerHTML
这句话表示执行js的函数,通过document对象查找html标签内的html代码.
这一点可以符合一些特殊需求,例如在通过webView显示终端页的同时,还需要获取终端页的html代码中的某些元数据;有一种做法就是通过写一个http get请求去抓取html代码的.但是这样的话就相当于请求了当前页面2次了.另一种方法就是这里所说的通过调用js函数来实现,通常做法是在webView设置WebViewClient对象后,重写其onPageFinish方法,在onPageFinish方法内通过loadUrl方法来调用js代码获取html代码;
好了,以上说了那么多,来看个具体的例子吧.
这个Demo是这样的.WebView显示js页面,通过点击js页面的某个图片,会调用Java代码的某个方法,然后在这个方法的内部再调用js函数,js函数执行,然后替换当前显示的图片.
html页面代码:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
<title>Document</title>
<script type="text/javascript">
//由java调用此方法
var count = 0;
function wave(){
if(count %2 == 0){
document.getElementById("droid").src="ic_launcher.png";
}else{
document.getElementById("droid").src="app_icon.png";
}
count ++;
}
</script>
</head>
<body>
<a οnclick="window.callByJs.clickOnAndroid()">
<img id="droid" src="app_icon.png" mce_src="app_icon.png"/></br>Click me change icon!
</a>
</body>
</html>
Android 代码:
package com.example.chenys.webviewdemo;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.webkit.JavascriptInterface;
import android.webkit.WebSettings;
import android.webkit.WebView;
/**
* Created by mChenys on 2015/11/19.
* 实现js页面调用android的方法,及android的方法里面再调用js页面的js函数,实现互调的过程.
*/
public class TextCallJsActivity2 extends Activity {
private Handler mHandler = new Handler();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_text_call_js);
final WebView webView = (WebView) findViewById(R.id.webView);
WebSettings settings = webView.getSettings();
settings.setJavaScriptEnabled(true);
webView.addJavascriptInterface(new Object() {
@JavascriptInterface
public void clickOnAndroid() {
System.out.println("clickOnAndroid被调用了....");
/**
* 注意:这里调用webview的方法必须在同一个线程中完成,否则抛出异常:
* java.lang.RuntimeException: java.lang.Throwable: A WebView method was called on thread 'JavaBridge'. All WebView methods must be called on the same thread.
* (Expected Looper Looper (main, tid 1) {1d832dfa} called on Looper (JavaBridge, tid 263) {2a93b47f}, FYI main Looper is Looper (main, tid 1) {1d832dfa})
*/
mHandler.post(new Runnable() {
@Override
public void run() {
webView.loadUrl("javascript:wave()");
}
});
}
}, "callByJs");
webView.loadUrl("file:///android_asset/index2.html");
}
}
效果图:
点击后变成: