码迷,mamicode.com
首页 > 编程语言 > 详细

Webview 中 Javascript 无法调用 Java 对象

时间:2016-06-30 20:01:21      阅读:160      评论:0      收藏:0      [点我收藏+]

标签:

【问题产生】

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

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!