Android 的webview加载HTML页面时与JS的交互一直不大熟悉,此处仅针对页面的点击事件。
Android的webview加载的页面,在查看页面之后发现需要获取点击的元素中的图片信息,包括 img 的 src 或者 div 的backgroundImage等,当然也可以获取元素的其他的属性数据。
Android的 js 注入有两种方式
webView.evaluateJavascript(str, ValueCallback())
以及
webView.addJavascriptInterface(new MJavascriptInterface(), "imagelistener");
我会对这两种方式做出说明
对于 evaluateJavascript 这个方法不做过多的解释,需要了解的小伙伴可以去 百度搜索了解一下。
首先根据我们的需要编写JS代码,然后用 WebStorm 随便写一个网页测试所编写的JS代码,以验证JS代码的准确性。
先上此次需要对 页面的点击事件的监听,执行的JS 代码
window.onclick=function (event) {
console.log(event)
};
打印 event 根据event的数据详情筛选我们需要的数据
点开数据详情,寻找需要获取的元素,发现 path属性下面保存的是对应 的点击位置的所有的元素
元素的排序顺序为 从内到外 即 0 为最里面的一层,参考下图
点击打开对应的元素信息查看属性值,找到我们关心的值
确定值得获取当时 为 event.path[0].src 以及 event.path[0].style.backgroundImage;如果需要获取其他的值请参考元素的打印的属性数据详情
修改JS代码
window.onclick=function (event) {
var src=event.path[0].src;
if(src!=null){
console.log(src)
}else {
var back=event.path[0].style.backgroundImage;
if(back!=null){
console.log(back)
}
}
};
测试
打印的两行数据别属于 img 的 src 以及div 的 backgroundImage,确认js代码没有问题,下面开始两种方式的注入取值
注意:str对应的为一个JS的执行语句,如果是获取某个值的js代码那么在后面的 ValueCallback
例如:str=document.getElementById("test").className 那么在 ValueCallback
String str="document.getElementById(\"test\").className";
webView.evaluateJavascript(str, new ValueCallback() {
@Override
public void onReceiveValue(String s) {
//s 为对应语句 str获取到的结果
}
});
但是我们此时需要执行的JS语句为 window.οnclick=function (event) { ...... }; 是一个方法,不是直接的获取数值的JS语句,所以此处我们不需要传递 ValueCallback
看代码
String str=" window.onclick=function (event) {\n" +
" var src=event.path[0].src;\n" +
" if(src!=null){\n" +
" console.log(src)\n" +
" }else {\n" +
" var back=event.path[0].style.backgroundImage;\n" +
" if(back!=null){\n" +
" console.log(back)\n" +
" }\n" +
" }\n" +
" };";
webView.evaluateJavascript(str, null);
此处我们 使用 console.log(s) 打印数据并重写 WebChromeClient() 的 onConsoleMessage 方法进行拦截,代码如下
webView.setWebChromeClient(new WebChromeClient(){
@Override
public boolean onConsoleMessage(ConsoleMessage consoleMessage) {
String message=consoleMessage.message();
if(message!=null&&!message.equals("")&&!message.equals("null"))
Log.d(TAG, "onConsoleMessage: "+message);
return super.onConsoleMessage(consoleMessage);
}
});
然后我们就可以获取到所要的数据了,可以在次 做 下一步的逻辑操作。
首先在webview初始化的时候 设置代码
webView.addJavascriptInterface(new MJavascriptInterface(), "imagelistener");
MJavascriptInterface() 的代码
public class MJavascriptInterface {
@android.webkit.JavascriptInterface
public void getImagePath(String img) {
Log.d("MainActivity","backgroundImage:"+img);
}
@android.webkit.JavascriptInterface
public void getImageSrc(String src) {
Log.d("MainActivity","src:"+src);
}
}
新建一个类 SWebViewClient 继承自 WebViewClient,重写onPageFinished 以及 onPageStarted 方法:
public class SWebViewClient extends WebViewClient {
@Override
public void onPageFinished(WebView view, String url) {
view.getSettings().setJavaScriptEnabled(true);
super.onPageFinished(view, url);
getYSimage(view);
}
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
view.getSettings().setJavaScriptEnabled(true);
super.onPageStarted(view, url, favicon);
}
private void getYSimage(WebView webView) {
webView.loadUrl("javascript:window.onclick=function (event) {" +
" var src=event.path[0].src;" +
" if(src!=null){" +
" window.imagelistener.getImageSrc(src)" +
" }else {" +
" var back=event.path[0].style.backgroundImage;" +
" if(back!=null){" +
" window.imagelistener.getImagePath(back)" +
" }" +
" }" +
"" +
" };");
}
}
webView.loadUrl(str) 中的参数为 需要注入的JS代码。window.imagelistener.getImageSrc(src) 中的 imagelistener 对应的是addJavascriptInterface(new MJavascriptInterface(), "imagelistener");中的第二个参数 必须相同 ,window.imagelistener.getImageSrc(src)
语句调用的是 MJavascriptInterface() 中的 getImageSrc(src)
方法,window.imagelistener.getImagePath(back)
语句调用的是 MJavascriptInterface() 中的 getImagePath(back)
,然后我们就可以在 MJavascriptInterface() 对应的方法中获取到 我们需要的值了。