WebViewJsBridge-Android 做一個(gè)好用的橋接庫(kù)

移動(dòng)技術(shù)發(fā)展了七八年漱牵,開(kāi)發(fā)人員永遠(yuǎn)有個(gè)跨平臺(tái)的夢(mèng)戳杀。從最開(kāi)始的 Web App 被人詬病體驗(yàn)差,ReactNative卡乾,Weex 等技術(shù)又有很多難以平復(fù)的坑翼悴,包括現(xiàn)在的 Flutter 也有很多問(wèn)題待解決,跨平臺(tái)的夢(mèng)想很美好,現(xiàn)實(shí)卻總有這樣那樣的瑕疵鹦赎。移動(dòng)開(kāi)發(fā)發(fā)展到今天谍椅,我認(rèn)為最好的跨平臺(tái)技術(shù)還是 H5 + Native 的混合開(kāi)發(fā)模式。隨著前端技術(shù)的飛速發(fā)展古话,如今可以依靠各種技術(shù)和工具對(duì)前端進(jìn)行優(yōu)化雏吭,使其在移動(dòng)端的體驗(yàn)更接近原生水平。

我們?cè)谧龌旌祥_(kāi)發(fā)(Hybrid App)時(shí)陪踩,絕對(duì)繞不開(kāi) JavaScript 與 Native(iOS & Android)之間的交互問(wèn)題≌让牵現(xiàn)在主流的交互框架有 JsBridge,它可能是最早的 Android 與 JavaScript 橋接庫(kù)肩狂,該庫(kù)優(yōu)點(diǎn)是接口簡(jiǎn)單摘完,不用往 HTML 中引入額外的 js 文件,缺點(diǎn)是只支持 Android傻谁,同一個(gè)項(xiàng)目還要為 iOS 尋找一個(gè)對(duì)應(yīng)的橋接庫(kù)孝治,另一個(gè)問(wèn)題是對(duì)交互接口沒(méi)有管理,大多數(shù)情況下我們把接口都寫(xiě)到一個(gè) Activity 中的审磁,造成代碼堆積谈飒,接口不易維護(hù)。近幾年還有一個(gè)比較好的橋接庫(kù)是 DSBridge-Android态蒂,這個(gè)庫(kù)相比 JsBridge 的優(yōu)勢(shì)是支持 Android 與 iOS步绸,接口支持以類(lèi)的方式管理,但是使用時(shí)需要往 HTML 中引入一個(gè) js 文件吃媒,其實(shí)現(xiàn)方式是繼承了 WebView瓤介,所以使用時(shí)要使用其改造后的 DWebView,我本人不喜歡這種對(duì) WebView 的侵入方式赘那。

我在其兩個(gè)庫(kù)的基礎(chǔ)之上又造了一個(gè)輪子刑桑,這就是 WebViewJsBridge-Android,它首先支持 Android 與 iOS 兩個(gè)端募舟,接口與 JsBridge 相似祠斧,同樣支持以類(lèi)的方式管理交互接口,同樣需要引入一個(gè) js 文件(在 1.1.0 版本中可以不引用這個(gè) js 文件)拱礁,沒(méi)有使用繼承 WebView 這種侵入方式實(shí)現(xiàn)功能琢锋。

以下是 WebViewJsBridge-Android 的使用文檔供大家參考:

WebViewJsBridge-Android

WebViewJsBridge-Android 是 HTML5 和 WebView 之間用于通訊的工具庫(kù)。

WebViewJsBridge-iOS:https://github.com/al-liu/WebViewJsBridge-iOS

它的特點(diǎn)是跨平臺(tái)呢灶,支持 iOS吴超,Android,JavaScript鸯乃,接口統(tǒng)一鲸阻,簡(jiǎn)單易用。工具庫(kù)的實(shí)現(xiàn)對(duì) WebView 無(wú)侵入性。使用以類(lèi)的方式來(lái)管理通信的接口鸟悴,每個(gè)接口的實(shí)現(xiàn)類(lèi)對(duì)應(yīng)唯一的命名空間陈辱,如 ui.alert,ui 對(duì)應(yīng)一個(gè)實(shí)現(xiàn)類(lèi)的命名空間细诸,alert 是該實(shí)現(xiàn)類(lèi)的一個(gè)實(shí)現(xiàn)方法沛贪。在 1.1.0 版本中, H5 可以不引入 hcJsBridge.js 文件震贵。

下面這張圖幫助理解它們之間的關(guān)系:

WebViewJsBridge-namespace.png

系統(tǒng)版本要求

支持 API 19利赋,Android4.4及以上的系統(tǒng)版本。

安裝

Gradle

compile 'com.lhc:webviewjsbridge:1.1.0'

引入 WebViewJsBridge 的 js 文件

在 html 中 <script>引入 hcJsBridge.js</script>屏歹。

注意: 1.1.0 版本 H5 可以不引入 hcJsBridge.js 文件隐砸,但使用方法有少許差異之碗,后面有介紹蝙眶。

Example 的說(shuō)明

example 模塊中提供完整使用示例,包括基礎(chǔ)的調(diào)用演示和進(jìn)階用法褪那,如幽纷,調(diào)用相機(jī)拍攝一張圖片,使用 okhttp 發(fā)起一個(gè) GET 請(qǐng)求博敬。

使用方法

初始化原生的 WebViewJsBridge 環(huán)境

// WebView 要開(kāi)啟 JavaScriptEnabled
webSettings.setJavaScriptEnabled(true);
mJsBridge = WebViewJsBridge.newInstance(mMainWebView);

如果 H5 不引入 hcJsBridge.js友浸,則還需要在 onPageFinished 中調(diào)用 injectWebViewJavascript 方法

mMainWebView.setWebViewClient(new WebViewClient() {
    @Override
    public void onPageFinished(WebView view, String url) {
        super.onPageFinished(view, url);
        mJsBridge.injectWebViewJavascript();
    }
});

原生注冊(cè)接口實(shí)現(xiàn)類(lèi)供 HTML5 調(diào)用

mJsBridge.addJsBridgeApiObject(new UIApiImpl(), "ui");
mJsBridge.addJsBridgeApiObject(new RequestApiImpl(weakReference), "request");

UIApiImpl 的實(shí)現(xiàn)類(lèi):

public class UIApiImpl {
    private static final String TAG = "UIApiImpl";
    
    @JavascriptInterface
    public void alert(JSONObject data, ResponseHandler<String> responseHandler){
        responseHandler.complete("native api alert'callback.");
    }
    // 實(shí)現(xiàn)類(lèi)支持四種方法簽名:
    // 有參數(shù),有回調(diào)
    @JavascriptInterface
    public void test1(String data, ResponseHandler<String> responseHandler){
        responseHandler.complete("response data");
    }
    // 有參數(shù)偏窝,無(wú)回調(diào)
    @JavascriptInterface
    public void test2(JSONObject data){
        Log.d(TAG, String.format("Js native api:test2, data is:%s", data.toString()));
    }
    // 無(wú)參數(shù)收恢,無(wú)回調(diào)
    @JavascriptInterface
    public void test3(){
        Log.d(TAG, "Js native api:test3");
    }
    // 無(wú)參數(shù),有回調(diào)
    @JavascriptInterface
    public void test4(ResponseHandler<String> responseHandler){
        responseHandler.complete("response data");
    }
}

原生調(diào)用 HTML5 接口

mJsBridge.callHandler("test1", "test1 data", new ResponseHandler() {
    @Override
    public void complete(Object responseData) {
        Log.d(TAG, String.format("test1 callback data is:%s", responseData));
    }
});

初始化 HTML5 的 WebViewJsBridge 環(huán)境

如果 H5 引入 hcJsBridge.js祭往,則使用下面的方式引入伦意。

<!DOCTYPE html>
<html>
    <head>
        ...
        <script src="./hcJsBridge.js"> </script>
    </head>
    ...
</html>

如果 H5 不引入 hcJsBridge.js,則使用下面這個(gè)方法注冊(cè)接口硼补。

// 在這個(gè) window._hcJsBridgeInitFinished 全局函數(shù)中等待 bridge 初始化完成驮肉,然后注冊(cè)接口,初始調(diào)用已骇。
window._hcJsBridgeInitFinished = function(bridge) {
    bridge.registerHandler("test1", function(data, callback) {
        callback('callback native,handlename is test1');
    })
    
    bridge.callHandler('ui.test3');
}

HTML5 注冊(cè)接口供原生調(diào)用

hcJsBridge.registerHandler("testCallJs", function(data, callback) {
    log('Native call js ,handlename is testCallJs, data is:', data);
    callback('callback native, handlename is testCallJs');
})

HTML5 調(diào)用原生接口

var data = {foo: "bar"};
hcJsBridge.callHandler('ui.alert', data, function (responseData) {
    log('Js receives the response data returned by native, response data is', responseData);
})

開(kāi)啟 debug 日志

開(kāi)啟 debug 日志离钝,將打印一些調(diào)用信息,輔助排查問(wèn)題褪储。debug 日志默認(rèn)不開(kāi)啟卵渴。

mJsBridge.enableDebugLogging(true);

License

WebViewJsBridge-Android 使用 MIT license 發(fā)布,查看 LICENSE 詳情鲤竹。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末奖恰,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌瑟啃,老刑警劉巖论泛,帶你破解...
    沈念sama閱讀 218,941評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異蛹屿,居然都是意外死亡屁奏,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)错负,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)坟瓢,“玉大人,你說(shuō)我怎么就攤上這事犹撒≌哿” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,345評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵识颊,是天一觀的道長(zhǎng)诚镰。 經(jīng)常有香客問(wèn)我,道長(zhǎng)祥款,這世上最難降的妖魔是什么清笨? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,851評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮刃跛,結(jié)果婚禮上抠艾,老公的妹妹穿的比我還像新娘。我一直安慰自己桨昙,他們只是感情好检号,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,868評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著蛙酪,像睡著了一般齐苛。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上滤否,一...
    開(kāi)封第一講書(shū)人閱讀 51,688評(píng)論 1 305
  • 那天脸狸,我揣著相機(jī)與錄音,去河邊找鬼藐俺。 笑死炊甲,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的欲芹。 我是一名探鬼主播卿啡,決...
    沈念sama閱讀 40,414評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼菱父!你這毒婦竟也來(lái)了颈娜?” 一聲冷哼從身側(cè)響起剑逃,我...
    開(kāi)封第一講書(shū)人閱讀 39,319評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎官辽,沒(méi)想到半個(gè)月后蛹磺,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,775評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡同仆,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評(píng)論 3 336
  • 正文 我和宋清朗相戀三年萤捆,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片俗批。...
    茶點(diǎn)故事閱讀 40,096評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡俗或,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出岁忘,到底是詐尸還是另有隱情辛慰,我是刑警寧澤,帶...
    沈念sama閱讀 35,789評(píng)論 5 346
  • 正文 年R本政府宣布干像,位于F島的核電站帅腌,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏蝠筑。R本人自食惡果不足惜狞膘,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,437評(píng)論 3 331
  • 文/蒙蒙 一揩懒、第九天 我趴在偏房一處隱蔽的房頂上張望什乙。 院中可真熱鬧,春花似錦已球、人聲如沸臣镣。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,993評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)忆某。三九已至,卻和暖如春阔蛉,著一層夾襖步出監(jiān)牢的瞬間弃舒,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,107評(píng)論 1 271
  • 我被黑心中介騙來(lái)泰國(guó)打工状原, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留聋呢,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,308評(píng)論 3 372
  • 正文 我出身青樓颠区,卻偏偏與公主長(zhǎng)得像削锰,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子毕莱,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,037評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容