《在WebView中如何让JS与Java安全地互相调用》核心JS全解析
2015-09-22 17:39
676 查看
1.说明:
《[在WebView中如何让JS与Java安全地互相调用](http://www.pedant.cn/2014/07/04/webview-js-java-interface-research/)》核心JS全解析2. 核心JS解析如下,欢迎拍砖!!!
javascript: (function(win) { console.log("HostApp initialization begin"); //win.HostApp对象 var H = { //回调函数队列 queue : [], //Java执行完毕后,调用此回调方法并传入一个索引。此回调方法根据索引,去回调函数队列中找到对应的回调方法 callback : function() { //获取Java传入的所有参数数组 var argArr = Array.prototype.slice.call(arguments, 0); console.log("queqe:" + this.queue); console.log("argArr:" + argArr); //获取第一个参数——回调方法的索引 var index = argArr.shift(); console.log("index:" + index); //获取第二个参数——是否是一个永久的方法(默认非永久)。当非永久方法的时候,使用完队列中的此回调方法后,删除此方法。 var isPerManent = argArr.shift(); console.log("isPerManent:" + isPerManent); console.log("argArr:" + argArr); console.log("queue[index]:" + this.queue[index]); //利用apply,将当前上下文和参数传入回调方法中 //(注意参数数组argArr的前面两个参数已经被shift取完并删除了,剩下的参数为此回调方法需要返回的数据,故传入此回调方法中) this.queue[index].apply(this, argArr); //如果是非永久的js方法,则回调完此方法之后,从队列中删除此方法 //(注意,方法虽然删除了,但只是删除的索引。也就是说,假设其它地方保留有此方法的索引,那么此方法不会被GC回收) if (!isPerManent) { delete this.queue[index] } } }; console.log("queqe:" + this.queue); H.alert = H.alert = H.alert = H.delayJsCallBack = H.getIMSI = H.getOsSdk = H.goBack = H.overloadMethod = H.overloadMethod = H.passJson2Java = H.passLongType = H.retBackPassJson = H.retJavaObject = H.testLossTime = H.toast = H.toast = function() { //获取业务中调用方法时,传入的所有参数数组 var argArr = Array.prototype.slice.call(arguments, 0); //第一个参数默认都是调用的方法本身的名字 //(虽然在业务中,没有传入方法的名字这个参数,但是下面的代码中,使用Object.getOwnPropertyNames方法, //获取了HostApp所有的属性,(当属性为function类型时)并将属性名当作第一个参数,拼接到业务传入的参数的最前面) if (argArr.length < 1) { throw "HostApp call error, message:miss method name" } //将要传入J***A端的类型数组 var typeArr = []; //循环所有业务传入的参数,获取每个参数的类型,存入到类型数组中。 for (var h = 1; h < argArr.length; h++) { var arg = argArr[h]; var argType = typeof arg; typeArr[typeArr.length] = argType; //如果发现传入的参数是回调函数,则将回调函数存入HostApp的回调函数队列中,并将参数的值替换为在回调函数在队列中的索引 //(注意,此时,尽管参数的值在argArr中只存了一个在队列中的索引,但参数的类型在typeArr中仍然存为function类型) if (argType == "function") { var queueLength = H.queue.length; H.queue[queueLength] = arg; argArr[h] = queueLength } } //传入方法名,参数类型数组以及业务传入的所有的参数,执行弹出框事件,让J***A端捕获。获取返回值,并转化为json对象。 var promptResultObj = JSON.parse(prompt(JSON.stringify({ method : argArr.shift(), types : typeArr, args : argArr }))); //如果返回码不为200,抛出异常 if (promptResultObj.code != 200) { throw "HostApp call error, code:" + promptResultObj.code + ", message:" + promptResultObj.result } //返回从J***A端获取到的返回值。 //(注意,业务中传入了回调方法的时候,大多数情况下,返回值通过在回调方法中获取。此时可以参考HostApp上的回调函数队列和callback方法) return promptResultObj.result }; //使用getOwnPropertyNames获取HostApp对象的所有属性,并循环。 //注意,forEach的第一个参数是数组元素(也就是HostApp的属性名),第二个参数是数组索引,后面依次是数组中的所有元素。 Object.getOwnPropertyNames(H).forEach( function(attrName) { var attrObj = H[attrName]; if (typeof attrObj === "function" && attrName !== "callback") { //此处是一个匿名的闭包函数,被HostApp的一个属性所引用。 //当HostApp中此属性一直存在时,局部变量attrName和attrObj可以被闭包函数永久访问,而不会被GC回收。 //显然,此处就已经把真实的函数(HostApp上所有相关属性,如getIMSI、getOsSdk)放到了一个只有闭包函数可以访问的局部变量attrObj里面了。 //总之,当前HostApp上所有的属性,只是一个闭包函数。但是,此闭包函数可以访问到之前的真实属性。 H[attrName] = function() { return attrObj.apply(H, [ attrName ] .concat(Array.prototype.slice .call(arguments, 0))) } } }); win.HostApp = H; console.log("HostApp initialization end") })(window);
相关文章推荐
- 在html中打开app
- Cocos2d-x 3.2打包错误总结
- 【转】iOS中几种数据持久化方案:我要永远地记住你!
- iOS开发CGD买票
- Android 核心分析 Service深入分析
- iOS开发CocoaPods使用详细说明
- HTML5 App的代码注入攻击
- WebView中文乱码
- 关于iOS 9 的一些新特性
- Android手势库
- iOS 音频播放的3中方式
- RecyclerView的点击事件,下拉刷新,上拉加载(Android5.0)
- objective-c 内存管理规范
- iOS开发脚踏实地学习day13-触摸事件和抽屉效果
- Android--内存管理,OOM问题
- iOS 快速创建常用控件
- Unity3D学习笔记(六)音乐和音效
- IOS CocoaPods安装和使用教程
- iOS相机字体英文转中文,相机全屏
- 关于IOS 开发 中的一些小技巧