WebView相关的两个重要的类:WebViewClient和WebViewClinet。
WebViewClient:帮助WebView处理各种通知,事件请求,主要的方法有:onLoadResource,onPageStart, onPageFInish, onReceiveError, ShouldOverrideUrlLoading。
WebChromeClient:处理javascript的对话框,网页图标,网站title,加载进度条。主要方法有:onCreateWindow, OnCloseWindow, onJsAlert, onJsConfirm, onJsConsole, onProgressChanged, onReceiveIcon, onReceiveTitle.
要实现JAVA和JS通信,就要解决:1,java调js;2,js调java。
loadUrl方法:例如通过webview.loadUrl(“javascript:alert(‘hello world’)”),可以将js代码注入到html页面执行。loadUrl可以直接调用js中的函数,也可以把android本地assets目录下的js文件读取到内存,获取字符串,直接把本地js文件注入到html页面,相当于在html页面中加载了一个本地js文件。对于客户端来说,和js的交互,本质上是拼接js字符串的过程,调用loadUrl不能直接获取js函数的返回值。
evaluateJavascript方法:和loadUrl方法类似,区别是:1,它可以获取调用的js函数的返回值;2,在android4.4以及上才可以使用。使用方法如下:
webview.evaluateJavascript(“javascript:alert(‘hello world’)”, new ValueCallback
@Override
public void onReceiveValue(String value){
System.out.println(“js函数返回值:” + value);
}
})。
需要注意的是一定要等onPageFinish完成了才能调用,否则有可能出现无法找到方法的错误。
1) 对象映射通过WebView的addJavascriptInterface方法把java对象映射到js对象,webview.addJavascriptInterface(new
JSObject(), “javaObject”),这样在js代码可以调用javaObject,就可以访问java代码。这个方法在android4.2以下有安全漏洞,
利用addJavascriptInterface方法注册可供javascript调用的java对象,利用反射机制调用Android API getRuntime执行shell命令进
行攻击,比如遍历sdcard,发送短信,安装木马APK等。
2) URL拦截,通过WebViewClient的shouldOverrideUrlLoading方法,拦截js代码执行例如:
“document.location=’js://webview?name=root&pwd=1234’”; 根据scheme(协议格式)和authority(协议名),获取name和
pwd。Js可以触发WebviewClient的shouldOverrideUrlLoading方法有:
1,document.loacation; 2,href; 3,window.open;4,iframe.src。
3)方法拦截,JS中执行对话框alert(警告框),prompt(提示框),confirm(确认框),console.log方法,可以触发
WebChromClinet的onJsAlert,onJsPrompt,onJsConfirm,onConsoleMessage的回调。alert会弹出对话框, confirm确定对
话框,console是用来debug javascript代码的,一般prompt使用的频率比较小,使用prompt来进行js调用java。
基于以上的前提,封装一个JsBridge框架将js和java的通信封装起来可以按如下思路进行:
JsBridge框架需要有一个本地的WebviewJsBridge.js文件和对应的java代码。
Java和js各自定义一个json串的消息传递的Message数据结构,形式如下:
{data: “”,
callbackId:””,
handlerName:””,
responseData:””,
responseId:””
}
本地js文件主要逻辑:
Java代码:
Java主动发起调用js代码,message格式:{callbackId:JAVA_CB_1_1234,data:XXX,handlerName:null};java回调函数处理js带过来的responseData时序图:
Js主动发起调用java代码,message格式:{callbackId:JS_CB_1_1234,data:XXXX,handlerName:null};js回调函数处理java带过来的responseData时序图: