文档章节

Android混合开发之WebViewJavascriptBridge实现JS与java安全交互

丁佳辉
 丁佳辉
发布于 2017/07/13 12:27
字数 2030
阅读 15
收藏 0
点赞 0
评论 0

前言:

     为了加快开发效率,目前公司一些功能使用H5开发,这里难免会用到Js与Java函数互相调用的问题,这个Android是提供了原生支持的,不过存在安全隐患,今天我们来学习一种安全方式来满足Js与java互相调用的需求。它就是WebViewJavascriptBridge。

学习动机:

    先看下之前的解决办法:Android混合开发之WebView与Javascript交互

    最近棒棒安全的一个市场推广来我们公司推广他们的产品,当时也没太引起我的注意,后来这个市场推广人员把我们的app的进行了他们的安全验证,然后发给我一份检测报告,关于WebView的检测内容大致如下:

其实目前公司采用H5的业务都是相对不是很重要的一些业务,而且安全性要求相对比较低,不过作为技术负责人的我,觉得现在很有必要尽快寻找一个相对安全的方式来解决这个问题,算是未雨绸缪吧。经过搜过资料寻找的解决办法就是使用WebViewJavascriptBridge来实现Js与Java的互相调用。

WebViewJavascriptBridge介绍:

 WebViewJavascriptBridge是WebView和Js交互通信的桥梁,用作者的话来说就是实现java和js的互相调用的桥梁。替代了WebView的自带的JavascriptInterface的接口,使得开发者更方便的让js和native灵活交互,使我们的开发更加灵活和安全。

 目前实现JSBridge的开源框架很多,这里采用的hi大头鬼hi写的开源框架:https://github.com/lzyzsd/JsBridge

WebViewJavascriptBridge使用方式:

1.)添加配置信息

project的build.gradle中添加如下配置

复制代码

allprojects {
    repositories {
        jcenter()
        maven { url "https://jitpack.io" }
    }
}

复制代码

在module的build.pradle中添加如下配置

dependencies {
    compile 'com.github.lzyzsd:jsbridge:1.0.4'
}

2.)用BridgeWebView替换WebView

<com.github.lzyzsd.jsbridge.BridgeWebView
        android:id="@+id/test_bridge_webView"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"/>

3.)Js调用Java方法并传递数据

 可以通过registerHandler()用来注册一个java函数,来实现js回调的handler

复制代码

//必须和js同名函数,注册具体执行函数,类似java实现类。
        //第一参数是订阅的java本地函数名字 第二个参数是回调Handler , 参数返回js请求的resqustData,function.onCallBack()回调到js,调用function(responseData)
        mBridgeWebView.registerHandler("submitFromWeb", new BridgeHandler() {

            @Override
            public void handler(String data, CallBackFunction function) {
                Log.e(TAG, "指定Handler接收来自web的数据:" + data);
                function.onCallBack("指定Handler收到Web发来的数据,回传数据给你");
            }
        });

复制代码

Js调用指定函数并传递参数

复制代码

function testClick1() {
           //调用本地java方法
           //第一个参数是 调用java的函数名字 第二个参数是要传递的数据 第三个参数js在被回调后具体执行方法,responseData为java层回传数据
           var data='发送消息给java代码指定接收';
           window.WebViewJavascriptBridge.callHandler(
               'submitFromWeb'
               ,data
               , function(responseData) {
                   bridgeLog('来自Java的回传数据: ' + responseData);
               }
           );
       }

复制代码

也可以mBridgeWebView.setDefaultHandler()设置DefaultHandler,这样可以接收Js通过window.WebViewJavascriptBridge通过send的所有数据

复制代码

mBridgeWebView.setDefaultHandler(new BridgeHandler() {
            @Override
            public void handler(String data, CallBackFunction function) {
                Log.e(TAG, "DefaultHandler接收全部来自web的数据:"+data);
                function.onCallBack("DefaultHandler收到Web发来的数据,回传数据给你");
            }
        });

复制代码

js实现向java发送数据

复制代码

function testClick() {
           //发送消息给java代码
           var data = '发送消息给java代码全局接收';

           window.WebViewJavascriptBridge.send(
               data
               , function(responseData) {
                  bridgeLog('来自Java的回传数据: ' +responseData);
               }
           );
       }

复制代码

4.)Java调用Js方法并传递参数

复制代码

//注册事件监听
       function connectWebViewJavascriptBridge(callback) {
           if (window.WebViewJavascriptBridge) {
               callback(WebViewJavascriptBridge)
           } else {
               document.addEventListener(
                   'WebViewJavascriptBridgeReady'
                   , function() {
                       callback(WebViewJavascriptBridge)
                   },
                   false
               );
           }
       }

复制代码

在使用WebViewJavaScriptBridge的时候需要首先判断一下WebViewJavaScriptBridge是否存在,如果不存在需要通过添加监听'WebViewJavascriptBridgeReady'来监听

复制代码

//注册回调函数,第一次连接时调用 初始化函数
       connectWebViewJavascriptBridge(function(bridge) {
           bridge.init(function(message, responseCallback) {
               bridgeLog('默认接收收到来自Java数据: ' + message);
               var responseData = '默认接收收到来自Java的数据,回传数据给你';
               responseCallback(responseData);
           });

           bridge.registerHandler("functionInJs", function(data, responseCallback) {
               bridgeLog('指定接收收到来自Java数据: ' + data);
               var responseData = '指定接收收到来自Java的数据,回传数据给你';
               responseCallback(responseData);
           });
       })

复制代码

通过上面的链接WebViewJavascriptBridge可以得到一个可用WebViewJavascriptBridge,可以通过init方法来设置一个默认接收所以java发来的数据的回调,也可以通过registerHandler设置指定接收方法。

java发送数据给Js默认接收

复制代码

mBridgeWebView.send("发送数据给web默认接收",new CallBackFunction(){
                    @Override
                    public void onCallBack(String data) {
                        Log.e(TAG, "来自web的回传数据:" + data);
                    }
                });

复制代码

java发送数据给Js指定方法接收

复制代码

mBridgeWebView.callHandler("functionInJs","发送数据给web指定接收",new CallBackFunction(){
                    @Override
                    public void onCallBack(String data) {
                        Log.e(TAG, "来自web的回传数据:" + data);
                    }
                });

复制代码

 5.)整个示例

为了方便学习,贴出整个示例

 MainActivity

复制代码

public class MainActivity extends AppCompatActivity {
private static  final  String TAG=MainActivity.class.getSimpleName();
    private BridgeWebView mBridgeWebView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initViews();
    }

    private void  initViews(){
        mBridgeWebView= (BridgeWebView) findViewById( R.id.test_bridge_webView);
        mBridgeWebView.loadUrl("file:///android_asset/wx.html");

        mBridgeWebView.setDefaultHandler(new BridgeHandler() {
            @Override
            public void handler(String data, CallBackFunction function) {
                Log.e(TAG, "DefaultHandler接收全部来自web的数据:"+data);
                function.onCallBack("DefaultHandler收到Web发来的数据,回传数据给你");
            }
        });

        //必须和js同名函数,注册具体执行函数,类似java实现类。
        //第一参数是订阅的java本地函数名字 第二个参数是回调Handler , 参数返回js请求的resqustData,function.onCallBack()回调到js,调用function(responseData)
        mBridgeWebView.registerHandler("submitFromWeb", new BridgeHandler() {

            @Override
            public void handler(String data, CallBackFunction function) {
                Log.e(TAG, "指定Handler接收来自web的数据:" + data);
                function.onCallBack("指定Handler收到Web发来的数据,回传数据给你");
            }
        });
        findViewById(R.id.to_web_default).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                mBridgeWebView.send("发送数据给web默认接收",new CallBackFunction(){
                    @Override
                    public void onCallBack(String data) {
                        Log.e(TAG, "来自web的回传数据:" + data);
                    }
                });
            }
        });
        findViewById(R.id.to_web).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                mBridgeWebView.callHandler("functionInJs","发送数据给web指定接收",new CallBackFunction(){
                    @Override
                    public void onCallBack(String data) {
                        Log.e(TAG, "来自web的回传数据:" + data);
                    }
                });
            }
        });
    }
}

复制代码

activity_main.xml

复制代码

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:orientation="vertical"
    android:paddingBottom="@dimen/activity_vertical_margin"
    tools:context="com.whoislcj.jsbridge.MainActivity">

    <com.github.lzyzsd.jsbridge.BridgeWebView
        android:id="@+id/test_bridge_webView"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"/>
    <Button
        android:id="@+id/to_web_default"
        android:layout_margin="10dp"
        android:layout_width="match_parent"
        android:text="默认传递数据给Web"
        android:layout_height="wrap_content"/>
    <Button
        android:id="@+id/to_web"
        android:layout_margin="10dp"
        android:layout_width="match_parent"
        android:text="指定传递数据给Web"
        android:layout_height="wrap_content"/>
</LinearLayout>

复制代码

wx.html

复制代码

<html>
<head>
    <meta http-equiv="Content-Type" content="text/html;charset=utf-8">
    <script >

       function testClick() {
           //发送消息给java代码
           var data = '发送消息给java代码全局接收';
           //第一个参数要发送的数据 第二个参数js在被回调后具体执行方法,responseData为java层回传数据
           window.WebViewJavascriptBridge.send(
               data
               , function(responseData) {
                  bridgeLog('来自Java的回传数据: ' +responseData);
               }
           );
       }

       function testClick1() {
           //调用本地java方法
           //第一个参数是 调用java的函数名字 第二个参数是要传递的数据 第三个参数js在被回调后具体执行方法,responseData为java层回传数据
           var data='发送消息给java代码指定接收';
           window.WebViewJavascriptBridge.callHandler(
               'submitFromWeb'
               ,data
               , function(responseData) {
                   bridgeLog('来自Java的回传数据: ' + responseData);
               }
           );
       }

       function bridgeLog(logContent) {
           document.getElementById("log_msg").innerHTML = logContent;
       }

       //注册事件监听
       function connectWebViewJavascriptBridge(callback) {
           if (window.WebViewJavascriptBridge) {
               callback(WebViewJavascriptBridge)
           } else {
               document.addEventListener(
                   'WebViewJavascriptBridgeReady'
                   , function() {
                       callback(WebViewJavascriptBridge)
                   },
                   false
               );
           }
       }
       //注册回调函数,第一次连接时调用 初始化函数
       connectWebViewJavascriptBridge(function(bridge) {
           bridge.init(function(message, responseCallback) {
               bridgeLog('默认接收收到来自Java数据: ' + message);
               var responseData = '默认接收收到来自Java的数据,回传数据给你';
               responseCallback(responseData);
           });

           bridge.registerHandler("functionInJs", function(data, responseCallback) {
               bridgeLog('指定接收收到来自Java数据: ' + data);
               var responseData = '指定接收收到来自Java的数据,回传数据给你';
               responseCallback(responseData);
           });
       })
   </script>

</head>
<body>
<p>WebViewJsBridge</p>
<div>
    <button onClick="testClick()">发送数据给默认Handler接收</button>
</div>
<br/>
<div>
    <button onClick="testClick1()">发送数据给指定Handler接收</button>
</div>
<br/>
<div id="log_msg">调用打印信息</div>
</body>
</html>

复制代码

 总结:

    这里仅仅是先找到了一种安全的调用方式,并没有进行真正的商用验证,接下来会对这个框架进一步了解,然后推广使用。

 

干我们这行,啥时候懈怠,就意味着长进的停止,长进的停止就意味着被淘汰,只能往前冲,直到凤凰涅槃的一天!

本文转载自:http://www.cnblogs.com/whoislcj/p/6104015.html

共有 人打赏支持
丁佳辉
粉丝 18
博文 382
码字总数 195396
作品 0
浦东
程序员
iOS下JS与OC互相调用(六)--WKWebView + WebViewJavascriptBridge

iOS下JS与OC互相调用(六)--WKWebView + WebViewJavascriptBridge 转载:原地址 https://www.jianshu.com/p/e951af9e5e74 上一篇文章介绍了UIWebView 如何通过WebViewJavascriptBridge 来实现......

法斗斗 ⋅ 05/11 ⋅ 0

iOS一些代码的取巧写法总结(二)

一、在xib/storyboard里面设置view圆角半径 在xib/storyboard里面设置view圆角半径 神奇的IB_DESIGNABLE和IBInspectable(xib中设置圆角) 二、push pop 动画突然消失的解决方案 产生的原因是动...

朝雨晚风 ⋅ 2016/12/05 ⋅ 0

3.3 Js、App和缓存---熊孩子、篮子和仓库

前端组合:熊孩子、村姑、化妆师   上次在这提到村姑和化妆师的故事,其实村姑背后有个大家族。上次教大家如何用代码做自我介绍,其实用到了JavaScript(简称js)。   html只是个静态页面...

产品经理的技术课堂 ⋅ 04/26 ⋅ 0

Android 开发必学!Kotlin初学者教程

Kotlin是由JetBrains为现代多平台应用程序开发的一种编程语言。 在本综合指南中,你可以获得以下信息: 为什么要学习Kotlin? 如何开始? 如何学习它? 在学习Kotlin之前要知道的事情 为什么...

实验楼 ⋅ 06/21 ⋅ 0

继 Java 版权案之后,甲骨文公司开始向 JavaScript 伸手!

就在 JavaScript 成为 GitHub 网站最为流行、越来越受到广大开发者热衷的编程语言之际,国外网站 reddit 的一篇求助性帖子引发行业内的热议。 帖子大意就是,该作者收到苹果公司的一封邮件,...

亦枫 ⋅ 04/19 ⋅ 0

学java还是javascript好?哪个更有前途?

  对于哪种语言好这种问题,其实并没有固定的答案,最重要的还是 兴趣!兴趣!兴趣!重要的事情说三遍。无论做什么开发,永远要以兴趣来驱动自己学习。 先大致的说一下,Java学习是一个需要...

W3Cschool小编 ⋅ 04/23 ⋅ 0

C、C++、Java、JavaScript、PHP、Python分别用来开发什么?

C、C++、Java、JavaScript、PHP、Python分别用来开发什么? 2018-05-25 11:47编辑: 游星啊分类:程序人生来源:代码湾 开发程序人生C 招聘信息: C++工程师 Cocos2d-x游戏客户端开发 iOS开发...

游星啊 ⋅ 05/25 ⋅ 0

艾润物联/vehicle-keyboard-android

停车王车牌号码专用键盘 VehicleKeyboard - Android 是停车王品牌的各端产品线的基础组件,专为提高中国车牌号码输入速度而定制开发的专用键盘组件,包括以下三个项目: Android项目,为And...

艾润物联 ⋅ 04/24 ⋅ 0

android h5 js 匿名函数通信

android js 互相调用 支持js匿名函数接收 支持js json对象接收 支持js函数返回值获取 通过注解注入js方法,支持自定义方法名 github https://github.com/lwugang/android-js-bridge Add it i...

liwg ⋅ 04/25 ⋅ 0

React Native通信原理源码分析二

本篇文章已授权微信公众号 JueCode 独家发布 在上一篇中分析了Native调用JavaScript的原理,这一篇我们分析下JavaScript调用Native的原理。上一篇提到的内容这里就不重复了,建议小伙伴们先看...

juexingzhe ⋅ 04/16 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

个人博客的运营模式能否学习TMALL天猫质量为上?

心情随笔|个人博客的运营模式能否学习TMALL天猫质量为上? 中国的互联网已经发展了很多年了,记得在十年前,个人博客十分流行,大量的人都在写博客,而且质量还不错,很多高质量的文章都是在...

原创小博客 ⋅ 今天 ⋅ 0

JavaScript零基础入门——(十一)JavaScript的DOM操作

JavaScript零基础入门——(十一)JavaScript的DOM操作 大家好,欢迎回到我们的JavaScript零基础入门。最近有些同学问我说,我讲的的比书上的精简不少。其实呢,我主要讲的是我在开发中经常会...

JandenMa ⋅ 今天 ⋅ 0

volatile和synchronized的区别

volatile和synchronized的区别 在讲这个之前需要先了解下JMM(Java memory Model :java内存模型):并发过程中如何处理可见性、原子性、有序性的问题--建立JMM模型 详情请看:https://baike.b...

MarinJ_Shao ⋅ 今天 ⋅ 0

深入分析Kubernetes Critical Pod(一)

Author: xidianwangtao@gmail.com 摘要:大家在部署Kubernetes集群AddOn组件的时候,经常会看到Annotation scheduler.alpha.kubernetes.io/critical-pod"="",以表示这是一个关键服务,那你知...

WaltonWang ⋅ 今天 ⋅ 0

原子性 - synchronized关键词

原子性概念 原子性提供了程序的互斥操作,同一时刻只能有一个线程能对某块代码进行操作。 原子性的实现方式 在jdk中,原子性的实现方式主要分为: synchronized:关键词,它依赖于JVM,保证了同...

dotleo ⋅ 今天 ⋅ 0

【2018.06.22学习笔记】【linux高级知识 14.4-15.3】

14.4 exportfs命令 14.5 NFS客户端问题 15.1 FTP介绍 15.2/15.3 使用vsftpd搭建ftp

lgsxp ⋅ 今天 ⋅ 0

JeeSite 4.0 功能权限管理基础(Shiro)

Shiro是Apache的一个开源框架,是一个权限管理的框架,实现用户认证、用户授权等。 只要有用户参与一般都要有权限管理,权限管理实现对用户访问系统的控制,按照安全规则或者安全策略控制用户...

ThinkGem ⋅ 昨天 ⋅ 0

python f-string 字符串格式化

主要内容 从Python 3.6开始,f-string是格式化字符串的一种很好的新方法。与其他格式化方式相比,它们不仅更易读,更简洁,不易出错,而且速度更快! 在本文的最后,您将了解如何以及为什么今...

阿豪boy ⋅ 昨天 ⋅ 0

Python实现自动登录站点

如果我们想要实现自动登录,那么我们就需要能够驱动浏览器(比如谷歌浏览器)来实现操作,ChromeDriver 刚好能够帮助我们这一点(非谷歌浏览器的驱动有所不同)。 一、确认软件版本 首先我们...

blackfoxya ⋅ 昨天 ⋅ 0

线性回归原理和实现基本认识

一:介绍 定义:线性回归在假设特证满足线性关系,根据给定的训练数据训练一个模型,并用此模型进行预测。为了了解这个定义,我们先举个简单的例子;我们假设一个线性方程 Y=2x+1, x变量为商...

wangxuwei ⋅ 昨天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部