天天看點

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

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

前言

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

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

* 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.alert,window.confirm,window.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 = ;
var b = ;
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互相調用的方式。