前人栽樹(shù),后臺(tái)乘涼,本文參考了以下來(lái)源
閱讀本文前,建議先閱讀以下文章
Hybrid APP的關(guān)鍵是原生頁(yè)面與H5頁(yè)面直接的交互,本文做簡(jiǎn)單介紹
在Hybrid APP中,原生與H5的交互方式在Android和iOS上的實(shí)現(xiàn)是有異同的,原因是Android、iOS的通信機(jī)制有所區(qū)別,下面介紹原生和H5相互調(diào)用的方法
4.4版本之前
// mWebView = new WebView(this); //即當(dāng)前webview對(duì)象 mWebView.loadUrl("javascript: 方法名('參數(shù),需要轉(zhuǎn)為字符串')"); //ui線(xiàn)程中運(yùn)行 runOnUiThread(new Runnable() { @Override public void run() { mWebView.loadUrl("javascript: 方法名('參數(shù),需要轉(zhuǎn)為字符串')"); Toast.makeText(Activity名.this, "調(diào)用方法...", Toast.LENGTH_SHORT).show(); } });
4.4以后(包括4.4)
//異步執(zhí)行JS代碼,并獲取返回值 mWebView.evaluateJavascript("javascript: 方法名('參數(shù),需要轉(zhuǎn)為字符串')", new ValueCallback() { @Override public void onReceiveValue(String value) { //這里的value即為對(duì)應(yīng)JS方法的返回值 }});
如上所示,Native用H5頁(yè)面中的JS方法,有如下特點(diǎn)
WebSettings webSettings = mWebView.getSettings(); //Android容器允許JS腳本,必須要webSettings.setJavaScriptEnabled(true);//Android容器設(shè)置僑連對(duì)象mWebView.addJavascriptInterface(getJSBridge(), "JSBridge");
Android中JSBridge的代碼
//Android4.2版本以上,本地方法要加上注解@JavascriptInterface,否則會(huì)找不到方法。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調(diào)用原生的代碼
//調(diào)用方法一window.JSBridge.foo(); //返回:'foo'//調(diào)用方法二window.JSBridge.foo2('test');//返回:'foo2:test'
如上所示,Native中通過(guò)addJavascriptInterface添加暴露出來(lái)的JS橋?qū)ο?然后再該對(duì)象內(nèi)部聲明對(duì)應(yīng)的API方法,有如下特點(diǎn):
所以,也就是為什么Android中也會(huì)使用JSBridge來(lái)進(jìn)行交互,而不是addJavascriptInterface直接暴露api
//可以取得JS函數(shù)執(zhí)行的返回值//方法必須是Html頁(yè)面綁定在最頂層的window上對(duì)象的//如window.top.foo//Swiftwebview.stringByEvaluatingJavaScriptFromString("方法名(參數(shù))")//OC[webView stringByEvaluatingJavaScriptFromString:@"方法名(參數(shù));"];
如上所示,Native通過(guò)stringByEvaluatingJavaScriptFromString調(diào)用Html綁定在window上的函數(shù),有如下特點(diǎn)
引入官方的庫(kù)文件
#import <JavaScriptCore/JavaScriptCore.h>
Native注冊(cè)api函數(shù)(OC)
//webview加載完畢后設(shè)置一些js接口-(void)webViewDidFinishLoad:(UIWebView *)webView{ [self hideProgress]; [self setJSInterface];}-(void)setJSInterface{ JSContext *context =[_wv valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"]; // 注冊(cè)名為foo的api方法 context[@"foo"] = ^() { //獲取參數(shù) NSArray *args = [JSContext currentArguments]; NSString *title = [NSString stringWithFormat:@"%@",[args objectAtIndex:0]]; //做一些自己的邏輯 //返回一個(gè)值 'foo:'+title return [NSString stringWithFormat:@"foo:%@", title]; }; }
Html中JS調(diào)用原生的代碼
//調(diào)用方法,用top是確保調(diào)用到最頂級(jí),因?yàn)閕frame要用top才能拿到頂級(jí)window.top.foo('test'); //返回:'foo:test'
如上所示,Native中通過(guò)引入官方提供的JavaScriptCore庫(kù)(iOS7中出現(xiàn)的),然后可以將api綁定到JSContext上(然后Html中JS默認(rèn)通過(guò)window.top.***可調(diào)用)。有如下特點(diǎn)
實(shí)際上,Native與H5通信,除了前面提到的用基本方法外,還有一種廣為流行的方法:JSBridge
JSBridge是廣為流行的Hybrid開(kāi)發(fā)中JS和Native一種通信方式,各大公司的應(yīng)用中都有用到這種方法
簡(jiǎn)單的說(shuō),JSBridge就是定義Native和JS的通信,Native只通過(guò)一個(gè)固定的橋?qū)ο笳{(diào)用JS,JS也只通過(guò)固定的橋?qū)ο笳{(diào)用Native,基本原理是:
H5->通過(guò)某種方式觸發(fā)一個(gè)url->Native捕獲到url,進(jìn)行分析->原生做處理->Native調(diào)用H5的JSBridge對(duì)象傳遞回調(diào)。如下圖
上圖簡(jiǎn)單的介紹了下JSBridge的核心原理,具體詳細(xì)實(shí)現(xiàn)請(qǐng)參考后面詳解。
在上文中我們有提到Native和原生之間的基本通信,既然Native和原生已經(jīng)能夠?qū)崿F(xiàn)通信了,那為什么還要這種通過(guò)url scheme的JSBridge方式呢,原因大致如下
另外,請(qǐng)注意,可以理解為JSBridge是一種交互理念,而上述的url scheme則是其中的一種實(shí)現(xiàn),所以也就是說(shuō),就算后面實(shí)現(xiàn)變?yōu)榱薬ddJavascriptInterface,JavaScriptCore,也一樣是JSBridge交互
JSBridge交互的一個(gè)很大特點(diǎn)就是便于拓展,而且沒(méi)有重大的安全性問(wèn)題,所以也就是為什么它廣為流行
JSBridge的原理和實(shí)現(xiàn)請(qǐng)參考 JSBridge實(shí)現(xiàn)原理
聯(lián)系客服