http://www.cnblogs.com/dailc/p/8097598.htmljavascript
Hybrid模式原生和H5交互原理html
前人栽樹,後臺乘涼,本文參考瞭如下來源java
閱讀本文前,建議先閱讀如下文章web
Hybrid APP的關鍵是原生頁面與H5頁面直接的交互,本文作簡單介紹api
在Hybrid APP中,原生與H5的交互方式在Android和iOS上的實現是有異同的,緣由是Android、iOS的通訊機制有所區別,下面介紹原生和H5相互調用的方法安全
4.4版本以前架構
// mWebView = new WebView(this); //即當前webview對象 mWebView.loadUrl("javascript: 方法名('參數,須要轉爲字符串')"); //ui線程中運行 runOnUiThread(new Runnable() { @Override public void run() { mWebView.loadUrl("javascript: 方法名('參數,須要轉爲字符串')"); Toast.makeText(Activity名.this, "調用方法...", Toast.LENGTH_SHORT).show(); } });
4.4之後(包括4.4)app
//異步執行JS代碼,並獲取返回值 mWebView.evaluateJavascript("javascript: 方法名('參數,須要轉爲字符串')", new ValueCallback() { @Override public void onReceiveValue(String value) { //這裏的value即爲對應JS方法的返回值 } });
如上所示,Native用H5頁面中的JS方法,有以下特色異步
WebSettings webSettings = mWebView.getSettings(); //Android容器容許JS腳本,必需要 webSettings.setJavaScriptEnabled(true); //Android容器設置僑連對象 mWebView.addJavascriptInterface(getJSBridge(), "JSBridge");
Android中JSBridge的代碼ide
//Android4.2版本以上,本地方法要加上註解@JavascriptInterface,不然會找不到方法。 private Object getJSBridge(){ Object insertObj = new Object(){ @JavascriptInterface public String foo(){ return "foo"; } @JavascriptInterface public String foo2(final String param){ return "foo2:" + param; } }; return insertObj; }
Html中JS調用原生的代碼
//調用方法一 window.JSBridge.foo(); //返回:'foo' //調用方法二 window.JSBridge.foo2('test');//返回:'foo2:test'
如上所示,Native中經過addJavascriptInterface添加暴露出來的JS橋對象,而後再該對象內部聲明對應的API方法,有以下特色:
因此,也就是爲何Android中也會使用JSBridge來進行交互,而不是addJavascriptInterface直接暴露api
//能夠取得JS函數執行的返回值 //方法必須是Html頁面綁定在最頂層的window上對象的 //如window.top.foo //Swift webview.stringByEvaluatingJavaScriptFromString("方法名(參數)") //OC [webView stringByEvaluatingJavaScriptFromString:@"方法名(參數);"];
如上所示,Native經過stringByEvaluatingJavaScriptFromString調用Html綁定在window上的函數,有以下特色
引入官方的庫文件
#import <JavaScriptCore/JavaScriptCore.h>
Native註冊api函數(OC)
//webview加載完畢後設置一些js接口 -(void)webViewDidFinishLoad:(UIWebView *)webView{ [self hideProgress]; [self setJSInterface]; } -(void)setJSInterface{ JSContext *context =[_wv valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"]; // 註冊名爲foo的api方法 context[@"foo"] = ^() { //獲取參數 NSArray *args = [JSContext currentArguments]; NSString *title = [NSString stringWithFormat:@"%@",[args objectAtIndex:0]]; //作一些本身的邏輯 //返回一個值 'foo:'+title return [NSString stringWithFormat:@"foo:%@", title]; }; }
Html中JS調用原生的代碼
//調用方法,用top是確保調用到最頂級,由於iframe要用top才能拿到頂級 window.top.foo('test'); //返回:'foo:test'
如上所示,Native中經過引入官方提供的JavaScriptCore庫(iOS7中出現的),而後能夠將api綁定到JSContext上(而後Html中JS默認經過window.top.***可調用)。有以下特色
實際上,Native與H5通訊,除了前面提到的用基本方法外,還有一種廣爲流行的方法:JSBridge
JSBridge是廣爲流行的Hybrid開發中JS和Native一種通訊方式,各大公司的應用中都有用到這種方法
簡單的說,JSBridge就是定義Native和JS的通訊,Native只經過一個固定的橋對象調用JS,JS也只經過固定的橋對象調用Native,基本原理是:
H5->經過某種方式觸發一個url->Native捕獲到url,進行分析->原生作處理->Native調用H5的JSBridge對象傳遞迴調。以下圖
上圖簡單的介紹了下JSBridge的核心原理,具體詳細實現請參考後面詳解。
在上文中咱們有提到Native和原生之間的基本通訊,既然Native和原生已經可以實現通訊了,那爲何還要這種經過url scheme的JSBridge方式呢,緣由大體以下
另外,請注意,能夠理解爲JSBridge是一種交互理念,而上述的url scheme則是其中的一種實現,因此也就是說,就算後面實現變爲了addJavascriptInterface,JavaScriptCore,也同樣是JSBridge交互
JSBridge交互的一個很大特色就是便於拓展,並且沒有重大的安全性問題,因此也就是爲何它廣爲流行
JSBridge的原理和實現請參考 JSBridge實現原理