Android中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>

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

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值