Cordova插件實現(xiàn)JavaScript與Java的通信的詳細過程
背景
Cordova平臺是開源的跨平臺開發(fā)框架,被廣泛應(yīng)用于移動應(yīng)用開發(fā)領(lǐng)域,可以開發(fā)跨安卓、iOS等系統(tǒng)的應(yīng)用。Cordova平臺是基于HTML/JavaScript語言,它是如何在不同平臺上能夠運行并實現(xiàn)相應(yīng)功能的呢?這里就用到了Cordova提供的豐富的插件,Cordova的大量插件結(jié)合自身的框架,為應(yīng)用開發(fā)者提供了跨平臺的能力,開發(fā)者不需要與操作系統(tǒng)層面的接口進行交互,可以關(guān)注于應(yīng)用功能本身。HMS Core為了方便Cordova開發(fā)者能夠更方便快速的接入HMS Core的能力,也針對各能力提供了Cordova的插件。
簡介
這里將結(jié)合最常用的華為推送服務(wù)Cordova插件,介紹HMS Core用到的JS-Java消息交互方式,講解在JS側(cè)如何調(diào)用Java側(cè)接口,最終實現(xiàn)HMS Core能力。當(dāng)然,在進行問題定位時也可以參考本文進行分析。
Cordova基本結(jié)構(gòu)
App啟動時,在MainActivity中調(diào)用loadUrl函數(shù),即觸發(fā)了CordovaWebView的初始化,進行Cordova的啟動。此時CordovaWebView會創(chuàng)建PluginManager對象,NativeToJsMessageQueue對象以及JavascriptInterface的ExposedJsApi對象。在后續(xù)的消息交互中,則主要通過ExposedJsApi和NativeToJsMessageQueue進行。
插件的加載分兩步。首先,在PluginManager對象創(chuàng)建時,讀取配置文件中的所有Plugin,并創(chuàng)建映射;而在第一次調(diào)用該插件時,進行實例化,并執(zhí)行相關(guān)功能。
消息返回模式包含同步和異步兩種模式,Cordova中通過在函數(shù)中配置async關(guān)鍵字進行區(qū)分。
對于同步模式,系統(tǒng)會從NativeToJsMessageQueue隊列頭獲取數(shù)據(jù),并返回。然后再根據(jù)callbackID查找到請求,返回給success函數(shù)。
對于異步模式,執(zhí)行后會啟動循環(huán)函數(shù)不停的獲取隊列中的數(shù)據(jù)。查找到對應(yīng)的請求時,返回給success函數(shù)。
在華為推送服務(wù)的插件中,采用的是同步的方式。
以推送為樣例說明插件調(diào)用方式
如果以上沒有看懂,沒有關(guān)系,只要了解下面的過程即可。
1. 插件安裝
執(zhí)行命令 cordova plugin add @hmscore/cordova-plugin-hms-push 安裝最新插件。執(zhí)行后會在plugins中增加插件信息。
其中在plugin.xml中記錄了所有用到的js類,android類等信息,在plugin初始化時會將其加載到系統(tǒng)中,如果某個函數(shù)或接口未在其中進行配置,會導(dǎo)致無法使用。
2. 消息映射
插件提供了4種消息映射方式:
(1) HmsMessaging消息調(diào)用
在HmsPush.js中通過runHmsMessaging接口將消息轉(zhuǎn)給Android平臺,通過異步調(diào)用方式,Android返回的結(jié)果將通過Promise返回。
消息將會轉(zhuǎn)到HmsPushMessaging類中,在HmsPushMessaging的execute函數(shù)中,根據(jù)各功能的不同,轉(zhuǎn)向不同的函數(shù)進行處理:
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)用中,通過設(shè)置結(jié)果的方式,將結(jié)果返回給JS層。內(nèi)容將被寫入nativeToJsMessageQueue隊列中。
callBack.sendPluginResult(new PluginResult(PluginResult.Status.OK,autoInit));
(2) HmsInstanceId消息調(diào)用
在HmsPush.js中通過runHmsInstance接口將消息轉(zhuǎn)給Android平臺,通過異步調(diào)用方式,平臺將結(jié)果通過Promise返回。
消息將會轉(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隊列中。
callBack.sendPluginResult(new PluginResult(PluginResult.Status.OK,autoInit));
過程與HmsPushMessaging非常相似。主要區(qū)別在于HmsPushInstanceId用于映射HmsInstanceId相關(guān)的接口,HmsPushMessaging用于映射HmsMessaging相關(guān)接口。
(3) localNotification消息調(diào)用
在HmsLocalNotification.js中通過run接口將消息傳遞給Android平臺,通過異步調(diào)用方式,平臺將結(jié)果通過Promise返回。
消息將會轉(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;
同樣會通過sendPluginResult接口返回處理結(jié)果。但是localNotification的消息涉及消息發(fā)送,會在發(fā)送完成后進行消息返回。
(4) Push事件回調(diào)
在Push消息中除了函數(shù)調(diào)用外,還有很多的事件監(jiān)聽,比如收到普通消息,收到透傳消息,收到Token等,因此在Push中還有對于各種事件的監(jiān)聽。
對于回調(diào)流程的介紹從Android側(cè)開始。
在Android側(cè),Push回調(diào)消息的函數(shù)定義在HmsPushMessageService.java中。
根據(jù)SDK的要求,復(fù)寫需要用到的回調(diào)函數(shù):onMessageReceived,onDeletedMessages,onNewToken等。
當(dāng)事件被觸發(fā)時,會向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)聽定義:
在HmsPushEvent.js中對每個事件都進行了定義及注冊
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ā)時主動調(diào)用,否則不會生效??梢詤⒖糄emo中的eventListeners.js。
如果發(fā)現(xiàn)已經(jīng)在Java側(cè)觸發(fā)回調(diào),但是沒有接收到,就需要檢查一下Cordova中是否定義有相關(guān)調(diào)用事件。
這樣,在Android側(cè)觸發(fā)事件時,JS側(cè)就可以收到并處理相關(guān)的消息了。如果需要增加新的事件,也可以參考該流程。
小結(jié)
通過以上的方式,Push插件實現(xiàn)了JS側(cè)-Java側(cè)的消息互通。在大部分的服務(wù)函數(shù)接口調(diào)用中都采用的類似形式。但是對于某些服務(wù),如廣告、地圖等需要顯示圖片或視頻的場景(如地圖,原生廣告等),會用到其他的方式,使用上也更復(fù)雜一些,這些會在其他的文檔中做詳細的介紹。
>>訪問HMS Core官網(wǎng),了解更多相關(guān)內(nèi)容
>>獲取HMS Core Cordova插件開發(fā)指導(dǎo)文檔
>>華為HMS Core官方論壇
>>華為HMS Core Cordova插件開源倉庫地址:GitHub
以上就是Cordova插件如何實現(xiàn)JavaScript與Java的通信的詳細內(nèi)容,更多關(guān)于Cordova插件JavaScript與Java通信的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
詳解基于深度學(xué)習(xí)的兩種信源信道聯(lián)合編碼
信源編碼是一個數(shù)據(jù)壓縮的過程,其目的是盡可能地將信源中的冗余度去掉;而信道編碼則是一個增加冗余的過程,通過適當(dāng)加入冗余度來達到抵抗信道噪聲,保護傳輸數(shù)據(jù)的目的。2021-05-05權(quán)限控制之粗粒度與細粒度概念及實現(xiàn)簡單介紹
這篇文章主要介紹了權(quán)限控制之粗粒度與細粒度概念及實現(xiàn)簡單介紹,具有一定參考價值,需要的朋友可以了解下。2017-10-10