标签:
【问题产生】
Webview 通过 addjavascriptInterface 传递对象给前端,一切正常。但是 Android官方已提醒此功能是有安全风险,改用 safe-java-js-webview-bridge 做java和js交互。
官方的用法正常:
<ul class="entry"> <li onclick="HostApp.alert(‘HostApp.alert‘);">HostApp.alert</li> <li onclick="HostApp.toast(‘HostApp.toast‘);">HostApp.toast</li> </ul>
但如果我们在body里的<script>标签这样写,就无法获取HostApp对象:
HostApp.alert(‘alert‘); // 直接调用,无法找到HostApp window.onload = 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);else originCb($); }; //是否跳过等待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.onload = function () { function isReady() { if(step < 150 && !window.HostApp) { // 重试150次 step ++; setTimeout(isReady,10); } else { init(); } } isReady(); };
更多使用说明及完整源代码见:Safe Java-JS Bridge In Android WebView[Github]
参考:http://mobile.51cto.com/aprogram-452011.htm
Webview 中 Javascript 无法调用 Java 对象
标签:
原文地址:http://www.cnblogs.com/dcchan/p/5630383.html