Android與Js交互之JSBridge的使用

什么是JsBridge

JsBridge是js與Native之間進行通信的橋梁。

為什么要使用JsBridge

Android4.2以下的addJavascriptInterface存在安全漏洞,雖然在Android4.2之后用@JavascriptInterface代替了addJavascriptInterface但是由于兼容性和安全性問題,基本上我們不會再利用Android系統(tǒng)為我們提供的addJavascriptInterface方法或者@JavascriptInterface注解來實現(xiàn),所以我們只能另辟蹊徑,去尋找既安全,又能實現(xiàn)兼容Android各個版本的方案。

如何使用JsBridge

在Android中我們使用JsBridge開源項目來實現(xiàn),實現(xiàn)JSBridge分為以下幾個步驟。

步驟一:導入依賴

在項目gradle文件中添加
repositories {
        ...
        maven { url "https://jitpack.io" }
    }
在module的gradle中添加
dependencies {
    ...
    implementation 'com.github.lzyzsd:jsbridge:1.0.4'
}

步驟二:布局文件中用BridgeWebView代替WebView

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:orientation="vertical"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <EditText
        android:layout_width="match_parent"
        android:id="@+id/et"
        android:layout_height="wrap_content" />
    <Button
        android:layout_width="match_parent"
        android:text="調(diào)用js方法"
        android:id="@+id/bt"
        android:layout_height="wrap_content" />
    <com.github.lzyzsd.jsbridge.BridgeWebView
        android:id="@+id/webview"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

    </com.github.lzyzsd.jsbridge.BridgeWebView>
</LinearLayout>

步驟三:在Activity中對BridgeWebView進行配置

public class MainActivity extends AppCompatActivity {
    private EditText et;
    private Button bt;
    private BridgeWebView webview;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        et = (EditText) findViewById(R.id.et);
        bt = (Button) findViewById(R.id.bt);
        webview = (BridgeWebView) findViewById(R.id.webview);
        webview.setDefaultHandler(new DefaultHandler());
        webview.setWebChromeClient(new WebChromeClient());
        webview.loadUrl("file:///android_asset/test.html");
//      注冊監(jiān)聽方法當js中調(diào)用callHandler方法時會調(diào)用此方法(handlerName必須和js中相同)
        webview.registerHandler("submitFromWeb", new BridgeHandler() {
            @Override
            public void handler(String data, CallBackFunction function) {
                Log.e("TAG", "js返回:" + data);
                //顯示js傳遞給Android的消息
                Toast.makeText(MainActivity.this, "js返回:" + data, Toast.LENGTH_LONG).show();
                //Android返回給JS的消息
                function.onCallBack("我是js調(diào)用Android返回數(shù)據(jù):" + et.getText().toString());
            }
        });
        bt.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
//              調(diào)用js中的方法(必須和js中的handlerName想同)
                webview.callHandler("functionInJs", "Android調(diào)用js66", new CallBackFunction() {
                    @Override
                    public void onCallBack(String data) {
                        Log.e("TAG", "onCallBack:" + data);
                        Toast.makeText(MainActivity.this, data, Toast.LENGTH_LONG).show();
                    }
                });
            }
        });
    }
}

步驟四:編寫html文件并對應Activity中的參數(shù)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <!-- Compiled and minified CSS -->
    <link rel="stylesheet" href="./materialize.min.css">
    <!-- Compiled and minified JavaScript -->
    <script src="./materialize.min.js"></script>
    <title>Test</title>
</head>
<body>
<div class="input-field col s6">
    <input placeholder="請輸入數(shù)據(jù)" id="text1" type="text" class="validate">
</div>
<a class="waves-effect waves-light btn" onclick="testClick();">button</a>
</body>
<script>

         //js調(diào)用Android方法:接收Android傳遞過來的數(shù)據(jù),并做處理

         function testClick() {

          //參數(shù)一:調(diào)用java中的方法   submitFromWeb是方法名,必須和Android中注冊時候的方法名稱保持一致
          //參數(shù)二:返回給Android端的數(shù)據(jù),可以為字符串,json等信息
          //參數(shù)三:js接收到Android傳遞過來的數(shù)據(jù)之后的相應處理邏輯

            window.WebViewJavascriptBridge.callHandler(
               'submitFromWeb'
               , {'param': "JS成功接收到數(shù)據(jù)---"}
               , function(responseData) {
                    alert(responseData)
               }
           );
       }

       //JS注冊事件監(jiān)聽
       function connectWebViewJavascriptBridge(callback) {
           if (window.WebViewJavascriptBridge) {
               callback(WebViewJavascriptBridge)
           } else {
               document.addEventListener(
                   'WebViewJavascriptBridgeReady'
                   , function() {
                       callback(WebViewJavascriptBridge)
                   },
                   false
               );
           }
       }

        //注冊回調(diào)函數(shù),第一次連接時調(diào)用 初始化函數(shù)
       connectWebViewJavascriptBridge(function(bridge) {
            //初始化
           bridge.init(function(message, responseCallback) {
               var data = {
                   'Javascript Responds': 'Wee!'
               };
               alert("jasdashjd");
               responseCallback(data);
           });


           //Android調(diào)用js方法:functionInJs方法名稱需要保持一致 ,并返回給Android通知

           bridge.registerHandler("functionInJs", function(data, responseCallback) {
               alert(data);
               var data2 = document.getElementById("text1").value;
               var responseData = "我是Android調(diào)用js方法返回的數(shù)據(jù)---"+ data2;
               responseCallback(responseData);
           });
       })

</script>
</html>

步驟五:將html文件放入assets文件夾中

效果展示:

補充:

jsbridge調(diào)用默認的方法

●Activity代碼

// 重寫handler方法接收js的消息
 webview.setDefaultHandler(new DefaultHandler(){
            @Override
            public void handler(String data, CallBackFunction function) {
                Toast.makeText(MainActivity.this, data, Toast.LENGTH_SHORT).show();
                function.onCallBack("Android收到了默認的消息");
            }
        });
        bt2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
//              發(fā)送信息給js,此處不需要配置handlerName
                webview.send(et.getText().toString().trim(), new CallBackFunction() {
                    @Override
                    public void onCallBack(String data) {
//                      接收js的回調(diào)數(shù)據(jù)
                        Toast.makeText(MainActivity.this, data, Toast.LENGTH_SHORT).show();
                    }
                });
            }
        });

●html代碼

 //初始化
           bridge.init(function(message, responseCallback) {
               var data = {
                   'Javascript Responds': 'Wee!'
               };
               //添加代碼用來彈出Activity發(fā)送的默認消息
               alert(message);
               responseCallback(data);
           });
// 加入如下方法用于發(fā)送消息給Activity
function testClick2() {
var data2 = document.getElementById("text1").value;
          //參數(shù)一:調(diào)用java中的方法   submitFromWeb是方法名,必須和Android中注冊時候的方法名稱保持一致
          //參數(shù)二:返回給Android端的數(shù)據(jù),可以為字符串,json等信息
          //參數(shù)三:js接收到Android傳遞過來的數(shù)據(jù)之后的相應處理邏輯

            window.WebViewJavascriptBridge.send(
        data2,
        function(responseData){
            //java中DefaultHandler所實現(xiàn)的方法中callback所定義的入?yún)?            alert(responseData);
        }
    );
       }

案例源碼

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容