Cordova插件實(shí)現(xiàn)JavaScript與Java的通信的詳細(xì)過(guò)程
背景
Cordova平臺(tái)是開源的跨平臺(tái)開發(fā)框架,被廣泛應(yīng)用于移動(dòng)應(yīng)用開發(fā)領(lǐng)域,可以開發(fā)跨安卓、iOS等系統(tǒng)的應(yīng)用。Cordova平臺(tái)是基于HTML/JavaScript語(yǔ)言,它是如何在不同平臺(tái)上能夠運(yùn)行并實(shí)現(xiàn)相應(yīng)功能的呢?這里就用到了Cordova提供的豐富的插件,Cordova的大量插件結(jié)合自身的框架,為應(yīng)用開發(fā)者提供了跨平臺(tái)的能力,開發(fā)者不需要與操作系統(tǒng)層面的接口進(jìn)行交互,可以關(guān)注于應(yīng)用功能本身。HMS Core為了方便Cordova開發(fā)者能夠更方便快速的接入HMS Core的能力,也針對(duì)各能力提供了Cordova的插件。
簡(jiǎn)介
這里將結(jié)合最常用的華為推送服務(wù)Cordova插件,介紹HMS Core用到的JS-Java消息交互方式,講解在JS側(cè)如何調(diào)用Java側(cè)接口,最終實(shí)現(xiàn)HMS Core能力。當(dāng)然,在進(jìn)行問(wèn)題定位時(shí)也可以參考本文進(jìn)行分析。
Cordova基本結(jié)構(gòu)
App啟動(dòng)時(shí),在MainActivity中調(diào)用loadUrl函數(shù),即觸發(fā)了CordovaWebView的初始化,進(jìn)行Cordova的啟動(dòng)。此時(shí)CordovaWebView會(huì)創(chuàng)建PluginManager對(duì)象,NativeToJsMessageQueue對(duì)象以及JavascriptInterface的ExposedJsApi對(duì)象。在后續(xù)的消息交互中,則主要通過(guò)ExposedJsApi和NativeToJsMessageQueue進(jìn)行。
插件的加載分兩步。首先,在PluginManager對(duì)象創(chuàng)建時(shí),讀取配置文件中的所有Plugin,并創(chuàng)建映射;而在第一次調(diào)用該插件時(shí),進(jìn)行實(shí)例化,并執(zhí)行相關(guān)功能。
消息返回模式包含同步和異步兩種模式,Cordova中通過(guò)在函數(shù)中配置async關(guān)鍵字進(jìn)行區(qū)分。
對(duì)于同步模式,系統(tǒng)會(huì)從NativeToJsMessageQueue隊(duì)列頭獲取數(shù)據(jù),并返回。然后再根據(jù)callbackID查找到請(qǐng)求,返回給success函數(shù)。
對(duì)于異步模式,執(zhí)行后會(huì)啟動(dòng)循環(huán)函數(shù)不停的獲取隊(duì)列中的數(shù)據(jù)。查找到對(duì)應(yīng)的請(qǐng)求時(shí),返回給success函數(shù)。
在華為推送服務(wù)的插件中,采用的是同步的方式。
以推送為樣例說(shuō)明插件調(diào)用方式
如果以上沒(méi)有看懂,沒(méi)有關(guān)系,只要了解下面的過(guò)程即可。
1. 插件安裝
執(zhí)行命令 cordova plugin add @hmscore/cordova-plugin-hms-push 安裝最新插件。執(zhí)行后會(huì)在plugins中增加插件信息。

其中在plugin.xml中記錄了所有用到的js類,android類等信息,在plugin初始化時(shí)會(huì)將其加載到系統(tǒng)中,如果某個(gè)函數(shù)或接口未在其中進(jìn)行配置,會(huì)導(dǎo)致無(wú)法使用。
2. 消息映射
插件提供了4種消息映射方式:
(1) HmsMessaging消息調(diào)用
在HmsPush.js中通過(guò)runHmsMessaging接口將消息轉(zhuǎn)給Android平臺(tái),通過(guò)異步調(diào)用方式,Android返回的結(jié)果將通過(guò)Promise返回。
消息將會(huì)轉(zhuǎn)到HmsPushMessaging類中,在HmsPushMessaging的execute函數(shù)中,根據(jù)各功能的不同,轉(zhuǎn)向不同的函數(shù)進(jìn)行處理:
public void execute(String action, final JSONArray args, final CallbackContext callbackContext)
throws JSONException {
hmsLogger.startMethodExecutionTimer(action);
switch (action) {
case "isAutoInitEnabled":
isAutoInitEnabled(callbackContext);
break;
case "setAutoInitEnabled":
setAutoInitEnabled(args.getBoolean(1), callbackContext);
break;
case "turnOffPush":
turnOffPush(callbackContext);
break;
case "turnOnPush":
turnOnPush(callbackContext);
break;
case "subscribe":
subscribe(args.getString(1), callbackContext);
break;
在各函數(shù)調(diào)用中,通過(guò)設(shè)置結(jié)果的方式,將結(jié)果返回給JS層。內(nèi)容將被寫入nativeToJsMessageQueue隊(duì)列中。
callBack.sendPluginResult(new PluginResult(PluginResult.Status.OK,autoInit));
(2) HmsInstanceId消息調(diào)用
在HmsPush.js中通過(guò)runHmsInstance接口將消息轉(zhuǎn)給Android平臺(tái),通過(guò)異步調(diào)用方式,平臺(tái)將結(jié)果通過(guò)Promise返回。
消息將會(huì)轉(zhuǎn)到HmsPushInstanceId類中,在HmsPushInstanceId的execute函數(shù)中,根據(jù)各功能不同,轉(zhuǎn)向不同的函數(shù)處理。
public void execute(String action, final JSONArray args, final CallbackContext callbackContext) throws JSONException {
if (!action.equals("init"))
hmsLogger.startMethodExecutionTimer(action);
switch (action) {
case "init":
Log.i("HMSPush", "HMSPush initialized ");
break;
case "enableLogger":
enableLogger(callbackContext);
break;
case "disableLogger":
disableLogger(callbackContext);
break;
case "getToken":
getToken(args.length() > 1 ? args.getString(1) : Core.HCM, callbackContext);
break;
case "getAAID":
getAAID(callbackContext);
break;
case "getCreationTime":
getCreationTime(callbackContext);
break;
最后同樣使用設(shè)置結(jié)果的方式,將結(jié)果返回給JS層。內(nèi)容將被寫入nativeToJsMessageQueue隊(duì)列中。
callBack.sendPluginResult(new PluginResult(PluginResult.Status.OK,autoInit));
過(guò)程與HmsPushMessaging非常相似。主要區(qū)別在于HmsPushInstanceId用于映射HmsInstanceId相關(guān)的接口,HmsPushMessaging用于映射HmsMessaging相關(guān)接口。
(3) localNotification消息調(diào)用
在HmsLocalNotification.js中通過(guò)run接口將消息傳遞給Android平臺(tái),通過(guò)異步調(diào)用方式,平臺(tái)將結(jié)果通過(guò)Promise返回。
消息將會(huì)轉(zhuǎn)到HmsLocalNotification類中,在HmsLocalNotification的execute函數(shù)中,根據(jù)各功能不同,轉(zhuǎn)向不同的函數(shù)處理。
public void execute(String action, final JSONArray args, final CallbackContext callbackContext) throws JSONException {
switch (action) {
case "localNotification":
localNotification(args, callbackContext);
break;
case "localNotificationSchedule":
localNotificationSchedule(args.getJSONObject(1), callbackContext);
break;
case "cancelAllNotifications":
cancelAllNotifications(callbackContext);
break;
case "cancelNotifications":
cancelNotifications(callbackContext);
break;
case "cancelScheduledNotifications":
cancelScheduledNotifications(callbackContext);
break;
case "cancelNotificationsWithId":
cancelNotificationsWithId(args.getJSONArray(1), callbackContext);
break;
同樣會(huì)通過(guò)sendPluginResult接口返回處理結(jié)果。但是localNotification的消息涉及消息發(fā)送,會(huì)在發(fā)送完成后進(jìn)行消息返回。
(4) Push事件回調(diào)
在Push消息中除了函數(shù)調(diào)用外,還有很多的事件監(jiān)聽(tīng),比如收到普通消息,收到透?jìng)飨?,收到Token等,因此在Push中還有對(duì)于各種事件的監(jiān)聽(tīng)。
對(duì)于回調(diào)流程的介紹從Android側(cè)開始。
在Android側(cè),Push回調(diào)消息的函數(shù)定義在HmsPushMessageService.java中。
根據(jù)SDK的要求,復(fù)寫需要用到的回調(diào)函數(shù):onMessageReceived,onDeletedMessages,onNewToken等。

當(dāng)事件被觸發(fā)時(shí),會(huì)向JS層發(fā)送事件通知:
public static void runJS(final CordovaPlugin plugin, final String jsCode) {
if (plugin == null)
return;
Log.d(TAG, "runJS()");
plugin.cordova.getActivity().runOnUiThread(() -> {
CordovaWebViewEngine engine = plugin.webView.getEngine();
if (engine == null) {
plugin.webView.loadUrl("javascript:" + jsCode);
} else {
engine.evaluateJavascript(jsCode, (result) -> {
});
}
});
}
JS側(cè)的監(jiān)聽(tīng)定義:
在HmsPushEvent.js中對(duì)每個(gè)事件都進(jìn)行了定義及注冊(cè)
exports.REMOTE_DATA_MESSAGE_RECEIVED = "REMOTE_DATA_MESSAGE_RECEIVED"; exports.TOKEN_RECEIVED_EVENT = "TOKEN_RECEIVED_EVENT"; exports.ON_TOKEN_ERROR_EVENT = "ON_TOKEN_ERROR_EVENT"; exports.NOTIFICATION_OPENED_EVENT = "NOTIFICATION_OPENED_EVENT"; exports.LOCAL_NOTIFICATION_ACTION_EVENT = "LOCAL_NOTIFICATION_ACTION_EVENT"; exports.ON_PUSH_MESSAGE_SENT = "ON_PUSH_MESSAGE_SENT"; exports.ON_PUSH_MESSAGE_SENT_ERROR = "ON_PUSH_MESSAGE_SENT_ERROR"; exports.ON_PUSH_MESSAGE_SENT_DELIVERED = "ON_PUSH_MESSAGE_SENT_DELIVERED";
function onPushMessageSentDelivered(result) {
window.registerHMSEvent(exports.ON_PUSH_MESSAGE_SENT_DELIVERED, result);
}
exports.onPushMessageSentDelivered = onPushMessageSentDelivered;
需要注意的是,這里的定義需要在應(yīng)用開發(fā)時(shí)主動(dòng)調(diào)用,否則不會(huì)生效??梢詤⒖糄emo中的eventListeners.js。
如果發(fā)現(xiàn)已經(jīng)在Java側(cè)觸發(fā)回調(diào),但是沒(méi)有接收到,就需要檢查一下Cordova中是否定義有相關(guān)調(diào)用事件。
這樣,在Android側(cè)觸發(fā)事件時(shí),JS側(cè)就可以收到并處理相關(guān)的消息了。如果需要增加新的事件,也可以參考該流程。
小結(jié)
通過(guò)以上的方式,Push插件實(shí)現(xiàn)了JS側(cè)-Java側(cè)的消息互通。在大部分的服務(wù)函數(shù)接口調(diào)用中都采用的類似形式。但是對(duì)于某些服務(wù),如廣告、地圖等需要顯示圖片或視頻的場(chǎng)景(如地圖,原生廣告等),會(huì)用到其他的方式,使用上也更復(fù)雜一些,這些會(huì)在其他的文檔中做詳細(xì)的介紹。
>>訪問(wèn)HMS Core官網(wǎng),了解更多相關(guān)內(nèi)容
>>獲取HMS Core Cordova插件開發(fā)指導(dǎo)文檔
>>華為HMS Core官方論壇
>>華為HMS Core Cordova插件開源倉(cāng)庫(kù)地址:GitHub
以上就是Cordova插件如何實(shí)現(xiàn)JavaScript與Java的通信的詳細(xì)內(nèi)容,更多關(guān)于Cordova插件JavaScript與Java通信的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
ffmpeg播放器實(shí)現(xiàn)詳解之視頻顯示(推薦)
FFmpeg是一套可以用來(lái)記錄、轉(zhuǎn)換數(shù)字音頻、視頻,并能將其轉(zhuǎn)化為流的開源計(jì)算機(jī)程序。這篇文章主要介紹了ffmpeg播放器實(shí)現(xiàn)詳解視頻顯示,需要的朋友可以參考下2020-07-07
YOLO v4常見(jiàn)的非線性激活函數(shù)詳解
這篇文章主要介紹了YOLO v4常見(jiàn)的非線性激活函數(shù),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-05-05
一個(gè)能生成精美代碼圖片的工具Carbon!讓看代碼成為一種享受
當(dāng)我們想展示自己寫的代碼給別人看的時(shí)候,希望讓代碼保持原有的格式,并且要美觀一點(diǎn),有一個(gè)強(qiáng)大的在線工具可以幫助我們實(shí)現(xiàn),而且支持多種主題,他就是Carbon,需要的朋友可以參考下2021-05-05
Unity3D中shader 輪廓描邊效果實(shí)現(xiàn)代碼
這篇文章主要介紹了Unity3D中shader 輪廓描邊效果的相關(guān)資料,需要的朋友可以參考下2017-03-03
300行代碼讓外婆實(shí)現(xiàn)語(yǔ)音搜索購(gòu)物功能
這篇文章主要介紹了300行代碼讓外婆實(shí)現(xiàn)語(yǔ)音搜索購(gòu)物功能,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-03-03

