JSBridge实现Android和H5交互

  • 前言
  • 添加JSBridge库
  • 代码实现
  • AndroidManifest.xml
  • activity_main.xml
  • javascript.html
  • MainActivity.java
  • 效果图

前言

相比于WebView的自带的JavascriptInterface的接口,使用JSBridge实现Android和H5之间的交互会更加方便和安全,接下来介绍一下JSBridge的具体用法。

添加JSBridge库

在Android Studio的app/build.gradle添加如下配置,即可完成JSBridge库导入:

repositories {
	maven { url "https://jitpack.io" }
}

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

代码实现

接下来通过示例代码演示如何实现JS和Android之间的交互

AndroidManifest.xml

AndroidManifest.xml需要加入INTERNET权限:

<uses-permission android:name="android.permission.INTERNET" />

activity_main.xml

在activity_main.xml添加JSBridge的webView:

<com.github.lzyzsd.jsbridge.BridgeWebView
        android:id="@+id/activity_web_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

javascript.html

创建assets目录,并在assets目录下添加JS文件,这里命名为javascript.html。在javascript.html注册供Android调用的方法,并在点击按钮时调用Android注册的方法,实现交互,具体代码如下(实际项目中H5页面往往部署在服务器上,这个使用本地JS文件方便测试):

<html>
    <head>
        <meta content="text/html; charset=utf-8" http-equiv="content-type">
        <title>JSBridge测试</title>
        <script>

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

            connectWebViewJavascriptBridge(function(bridge) {
                //注册回调函数,接收Android端用send方法发送的消息
                bridge.init(function(message, responseCallback) {
                    alert("message from Java = " + message);
                    var responseData = "Received!";
                    responseCallback(responseData);
                });

                //注册回调函数,供Android调用,接收Android端发送的数据
                bridge.registerHandler("functionInJs", function(data, responseCallback) {
                    alert("data from Java = " + data);
                    var responseData = "Received!";
                    responseCallback(responseData);
                });
            })

            function queryInfo(key) {
                //调用Android端注册的getInformation方法进行数据查询
                window.WebViewJavascriptBridge.callHandler("getInfomation", key,
                function(responseData) {
                    alert("responseData from Java = " + responseData);
                });
            }

            function control(key) {
                //调用Android端注册的controlDevice方法进行设备状态控制
                window.WebViewJavascriptBridge.callHandler("controlDevice", key,
                function(responseData) {
                    alert("responseData from Java = " + responseData);
                });
            }

            function sendMessage(message) {
                //通过send方法向Android发送消息
                window.WebViewJavascriptBridge.send(message, function(responseData) {
                    alert("responseData from Java = " + responseData);
                });
            }

        </script>
    </head>

    <body>
        <p>JSBridge测试</p>
        <p><input type="button" value="查询设备类型" onclick='queryInfo("deviceType");'/></p>
        <p><input type="button" value="查询设备状态" onclick='queryInfo("deviceStatus");'/></p>
        <p><input type="button" value="打开设备" onclick='control("open");'/></p>
        <p><input type="button" value="关闭设备" onclick='control("close");'/></p>
        <p><input type="button" value="发送消息" onclick='sendMessage("Hello Android!");'/></p>
    </body>
</html>

MainActivity.java

在MainActivity.java中加载创建好的javascript.html,注册供JS调用的方法,并在启动时调用JS注册的方法发送消息和数据:

package com.example.testjsbridge;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.util.Log;
import android.webkit.WebChromeClient;

import com.github.lzyzsd.jsbridge.BridgeHandler;
import com.github.lzyzsd.jsbridge.BridgeWebView;
import com.github.lzyzsd.jsbridge.BridgeWebViewClient;
import com.github.lzyzsd.jsbridge.CallBackFunction;
import com.github.lzyzsd.jsbridge.DefaultHandler;

public class MainActivity extends Activity {

    BridgeWebView mWebView;
    String deviceType = "插座";
    boolean deviceStatus = false;
    String myData = "{data,1234567890}";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mWebView = (BridgeWebView) findViewById(R.id.activity_web_view);

        initWebView();
    }

    private void initWebView() {
        mWebView.setWebViewClient(new MyWebViewClient(mWebView));
        mWebView.setDefaultHandler(new MyHandlerCallback());
        mWebView.setWebChromeClient(new WebChromeClient());
        //开启webView的LocalStorage功能,使H5可以保存数据
        mWebView.getSettings().setDomStorageEnabled(true);
        //加载本地JS文件,实际项目中加载H5页面的url
        mWebView.loadUrl("file:///android_asset/javascript.html");

        //注册获取信息方法,供JS调用
        mWebView.registerHandler("getInfomation", new BridgeHandler() {
            @Override
            public void handler(String data, CallBackFunction function) {

                String responseData = "";
                Log.d("TestJsBridgeLog", "data from JS: " + data);
                if(data.contentEquals("deviceStatus")) {
                    if(deviceStatus) {
                        responseData = "开";
                    } else {
                        responseData = "关";
                    }
                } else if(data.contentEquals("deviceType")) {
                    responseData = deviceType;
                }
                //回调返回给JS
                function.onCallBack(responseData);
            }
        });

        //注册控制设备状态方法,供JS调用
        mWebView.registerHandler("controlDevice", new BridgeHandler() {
            @Override
            public void handler(String data, CallBackFunction function) {

                String responseData = "";
                Log.d("TestJsBridgeLog", "data from JS: " + data);
                if(data.contentEquals("open")) {
                    deviceStatus = true;
                    responseData = "打开设备成功";
                } else if (data.contentEquals("close")){
                    deviceStatus = false;
                    responseData = "关闭设备成功";
                } else {
                    responseData = "参数错误";
                }
                //回调返回给JS
                function.onCallBack(responseData);
            }
        });

        //调用send方法向JS发送消息
        mWebView.send("Hello JS!");

        //webView调用JS的方法发送数据
        mWebView.callHandler("functionInJs", myData, new CallBackFunction() {
            @Override
            public void onCallBack(String responseData) {
                //打印JS回复的消息
                Log.d("TestJsBridgeLog", "responseData from JS: " + responseData);
            }
        });

    }

    class MyWebViewClient extends BridgeWebViewClient {

        public MyWebViewClient(BridgeWebView webView) {
            super(webView);
        }

		//每次页面加载完成时,获取H5页面的title,可以根据项目需要使用
		@Override
        public void onPageFinished(WebView view, String url) {
            super.onPageFinished(view, url);
            String title = view.getTitle();
            if (!TextUtils.isEmpty(title)) {
                log("onPageFinished title:" + title);
            }
        }
    }

    //接收JS通过send方法发送的消息
    class MyHandlerCallback extends DefaultHandler {
        @Override
        public void handler(String data, CallBackFunction function) {
            super.handler(data, function);
            if (null != function) {
                Log.d("TestJsBridgeLog", "data from JS: " + data);
                function.onCallBack("收到JS消息");
            }
        }
    }

	//右滑时,返回上一个H5页面,H5页面多次跳转的项目中使用
	@Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK && mWebView.canGoBack()) {
            mWebView.goBack();
            return true;
        }
        return super.onKeyDown(keyCode, event);
    }
}

效果图

android 和H5的js交互无响应 android与h5交互框架_android