您的位置:首页 > 移动开发 > Android开发

android WebView与JS交互小结

2015-10-10 14:15 579 查看
android里边的WebView是一个经常用到的控件,尤其随着H5的发展,WebView被应用的更多。在使用WebView时,与JS交互是一个常见的场景,这里我简单的总结一下。

开启JS

为何要开启

开启很简单, 但是做之前我们可以先想一下为什么要开启JS支持。

其实开JS支持的最主要作用是使得H5页面可以正常运行,因为H5的火爆相当程度上要依靠JS的支撑,才实现那么多酷炫的效果。

我刚开始接触WebView与JS交互的时候,想当然的认为开启JS支持就是为了与JS交互。自己关闭了JS的支持,调试了一下才体会到原来并不是这个。

如何开启

开启的方法其实相当简单,如下:

webView.getSettings().setJavaScriptEnabled(true);


Java调用JS

Java调用JS相当简单,如下:

String call = "javascript:javaCallJsWithArgs('我来自Java')";
webView.loadUrl(call);


上面的代码让我想到了在Html页面里边调用JS函数也是类似的写法

<a onClick="javascript:javaCallJsWithArgs('我来自Html')">在Html页面里执行的Js函数</a>


不过在Html里边一般使用简写,即把前缀”javascript:”去掉,但是对于WebView来说则不能去掉,否则无法区别是要load一个url还是要执行一个javascript函数了。

JS调用Java

如何调用

API Level < 17

以前我们可以这样写

webView.addJavascriptInterface(new Object(){
public void callJavaFunction(){
Toast.makeText(getApplicationContext(), "通过js调用了java函数", Toast.LENGTH_SHORT).show();
}
}, "jsInteraction");


API Level >= 17

现在需要这样写才能正常调用

webView.addJavascriptInterface(new Object(){
@JavascriptInterface
public void callJavaFunction(){
Toast.makeText(getApplicationContext(), "通过js调用了java函数", Toast.LENGTH_SHORT).show();
}
}, "jsInteraction");


对了,在Html中我们需要怎么调用在Java里定义的方法呢?

如下

<a onClick="window.jsInteraction.callJavaFunction()">点击调用java代码</a>


看起来WebView#addJavascriptInterface()方法将传入的对象加入到了JS中window对象下面了。

上面定义Java逻辑的两种写法的区别在于后者显式的需要我们对要暴露到js中的方法加上注解”@JavascriptInterface”。因为之前的版本引发了一个安全问题,具体见下面的内容。

另一种方法

TO BE ADDED

安全问题

问题产生的原因

在API Level < 17时(即4.2版本之前),JS通过WebView暴露的对象,可以访问其任意的public fields(我专门测试了一下,静态方法和实例方法都可以被访问)。

这里边最严重的是Object#getClass()方法,网上传的都是通过JS调用Java对象的这个方法来达到执行恶意操作的目的,在这里我就不复制粘贴了,参考部分贴的链接里边都有相应的示例代码。

其实,我在老的模拟器里边(genymotion 2.3.7, 4.1.1)调试,发现JS调用getClass().forName()方法并不能正常执行,不知道这些版本模拟器是否经过调整。

解决方案

如果只适配API Level >= 17的设备,那google已经解决了这个问题,通过加上”@JavascriptInterface”注解暴露给JS指定的方法。

如果是适配老的设备

不需要JS与Java交互,但要保证Html页面里的JS正常执行

这种情况比较简单,首先不要addJavaInterface(),此外还要调用
webView.removeJavascriptInterface("searchBoxJavaBridge_")
删除掉系统自动添加到JS中的interface,名字为
searchBoxJavaBridge_


需要JS与Java交互

首先要执行上面的操作删除暴露给JS的interface。

这里边有另外一种思路[1](看到别人写得,觉得应该可行,不过我并没有试验),即在Html中需要与Java交互的地方调用JS的alert, prompt, confirm方法,然后系统会调用WebChromeClient里对应的回调,即onJsAlert, onJsPrompt, onJsConfirm方法。

拓展思考

前面调试JS调用Java静态方法的时候发现如下的一段log:

D/dalvikvm: GetMethodID: not returning static method LXXX/JSInteractionActivity$JSInterfaceClass;.callJavaFunction ()V
D/: 通过JS调用了Java的静态函数


由此可以推断出JS调用Java方法是通过Java反射来实现的,可以通过查阅WebView的源代码来验证这个猜测。在这里先留给自己一个ToDo Task。

参考

Android WebView的Js对象注入漏洞解决方案

WebView注入Java对象注意事项

百度网易等数大量安卓应用存在远程代码执行漏洞
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  android webview javascript