天天看點

JS 調 Android 原理,JSBridge的實作原理

HybridAPP 通過JSBridge提供調用Native功能的接口,讓混合開發中的『前端部分』可以友善地使用位址位置、攝像頭甚至支付等 Native 功能。它的核心是 建構 Native 和非 Native 間消息通信的通道,而且是 雙向通信的通道。

JSBridge的實作原理

js調用Native

注入api/對象

原理:通過WebView提供的接口向js的context(window)注入一個對象或者方法,js調用時,直接執行對應的Native代碼邏輯

iOS

UIWebVIew(iOS2+)和WKWebView(iOS8+)的調用方式有所差別

//假設ios用戶端約定方法名為nativeBridge

//UIWebView

window.nativeBridge(message);

//WKWebView

window.webkit.messageHandlers.nativeBridge.postMessage(message);

複制代碼

Android

原理:通過WebView提供的addJavascriptInterface方法給浏覽器window注入一個命名空間,然後給Web增加一些可以操作Java的反射。

// addJavascriptInterface

mWebView.addJavascriptInterface(new Class(), 'android');

//@JavascriptInterface

public class Class(){

@JavascriptInterface

public void method(){

}

}

// js 代碼

window.android.method();

複制代碼

在 4.2 之前,Android 注入 JavaScript 對象的接口是 addJavascriptInterface,但是這個接口有漏洞,可以被不法分子利用,危害使用者的安全,是以在 4.2 中引入新的接口 @JavascriptInterface(上面代碼中使用的)來替代這個接口,解決安全問題。

攔截URL scheme

iOS

在UIWebView内發起的所有網絡請求,都可以通過delegate函數在Native層得到通知。這樣,我們就可以在UIWebView内發起一個自定義的網絡請求,通常是這樣的格式:jsbridge://methodName?param1=value1&param2=value2

于是Native 攔截的請求中,我們隻要發現是jsbridge://開頭的位址,就不進行内容的加載,轉而執行相應的調用邏輯。

缺點:

使用 iframe.src 發送 URL SCHEME 會有 url 長度的隐患。

建立請求,需要一定的耗時,比注入 API 的方式調用同樣的功能,耗時會較長。

即使URL scheme連結有以上缺點,但因為它 支援 iOS6,是以為了實作相容很多方案會使用這種方式

Android邏輯與iOS相似

改寫浏覽器原有對象

使用prompt,console.log,alert方式,在android webview這一層可以重寫這些方法。

一般常使用prompt,因為這個在js裡使用的不多,用來和native通訊副作用比較少。

prompt簡單舉例說明,Web頁面通過調用prompt()方法,安卓用戶端通過監聽onJsPrompt事件,攔截傳入的參數,如果參數符合一定協定規範,那麼就解析參數,扔給後續的Java去處理。這種協定規範,最好是跟iOS的協定規範一樣,這樣跨端調起協定是一緻的,但具體實作不一樣而已。比如:hybrid://action?arg1=1這樣的協定,而其他格式的prompt參數,是不會監聽的,即除了hybrid://action?arg1=1這樣的規範協定,prompt還是原來的prompt。

Native調用JS

Native調用js實際就是執行拼接js字元串,從外部調用對應方法,傳回js執行結果。是以js方法必須放在全局的Window上

iOS

是通過UIWebView元件的stringByEvaluatingJavaScriptFromString方法來實作的,該方法傳回js腳本的執行結果。

//UIWebView

result = [uiWebview stringByEvaluatingJavaScriptFromString:javaScriptString];

//WKWebView

[wkWebView evaluateJavaScript:javaScriptString completionHandler:completionHandler];

複制代碼

Android

在 Kitkat(4.4)之前是使用webview的loadUrl進行調用的:

webView.loadUrl("javascript:JSBridge.trigger('webviewReady')");

複制代碼

而 Kitkat 之後的版本,也可以用 evaluateJavascript 方法實作:

webView.evaluateJavascript(javaScriptString, new ValueCallback() {

@Override

publicvoidonReceiveValue(String value){

}

});

複制代碼

參考: