HybridAPP 經過JSBridge提供調用Native功能的接口,讓混合開發中的『前端部分』能夠方便地使用地址位置、攝像頭甚至支付等 Native 功能。它的核心是 構建 Native 和非 Native 間消息通訊的通道,並且是 雙向通訊的通道。javascript
原理:經過WebView提供的接口向js的context(window)注入一個對象或者方法,js調用時,直接執行對應的Native代碼邏輯前端
iOSjava
UIWebVIew(iOS2+)和WKWebView(iOS8+)的調用方式有所區別android
//假設ios客戶端約定方法名爲nativeBridge
//UIWebView
window.nativeBridge(message);
//WKWebView
window.webkit.messageHandlers.nativeBridge.postMessage(message);
複製代碼
Androidios
原理:經過WebView提供的addJavascriptInterface
方法給瀏覽器window
注入一個命名空間,而後給Web增長一些能夠操做Java的反射。web
// 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(上面代碼中使用的)來替代這個接口,解決安全問題。c#
iOSsegmentfault
在UIWebView內發起的全部網絡請求,均可以經過delegate函數在Native層獲得通知。這樣,咱們就能夠在UIWebView內發起一個自定義的網絡請求,一般是這樣的格式:jsbridge://methodName?param1=value1¶m2=value2api
因而Native 攔截的請求中,咱們只要發現是jsbridge://開頭的地址,就不進行內容的加載,轉而執行相應的調用邏輯。瀏覽器
缺點:
即便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實際就是執行拼接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<String>() {
@Override
publicvoidonReceiveValue(String value){
}
});
複製代碼
參考: