【问题产生】

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 对象的更多相关文章

  1. Android NDK开发之Jni调用Java对象

    https://my.oschina.net/zhiweiofli/blog/114064 通过使用合适的JNI函数,你可以创建Java对象,get.set 静态(static)和 实例(instan ...

  2. Cordova插件中JavaScript代码与Java的交互细节介绍

    在Cordova官网中有这么一张架构图:大家看右下角蓝色的矩形框"Custom Plugin"--自定义插件.意思就是如果您用Cordova打包Mobile应用时,发现您的移动应用 ...

  3. android webView开发之js调用java代码示例

    1.webView设置 webView.getSettings().setJavaScriptEnabled(true);//设置支持js webView.addJavascriptInterface ...

  4. JNI系列——C文件中的方法调用Java中方法

    1.创建xxx.jni包并在该包下实现一些Java的方法,和要调用的本地方法 2.实现MainActivity中的按钮点击事件-即点击按钮调用本地的方法 3.在C文件中的方法中回调Java的方法 3. ...

  5. ios中javascript直接调用oc代码而非通过改变url回调方式(转)

    之前一个ios项目中,需要通过UIWebview来打开一个静态页面,并在静态页面中 调用相关object-c代码. 一.以前使用js调用object-c的方法 关于如何使用javascript调用ob ...

  6. 03_Android NDK中C语言调用Java代码,javah的使用,javap的使用以及生成签名,Android.mk的编写,C代码的编写

     1  案例场景,通过C语言回调Java的代码,案例的最终界面: 2  案例的代码结构如下: 3 编写DataProvider的代码: package com.example.ndkcallbac ...

  7. HAL中通过JNI调用java方法【转】

    转载请注明本文出处:http://www.cnblogs.com/xl19862005 作者:Xandy 由于工作的需要,最近一直在研究HAL.JNI.Java方法之间互调的问题,并做了如下一些记录和 ...

  8. 在webView 中使用JS 调用 Android / IOS的函数 Function

    最近做一个项目,混合了NativeCode 和 HTML,为了便于JS 调用App的一些方法,统一封装一个Js方法,记录如下 Android 端首先要再WebView中允许JS的调用 WebView ...

  9. Java中JSON字符串与java对象的互换实例详解

    这篇文章主要介绍了在java中,JSON字符串与java对象的相互转换实例详解,非常不错,具有参考借鉴价值,需要的朋友可以参考下 在开发过程中,经常需要和别的系统交换数据,数据交换的格式有XML.JS ...

随机推荐

  1. CSS3 animation的steps方式过渡

    animation默认以ease方式过渡,它会在每个关键帧之间插入补间动画,所以动画效果 是连贯性的.除了ease,linear.cubic-bezier之类的过渡函数都会为其插入补间. 但有些效果不 ...

  2. Matlab实现K-Means聚类算法

    人生如戏!!!! 一.理论准备 聚类算法,不是分类算法.分类算法是给一个数据,然后判断这个数据属于已分好的类中的具体哪一类.聚类算法是给一大堆原始数据,然后通过算法将其中具有相似特征的数据聚为一类. ...

  3. [转载]用c写PHP的扩展接口(php5,c++)

    原文[http://bugs.tutorbuddy.com/php5cpp/php5cpp/] 第1节. 开始之前 开始前,我要说明:这篇文章所描述的主要是在UNIX的PHP环境上的. 另外一点我要说 ...

  4. 用Firefly创建第一个工程

    原地址:http://blog.csdn.net/uxqclm/article/details/10382097 安装完成之后,在python script包中就存在 firefly-admin的工具 ...

  5. [Gauss]POJ1753 Flip Game

    题意:给4×4的棋盘的初始状态,b代表黑,w代表白. 要求变成全黑或者全白 最少需要几步. 简单的做法 可以暴搜 状压bfs 不再赘述 主要学习Gauss做法 同样是01方程组 用异或解 注意全黑或全 ...

  6. C#博文搜集

    1. abstract (抽象类) 参考1 2. interface (接口) 参考1 3. 委托 C#委托学习

  7. codeigniter 分页类练习

    controller page页: <?php class Blog extends CI_Controller{ public function __construct(){ parent:: ...

  8. SpringBoot入门 一 构建简单工程

    环境准备:jdk1.7(推荐)以上,tomcat8(推荐)以上,或者使用插件自带.mevan插件3.2以上,eclipse编辑工具 pom文件基本配置如下 <project xmlns=&quo ...

  9. 指令 scope

    angular学习笔记(三十)-指令(8)-scope <!DOCTYPE html> <html ng-app="myApp"> <head> ...

  10. Mac常用目录

    服务存放目录: ~/Library/Services/ Xcode代码片段目录 ~/Library/Developer/Xcode/UserData/CodeSnippets