Android中webview與native之間的交互方式(jsbridge)

Android中webview與native之間的交互方式(jsbridge)

前言

​ 隨着H5的廣泛使用,Android開發過程中免不了會使用網頁來做展示,那麼,web與native之間的通信就顯得尤其重要了,其實際上是JavaScript與java之間的通信;如圖所示,我們開發過程中需要在native中調用JavaScript,或者是在JavaScript中調用native。

這裏寫圖片描述
* JavaScript調用java

JavaScript調用java的方式可以分爲兩類,一是通過捕獲url scheme的方式,二是利用原生接口實現調用。

1. 捕獲url scheme的方式

​ 核心思想是:web端與native首先協商好通信中使用的url的格式,緊接着web端通過一定的方式將url發送出去,最後native層捕獲url,並進行分析後再去調用原生方法。這種方法也是目前被廣泛使用的方式。

a) 首先第一步是約定好url的格式,例如這裏約定爲:


JSBridge://bridge:129129723/showToast?{"msg":"Hello JSBridge"}

其中showToast爲需要調用的native層方法,{“msg”:”Hello JSBridge”}爲向native傳遞的json數據。

b) 約定好傳遞格式後,web端需要觸發native層去捕獲url。

​ Android中爲我們提供了兩個類WebViewClient和WebChromeClient,這兩個類分別爲我們提供了一些方法可以使用。當有任何url在webview中使用時都會被WebViewClient的shouldOverrideUrlLoading函數攔截,因此我們可以利用這個特性,在JavaScript中構建一個1像素的iframe來觸發這個函數。web端代碼如下:


var url = 'JSBridge://bridge:129129723/showToast?{"msg":"Hello JSBridge"}';
var iframe = document.createElement('iframe');
iframe.style.width = '1px';
iframe.style.height = '1px';
iframe.style.display = 'none';
iframe.src = url;
document.body.appendChild(iframe);

Android端代碼:


webView = (WebView) findViewById(R.id.webView);
webView.setVerticalScrollbarOverlay(true);
//設置WebView支持JavaScript
webView.getSettings().setJavaScriptEnabled(true);
String url = "file:///android_asset/test.html"; //加載本地html
webView.loadUrl(url);
webView.setWebViewClient(new JsbridgeWebViewClient());

其中JsbridgeWebViewClient繼承WebViewClient,並重寫shouldOverrideUrlLoading方法,並在裏面實現調用原生方法的邏輯。

​ 其次,WebChromeClient提供了三個原生的方法,當在JavaScript中使用window.alertwindow.confirmwindow.prompt三個方法時會相應的觸發WebChromeClient對象的onJsPrompt、onJsAlert、onJsConfirm方法,所以我們也可以在前端通過這三種方式觸發native捕獲url。web端代碼如下:


var url = 'JSBridge://bridge:129129723/showToast?{"msg":"Hello JSBridge"}';
window.prompt(uri, "");

Android端代碼只要將上面的JsbridgeWebViewClient繼承WebChromeClient ,並重寫onJsPrompt、onJsAlert、onJsConfirm方法即可,這裏就不再重複。

c) native層捕獲到url後,如何調用?

​ 通過解析url,可以得到需要調用的native方法名以及json數據;這裏舉例是調用native層的showToast方法,我採用反射的方式來進行調用,核心代碼:

“`
public static void showToast(WebView webView, JSONObject param) {
String message = param.optString(“msg”);
Toast.makeText(webView.getContext(), message, Toast.LENGTH_SHORT).show();
}

public static String callJava(WebView webView, String uriString, Object owner) {
String methodName = “”;
String className = “”;
String param = “{}”;
String port = “”;
if (!TextUtils.isEmpty(uriString) && uriString.startsWith(“jsbridge”)) {
Uri uri = Uri.parse(uriString);//解析url
className = uri.getHost();
param = uri.getQuery();
port = uri.getPort() + “”;
String path = uri.getPath();
if (!TextUtils.isEmpty(path)) {
methodName = path.replace(“/”, “”);
}
}
Class classType = owner.getClass();
Method showToastMethod = null;
try {
showToastMethod = classType.getMethod(methodName,new Class[]{WebView.class,JSONObject.class});
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
try {
showToastMethod.invoke(owner, webView, new JSONObject(param));//反射調用showToast方法
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
return null;
}
“`

​ 以上是通過捕獲url scheme實現JavaScript調用java的方式。

**2. 使用原生方法 **addJavascriptInterface

​ Android爲我們提供了addJavascriptInterface方法,JavaScript可以直接調用java方法,但該方法在Android 4.2以下是存在安全隱患的,可參考,官方在Android4.2進行了修復,在使用addJavascriptInterface方法時,必須在提供給JavaScript調用的方法前添加@JavascriptInterface。例如在Android端將showInfoFromJs和getInfoFromJs提供給js調用:

private class JsInterface {
    private Context mContext;
    public JsInterface(Context context) {
        this.mContext = context;
    }
    //在js中調用window.test.showInfoFromJs(name),便會觸發此方法。
    @JavascriptInterface
    public void showInfoFromJs(String name) {
        Toast.makeText(mContext, name, Toast.LENGTH_SHORT).show();
    }
    @JavascriptInterface
    public  void getInfoFromJs(int a, int b){
        int c = a+b;
        Toast.makeText(mContext, ""+c, Toast.LENGTH_SHORT).show();
    }
}
//設置WebView支持JavaScript
webView.getSettings().setJavaScriptEnabled(true);
String url = "file:///android_asset/test.html";
webView.loadUrl(url);
//在js中調用本地java方法
webView.addJavascriptInterface(new JsInterface(this), "test");

在js中通過以下進行調用:

var name = document.getElementById("name_input").value;
var a = 1;
var b = 2;
window.test.showInfoFromJs(name);
window.test.getInfoFromJs(a,b);
  • java調用JavaScript

    ​ java調用javascript的方法比較簡單,因爲android爲我們提供了相應的方法, 4.4之前通過loadUrl的方式,而在4.4之後提供了evaluateJavascrip異步調用的方式。這裏就只舉例loadurl的方法。

    String msg = ((EditText) findViewById(R.id.input_et)).getText().toString();
    //調用js中的函數:showInfoFromJava(msg)
    webView.loadUrl("javascript:showInfoFromJava('" + msg + "')");

    以上就是js與java互相調用的方式。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章