JsBridge原理浅析与实践

                                    JsBridge原理浅析与实践

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。

1,Java调js:通过loadUrl和evaluateJavascript两个方法:

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完成了才能调用,否则有可能出现无法找到方法的错误。

2,Js调java:分三种:1,对象映射;2,URL拦截,3,方法拦截

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文件主要逻辑:

  1. var messageHandlers = [];  // 以键值对的形式存储js处理与java约定的handler方法
  2. var responseCallbacks = [];  // 以键值对的形式存储js的回调函数
  3. var defaultHandler;        // 默认处理java调用js的方法
  4. doSend(handlerName, data, responseCallback) // 通过iframe.src赋值,将”XYZ://_JS_BRIDGE_//message”传递给java(shouldOverrideUrlLoading回调),其中message根据定义的数据结构生成的一个json串。
  5. function handleMessageFromNative(){} // 接受java传递过来的消息
  6. 自定义一个WebviewJsBridgeRead的Event,如果本地的webviewJsBridge加载完毕就做一些初始化工作,比如初始化默认的Handler.

Java代码:

  1. HashMap messageHandlers;     // js调用的java方法
  2. HashMap responseCallbacks;  // 发送消息给js后的java回调
  3. BridgeHandler defaultHandler;   // 默认处理js调用java的方法
  4. public void doSend(String handlerName, String data, CallbackFunction responseCallback){} // 通过webview.loadUrl(“javascript:// handleMessageFromNative(message)”),handleMessageFromNative。 js会收到java传递过来的消息

Java主动发起调用js代码,message格式:{callbackId:JAVA_CB_1_1234,data:XXX,handlerName:null};java回调函数处理js带过来的responseData时序图:

JsBridge原理浅析与实践_第1张图片

Js主动发起调用java代码,message格式:{callbackId:JS_CB_1_1234,data:XXXX,handlerName:null};js回调函数处理java带过来的responseData时序图:

JsBridge原理浅析与实践_第2张图片

你可能感兴趣的:(android,javascript)