介紹使用Android JSBridge原理與實現

來源:互聯網
上載者:User

標籤:

介紹使用Android JSBridge原理與實現

JSBridge

在Android中,JSBridge已經不是什麼新鮮的事物了,各家的實現方式也略有差異。大多數人都知道WebView存在一個漏洞,見WebView中介面隱患與手機掛馬利用,雖然該漏洞已經在Android 4.2上修複了,即使用@JavascriptInterface代替addJavascriptInterface,但是由於相容性和安全性問題,基本上我們不會再利用Android系統為我們提供的addJavascriptInterface方法或者@JavascriptInterface註解來實現,所以我們只能另闢蹊徑,去尋找既安全,又能實現相容Android各個版本的方案。


首先我們來瞭解一下為什麼要使用JSBridge,在開發中,為了追求開發的效率以及移植的便利性,一些展示性強的頁面我們會偏向於使用h5來完成,功能性強的頁面我們會偏向於使用native來完成,而一旦使用了h5,為了在h5中儘可能的得到native的體驗,我們native層需要暴露一些方法給js調用,比如,彈Toast提醒,彈Dialog,分享等等,有時候甚至把h5的網路請求放著native去完成,而JSBridge做得好的一個典型就是,給開發人員提供了JSSDK,該SDK中暴露了很多native層的方法,比如支付,定位等。


那麼,怎麼去實現一個相容Android各版本又具有一定安全性的JSBridge呢?我們知道,在WebView中,如果java要調用js的方法,是非常容易做到的,使用WebView.loadUrl(“javascript:function()”)即可,這樣,就做到了JSBridge的native層調用h5層的單向通訊,但是h5層如何調native層呢,我們需要尋找這麼一個通道,仔細回憶一下,WebView有一個方法,叫setWebChromeClient,可以設定WebChromeClient對象,而這個對象中有三個方法,分別是onJsAlert,onJsConfirm,onJsPrompt,當js調用window對象的對應的方法,即window.alert,window.confirm,window.prompt,WebChromeClient對象中的三個方法對應的就會被觸發,我們是不是可以利用這個機制,自己做一些處理呢?答案是肯定的


至於js這三個方法的區別,可以詳見w3c JavaScript 訊息框 (基礎教程qkxue.net)。一般來說,我們是不會使用onJsAlert的,為什麼呢?因為js中alert使用的頻率還是非常高的,一旦我們佔用了這個通道,alert的正常使用就會受到影響,而confirm和prompt的使用頻率相對alert來說,則更低一點。那麼到底是選擇confirm還是prompt呢,其實confirm的使用頻率也是不低的,比如你點一個連結下載一個檔案,這時候如果需要彈出一個提示進行確認,點擊確認就會下載,點取消便不會下載,類似這種情境還是很多的,因此不能佔用confirm。而prompt則不一樣,在Android中,幾乎不會使用到這個方法,就是用,也會進行自訂,所以我們完全可以使用這個方法。該方法就是彈出一個輸入框,然後讓你輸入,輸入完成後返回輸入框中的內容。因此,佔用prompt是再完美不過了。


到這一步,我們已經找到了JSBridge雙向通訊的一個通道了,接下來就是如何?的問題了。本文中實現的只是一個簡單的demo,如果要在生產環境下使用,還需要自己做一層封裝。

要進行正常的通訊,通訊協定的制定是必不可少的。我們回想一下熟悉的http請求url的組成部分(app開發ty300.com)。形如http://host:port/path?param=value,我們參考http,制定JSBridge的組成部分,我們的JSBridge需要傳遞給native什麼資訊,native層才能完成對應的功能,然後將結果返回呢?顯而易見我們native層要完成某個功能就需要調用某個類的某個方法,我們需要將這個類名和方法名傳遞過去,此外,還需要方法調用所需的參數,為了通訊方便,native方法所需的參數我們規定為json對象,我們在js中傳遞這個json對象過去,native層拿到這個對象再進行解析即可。為了區別於http協議,我們的jsbridge使用jsbridge協議,為了簡單起見,問號後面不適用索引值對,我們直接跟上我們的json字串,於是就有了形如下面的這個uri。

jsbridge://className:port/methodName?jsonObj

有人會問,這個port用來幹嘛,其實js層調用native層方法後,native需要將執行結果返回給js層,不過你會覺得通過WebChromeClient對象的onJsPrompt方法將傳回值返回給js不就好了嗎,其實不然,如果這麼做,那麼這個過程就是同步的,如果native執行非同步作業的話,傳回值怎麼返回呢?這時候port就發揮了它應有的作用,我們在js中調用native方法的時候,在js中註冊一個callback,然後將該callback在指定的位置上緩衝起來,然後native層執行完畢對應方法後通過WebView.loadUrl調用js中的方法,回調對應的callback。那麼js怎麼知道調用哪個callback呢?於是我們需要將callback的一個儲存位置傳遞過去,那麼就需要native層調用js中的方法的時候將儲存位置回傳給js,js再調用對應儲存位置上的callback,進行回調。於是,完整的協議定義如下:

jsbridge://className:callbackAddress/methodName?jsonObj

假設我們需要調用native層的Logger類的log方法,當然這個類以及方法肯定是遵循某種規範的,不是所有的java類都可以調用,不然就跟文章開頭的WebView漏洞一樣了,參數是msg,執行完成後js層要有一個回調,那麼地址就如下

jsbridge://Logger:callbackAddress/log?{"msg":"native log"}

至於這個callback對象的地址,可以儲存到js中的window對象中去。至於怎麼儲存,後文會慢慢倒來。

上面是js向native的通訊協定,那麼另一方面,native向js的通訊協定也需要制定,一個必不可少的元素就是傳回值,這個傳回值和js的參數做法一樣,通過json對象進行傳遞,該json對象中有狀態代碼code,提示資訊msg,以及返回結果result,如果code為非0,則執行過程中發生了錯誤,錯誤資訊在msg中,返回結果result為null,如果執行成功,返回的json對象在result中。下面是兩個例子,一個成功調用,一個調用失敗。

稿源:勤快學QKXue.NET

閱讀圖文完整版介紹使用Android JSBridge原理與實現

介紹使用Android JSBridge原理與實現

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.