android_jsbridge,讓你和前端愉快的交互

android_js

前言

做爲開發人員都知道,客戶端的版本更新對於用戶來講代價是很大的。爲了知足客戶端可以快速更新迭代的要求,許多app都內嵌入了H5,好比不少電商平臺,淘寶、京東、
聚划算等等。這類技術的關鍵就是在於Android客戶與Web前端之間的交互。不少大型項目的接口爲了防止Spammer的侵入,都是要求只能由客戶端發起請求的。因此本項目
就封裝了一個module,實現客戶端接收前端的調用,而後由客戶端發起Http請求的功能。
複製代碼
開始介紹項目以前,先來快速回顧一下Android客戶端與Web前端之間交互的幾種方式。
複製代碼

1. Android調用JS方法

1.1 經過WebView的loadUrl()

android客戶端代碼:javascript

private void initWebView() {
    WebSettings webSettings = webView.getSettings();
    webSettings.setJavaScriptEnabled(true); // 設置與Js交互的權限
    webSettings.setJavaScriptCanOpenWindowsAutomatically(true); // 設置容許JS彈窗

    webView.loadUrl("file:///android_asset/javascript.html");
    webView.setWebChromeClient(new WebChromeClient() {

        @Override
        public boolean onJsAlert(WebView view, String url, String message, final JsResult result) {
            AlertDialog.Builder b = new AlertDialog.Builder(SimpleWebViewActivity.this);
            b.setTitle("Alert");
            b.setMessage(message);
            b.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    result.confirm();
                }
            });
            b.setCancelable(false);
            b.create().show();
            return true;
        }
    });
}

private void setListener() {
    btnLoadUrl.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            webView.post(new Runnable() {
                @Override
                public void run() {
                    // 此處的callJS方法名與JS中的function方法名必需要一致
                    webView.loadUrl("javascript:callJS()");
                }
            });
        }
    });
}
複製代碼

javascript前端代碼:html

<!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8">
        <title>Carson_Ho</title>
        // JS代碼
        <script>
            // Android須要調用的方法
           function callJS() {
              alert("Android調用了JS的callJS方法");
           }

        </script>
    </head>
    </html>
複製代碼
運行結果如圖
複製代碼

    android客戶端代碼:

btnEvaluateJavascript.setOnClickListener(new View.OnClickListener() {

        @TargetApi(19)
        @Override
        public void onClick(final View v) {
            webView.evaluateJavascript("javascript:callJS()", new ValueCallback<String>() {
                @Override
                public void onReceiveValue(String value) {
                    //此處爲 js 返回的結果
                    Log.d(TAG, "value---" + value);
                }
            });
        }
    });
複製代碼
運行結果跟上圖是同樣的。
複製代碼
兩種交互方式的比較
複製代碼
調用方式 優勢 缺點 使用場景
使用loadUrl() 方便簡潔 效率低;獲取返回值麻煩 不須要使用返回值,對性能要求較低
使用evaluateJavascript() 效率高 向下兼容性差(僅Android 4.4以上可用) Android 4.4及以上

1.3 使用建議

// Android版本變量
final int version = Build.VERSION.SDK_INT;
// 由於該方法在 Android 4.4 版本纔可以使用,因此使用時需進行版本判斷
if (version < 18) {
    webView.loadUrl("javascript:callJS()");
} else {
    webView.evaluateJavascript("javascript:callJS()", new ValueCallback<String>() {
        @Override
        public void onReceiveValue(String value) {
            //此處爲 js 返回的結果
        }
    });
}
複製代碼

2. JS調用Android方法

2.1 經過WebView的addJavascriptInterface()進行對象映射

代碼再也不貼出,詳細代碼請參見:代碼地址    運行結果以下: 前端

2.2 經過 WebViewClient 的方法shouldOverrideUrlLoading()回調攔截 url

代碼再也不貼出,詳細代碼請參見:代碼地址    運行結果以下: java

2.3 經過 WebChromeClient 的onJsAlert()、onJsConfirm()、onJsPrompt()方法回調攔截JS對話框alert()、confirm()、prompt()消息

代碼再也不貼出,詳細代碼請參見:代碼地址    運行結果以下: android

2.3.1 onJsAlert()、onJsConfirm()、onJsPrompt()三者之間的比較
方法 做用 返回值
alert() 彈出警告框 沒有
confirm() 彈出確認框 兩個返回值(true或false)
prompt() 彈出輸入框 任意設置返回值
2.3.2 總結
經常使用的攔截是:攔截 JS的輸入框(即prompt()方法),由於只有prompt()能夠返回任意類型的值,操做最全面方便、更加靈活,
而alert()對話框沒有返回值,confirm()對話框只能返回兩種狀態(肯定 / 取消)兩個值。
複製代碼

2.4 三種Android Call Js 方式的對比以及使用場景

調用方式 優勢 缺點 使用場景
經過WebView的addJavascriptInterface()
進行對象映射
方便簡潔 Android 4.2如下存在漏洞問題 Android 4.2以上相對簡單的互調場景
經過 WebViewClient 的方法shouldOverrideUrlLoading()
回調攔截 url
不存在漏洞問題 有協議約束,客戶端向前端傳值繁瑣 不須要返回值的互調場景
經過 WebChromeClient 的onJsAlert()、onJsConfirm()、onJsPrompt()方法
回調攔截JS對話框alert()、confirm()、prompt()消息
不存在漏洞問題 有協議約束 能知足大多數狀況下的互調場景

附:WebView的addJavascriptInterface()方法在Android 4.2如下存在的漏洞git

以上都是對基礎知識的回顧,下面的纔是本項目的解釋說明。注意了,如下才是本項目的解釋說明!!

先來看一下項目運行的效果圖:
複製代碼

你們會說,這個不是跟攔截JS的prompt()方法同樣麼,沒錯,js和android之間的交互,也無非上面提到的幾種方法,這裏作的封裝採用的是:
js調android:經過WebView的addJavascriptInterface()進行對象映射
android回調js:android 4.4以上採用WebView的evaluateJavascript()方法,android 4.4如下采用loadUrl()方法
複製代碼
android端代碼:
複製代碼

JsBridgeWebView 這是一個繼承WebView的類,它裏面向JS注入了一個對象供JS調用,JS能夠經過這個對象調用Native的方法,調哪一個方法,傳哪些參數,徹底由JS決定,方法名必須兩端協議,Native經過反射找到對應的方法。傳遞過來的參數重包含了JS回調方法的方法名,客戶端執行完相應的操做以後再去執行JS的方法。github

js代碼:
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
        <title>Carson</title>
        <script>
            function callAndroid(){
                // 因爲對象映射,因此調用jsCallback對象等於調用Android映射的對象
                var json = "{\"name\": \"zlove\", \"_dscbstub\": \"callback\"}"
                _jsbridge.call("testAsync", json);
             }
             function callback(result) {
                alert("客戶端返回的結果是:" + result)
             }
        </script>
</head>
<body>
<!-- 點擊按鈕則調用callAndroid函數 -->
<button type="button" id="button1" style="font-size:30px" onclick="callAndroid()">Call Android</button>
</body>
</html>
複製代碼
var json = "{\"name\": \"zlove\", \"_dscbstub\": \"callback\"}" 
_jsbridge.call("testAsync", json);
_jsbridge表示客戶端注入的對象,testAsync是方法名,json是參數,而_dscbstub對應的callback是js的回調方法。
複製代碼

end

原本覺得要寫不少,事實上其實把基礎原理寫清楚了,也就這麼多😂😂😂。
I hope this will help you!
複製代碼

附:源碼地址web

相關文章
相關標籤/搜索