1. 程式人生 > >JSBridge連線JAVA和JS的橋樑

JSBridge連線JAVA和JS的橋樑

今天帶來github上的一個開源庫,JSBridge!
什麼是JSBridge ?
其實很好理解,是一個Java和JavaScript之間的一座橋樑。
為什麼要用JSBridge?
它提供了安全、方便的方式從js呼叫Java程式碼和呼叫js程式碼從Java。

效果圖:
這裡寫圖片描述

可能看效果,剛開始會有點不明白。沒事,仔細看下下面的介紹,相信你會對這個庫有個深入的瞭解,其實內容不是很多!

首先引入github上的依賴庫:
app目錄下的.build檔案

dependencies {
    compile 'com.github.lzyzsd.jsbridge:library:1.0.0'
}

JS呼叫原生的方法,實現JS傳參到原生,原生響應資料給JS。

JS中程式碼:

 function testClick1() {
            var str1 = document.getElementById("text1").value;
            var str2 = document.getElementById("text2").value;

            //call native method關鍵方法,呼叫原生方法
            window.WebViewJavascriptBridge.callHandler(
                'submitFromWeb'
//原生的方法名 , {'param': str1}//帶個原生方法的引數 , function(responseData) {//響應原生回撥方法 document.getElementById("show").innerHTML = "send get responseData from java, data = " + responseData } ); }

原生中的方法:

//JS呼叫原生的方法,原生方法名與JS呼叫一致
webView.registerHandler("submitFromWeb", new BridgeHandler() { @Override public void handler(String data, CallBackFunction function) {//data是Js傳來的資料,function方法是回撥給Js的(帶Str引數) Log.i(TAG, "handler = submitFromWeb, data from web = " + data);//data即為JS傳來的使用者名稱 function.onCallBack("submitFromWeb exe, response data from Java");//返回給JS的資料 } });

設定一個預設的handler,這樣Js呼叫原生的方法時不需要宣告Handler的名稱

原生方法:

webView.setDefaultHandler(new DefaultHandler());

Js方法:

 function testClick() {
            var str1 = document.getElementById("text1").value;
            var str2 = document.getElementById("text2").value;

            //send message to native
            var data = "name=" + str1 + ",pass=" + str2;
            window.WebViewJavascriptBridge.send(
                data
                , function(responseData) {
                    document.getElementById("show").innerHTML = "repsonseData from java, data = " + responseData
                }
            );

這樣Js呼叫原生的方法返回的響應資料,其實是DefaultHandler中實現的:

public class DefaultHandler implements BridgeHandler {
    String TAG = "DefaultHandler";

    public DefaultHandler() {
    }

    public void handler(String data, CallBackFunction function) {
        if(function != null) {
            function.onCallBack("DefaultHandler response data");
        }

    }
}

感覺這個方法不是特別實用,接著往下看!

原生呼叫Js中的放法:

原生方法:

@Override
    public void onClick(View v) {
        if (button.equals(v)) {
            //原生通過callHandler方法,可以調起JS中名為functionInJs的方法
            webView.callHandler("functionInJs", "data from Java", new CallBackFunction() {

                @Override
                public void onCallBack(String data) {
                    // TODO Auto-generated method stub
                    //data是Js的functionInJs中返回的資料
                    Log.i(TAG, "reponse data from js " + data);
                }

            });
        }

    }

JS中functionInJs的方法:

connectWebViewJavascriptBridge(function(bridge) {
            bridge.init(function(message, responseCallback) {
                console.log('JS got a message', message);
                var data = {
                    'Javascript Responds': 'Wee!'
                };
                console.log('JS responding with', data);
                responseCallback(data);
            });

            //這裡就是Js註冊的functionInJs方法,data即為原生帶來的引數
            bridge.registerHandler("functionInJs", function(data, responseCallback) {
                //將原生帶來的引數,顯示在show標籤位置
                document.getElementById("show").innerHTML = ("data from Java: = " + data);
                var responseData = "Javascript Says Right back aka!";
                //呼叫responseCallback方法可以帶傳引數到原生
                responseCallback(responseData);
            });
        })

OK,那麼上面效果預設進來的時候show標籤裡面的資料是哪裡來的呢,其實在原生的MainActivity中還有一個地方呼叫了Js中註冊的functionInJs方法

MainActicvity方法中,這裡user是原生定義的一個物件

//將User物件傳遞給JS的functionInJs方法,同樣會走到上面Js的functionInJs方法中
  webView.callHandler("functionInJs", new Gson().toJson(user), new CallBackFunction() {
            @Override
            public void onCallBack(String data) {

            }
        });

再來看js裡面選擇檔案上傳的,呼叫原生的方法

js中只要宣告:

<input type="file" value="開啟檔案" />

即可,主要工作在原生的MainActivity中執行:

webView.setWebChromeClient(new WebChromeClient() {

            @SuppressWarnings("unused")
            public void openFileChooser(ValueCallback<Uri> uploadMsg, String AcceptType, String capture) {
                this.openFileChooser(uploadMsg);
            }

            @SuppressWarnings("unused")
            public void openFileChooser(ValueCallback<Uri> uploadMsg, String AcceptType) {
                this.openFileChooser(uploadMsg);
            }

            public void openFileChooser(ValueCallback<Uri> uploadMsg) {
                mUploadMessage = uploadMsg;
                pickFile();
            }
        });

pickFile()方法是原生調起本地相簿

public void pickFile() {
        Intent chooserIntent = new Intent(Intent.ACTION_GET_CONTENT);
        chooserIntent.setType("image/*");
        startActivityForResult(chooserIntent, RESULT_CODE);
    }

Intent實現的回撥函式

@Override
    protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
        if (requestCode == RESULT_CODE) {
            if (null == mUploadMessage){
                return;
            }
            Uri result = intent == null || resultCode != RESULT_OK ? null : intent.getData();
            //這裡呼叫該方法,將原生得到的資料返回給JS
            mUploadMessage.onReceiveValue(result);
            mUploadMessage = null;
        }
    }

ps:注意,這個lib將把WebViewJavascriptBridge 物件注入視窗物件,因此,在你的js中使用webviewJavascripBridge之前,你必須確認你的WebViewJavaScriptBridge存在,如果你的webViewJavasciptBridge不存在,你可以監聽webViewJavascriptBridgeReady事件

function connectWebViewJavascriptBridge(callback) {
            if (window.WebViewJavascriptBridge) {
                callback(WebViewJavascriptBridge)
            } else {
                document.addEventListener(
                    'WebViewJavascriptBridgeReady'
                    , function() {
                        callback(WebViewJavascriptBridge)
                    },
                    false
                );
            }
        }