一、非引入JsBridge或WebViewJavascriptBridge庫的方案
1、H5與iOS/Android的通信方式
H5 webview與iOS通信
① 原生iOS調用js的方法(前端工程師可簡單理解,掛載在windows對象下的js方法iOS原生都可以調用觸發)
原生iOS可以訪問webview全局對象(windows對象下個的屬性),所以當我們要讓iOS調用我們js的某些方法的可以在window下添加一個jsBridge對象,里面可以定義給iOS調用的一些js方法。
②Js調用原生iOS(OC或Swift)方法
反過來,JS調用原生iOS并沒有現成的API可以直接拿過來使用,而是間接的利用一些方法來實現---->利用ios的UIWebview組件的特性,在UIWebview內發起的所有的網絡請求,都可以通過delegate函數在native層得到通知。簡單點說就是我們H5頁面url路徑的跳轉請求,原生iOS這邊都可以抓到,利用此特點我們可以像在get請求URL后面帶參數一樣帶參數讓原生iOS去取到。(利用url的這個過程需要前端和原生這邊約定好這個url的格式,例如:jsbridge://methodName?param1=value1¶m2=value2,只要以jsbridge://開頭的地址就不要讓webview進行頁面的跳轉,轉而執行相應的邏輯,原生可以把要傳給vebview的某個數據掛在到window下的某個屬性上,js通過window.屬性名取到原生傳來的數據)
上面提到的url的跳轉讓原生去攔截的方案,js這邊實現方式有兩種:
①window.location.href
②利用頁面中嵌套的iframe的url(將iframe的長寬都設為很小或者0,取到數據后再移除這個iframe)
建議使用②iframe的方式,因為如果我們連續多次修改window.location.href的值,在Native層只能接收到最后一次請求,前面的請求都會被忽略掉。
H5 webview與Android通信
1、目前js有三種調用原生Android的方式:
① 和上面Js調用原生iOS(OC或Swift)方法一樣,通過schema方式,Native使用shouldOverrideUrlLoading方法對url協議進行解析。這種js的調用方式與ios的一樣,使用iframe來調用native代碼。(原理和使用方式與上面講的iOS攔截url的一樣,建議ios和android端都采用此方式,那么前端也將方便做兼容些)
② 往webview里面注入方法,前端角度理解就是Android創建了一個方法,添加到我們js的window對象里面了,直接調用就可以觸發原生的方法,如下代碼:
③ 使用prompt、console.log、alert等方式,這三個方法對js里是屬于原生的,例如當我們js代碼中使用alert(data)時,原生這邊可以抓到data數據,然后它們進行相應的操作,一般我們使用prompt,因為這個在js代碼里面使用的很少,用來和native通訊副作用較少。
2、原生Android調用javascript方法通過在android代碼里使用webview的loadUrl進行調用。
2、js調用Native方法的封裝,兼容安卓和ios,供參考
二、引入JsBridge(安卓)或WebViewJavascriptBridge(iOS)庫的方案
安卓端的JsBridge: ? ?https://github.com/lzyzsd/JsBridge
iOS端的WebViewJavascriptBridge: ?https://github.com/marcuswestin/WebViewJavascriptBridge
實際項目中有相當一部分的原生內嵌H5頁面混合開發的項目采用這個方案,使用上來說也很簡單,其實就是對上面第一部分講的幾種實現原生與H5頁面通信方式的一個封裝。開發中安卓和iOS要分別引入JsBridge或者WebViewJavascriptBridge,Native這邊代碼參照官上面的github地址的代碼去配置,下面我僅以前端的角度來講解如何用代碼去實現:
① ?首先安卓、iOS、web前端三方要在一起定義好需要使用的接口的方法名及傳遞的參數,三方統一,由于h5這邊是要實現一套代碼和Native兩方通信,所以如果可以的話由前端來定義各個方法及傳遞的方式,原則上來說,web前端這邊是作為需求方的,我們定義好方法iOS和安卓設置此方法讓我們調用。(當然我們也可以注冊方法,讓Native來調用我們的方法)
②iOS和安卓端的代碼不羅列,基本思路就是他們要用registerHandler注冊一個方法,js這邊通過callHandler來調用這個方法,同時js這邊也可以用registerHandler注冊一個方法,Native端通過callHandler來調用。下面的代碼以我用的react框架來寫。
特別說明一下:js中與Native通信的所有方法的注冊和調用都必須包裹在下圖的setupWebVie wJavascriptBridge函數里面。