【问题产生】
Webview 通过 addjavascriptInterface 传递对象给前端,一切正常。但是 Android官方已提醒此功能是有安全风险,改用 safe-java-js-webview-bridge 做java和js交互。
官方的用法正常:
HostApp.alert
HostApp.toast
但如果我们在body里的
HostApp.alert(‘alert‘); //直接调用,无法找到HostApp
window.οnlοad= function(){
HostApp.toast(‘document ready now‘); //onload后调用,依然无法找到HostApp
};
$(document).ready(function(){
HostApp.toast(‘document ready now‘); //ready后调用,依然无法找到HostApp
});
【原因】
Safe Java-JS WebView Bridge 注入HostApp-JS片段的时机,可能在onload前也可能在其后。
如果document.ready的时候HostApp JS已经注入成功,在onload的时候调用没有问题。当onload的时候HostApp JS还未开始注入,就无法找到HostApp了。
【解决】
官方提供方法:
在js脚本层就需要做出变动,即轮询状态,直到端注入成功或者超时(1.5s),再发生回调。具体实现如下(下面的是以 zepto.js的$.ready()函数改造为例)。
//针对DOM的一些操作//Define methods that will be available on all//Zepto collections
$.fn ={//DOM Ready
ready: function(callback, jumpHostAppInject) {var originCb =callback;var mcounter = 0;//尝试等待(1500ms超时)让端注入HostApp Js
callback = function() {if(!window.HostApp && mcounter++ < 150)setTimeout(callback, 10);elseoriginCb($);
};//是否跳过等待HostApp的注入
if(jumpHostAppInject) {
callback=originCb;
}if (readyRE.test(document.readyState)) callback($); else document.addEventListener(‘DOMContentLoaded‘, function() {
callback($)
},false);return this},
...
...
};
这样的机制也就解释了为什么不把Java层的JS注入放在OnPageFinish了,如果那样页面轮询的次数就会上升,等待的时间就会变长,而且有可能会超时。好了,有了上面的改动,页面初始加载完备时需要立即触发HostApp的调用,如下:
$(function() {
HostApp.alert("HostApp ready now");
});
如果懒得去修改,可以到 gitHub 下载此插件提供的 zepto.js
由于本人项目没有用zepto,在初始化init的时候,按官方推荐的方法做了一个轮询。
var step = 0; //重试次数
window.οnlοad= function() {functionisReady() {if(step < 150 && !window.HostApp) { //重试150次
step ++;
setTimeout(isReady,10);
}else{
init();
}
}
isReady();
};
原文:http://www.cnblogs.com/dcchan/p/5630383.html