Предыстория

Cordova — это кроссплатформенная среда разработки с открытым исходным кодом, которая позволяет использовать HTML и JavaScript для разработки приложений на нескольких платформах, таких как Android и iOS. Как Cordova позволяет приложениям работать на разных платформах и реализовывать функции? Все дело в многочисленных плагинах в Cordova. Они позволяют сосредоточиться исключительно на функциях приложения, не взаимодействуя с API на уровне ОС.

Введение

Я буду использовать плагин Cordova в HUAWEI Push Kit в качестве примера, чтобы показать, как вызывать API Java в JavaScript через обмен сообщениями JavaScript-Java. Следующие принципы реализации помогут вам освоить решения по устранению неполадок. Их можно применить и к другим наборам средств разработки.

Базовая структура Cordova

При вызове параметра loadUrl в MainActivity будет инициализирован параметр CordovaWebView, после чего запустится Cordova. Затем CordovaWebView создаст параметры PluginManager, NativeToJsMessageQueue, а также ExposedJsApi для JavascriptInterface. Параметры ExposedJsApi и NativeToJsMessageQueue будут использоваться в последующем обмене данными.

Во время загрузки плагина создается объект PluginManager, считываются все плагины в файле конфигурации, а затем выполняется мапирование плагинов. При первом вызове плагина создается экземпляр класса и выполняются связанные функции.

Сообщение может быть возвращено из Java в JavaScript в синхронном или асинхронном режиме. В Cordova установите параметр async в методе, чтобы различать два режима.В синхронном режиме Cordova получает данные из заголовка очереди NativeToJsMessageQueue, находит запрос сообщения на основе callbackID и возвращает данные в метод success запроса.

В асинхронном режиме Cordova вызывает метод цикла для непрерывного получения данных из очереди NativeToJsMessageQueue, находит запрос сообщения и возвращает данные в метод success запроса.

В плагине Cordova для Push Kit используется режим синхронизации.

Вызов плагина

Теперь рассмотрим процесс вызова плагина подробнее.

1.Установите плагин.

Запустите команду cordova plugin add @hmscore/cordova-plugin-hms-push, чтобы установить последнюю версию плагина. После выполнения команды данные плагина будут добавлены в каталог plugins.

Файл plugin.xml записывает всю используемую информацию, такую ​​как классы JavaScript и Android. Во время инициализации плагина классы будут загружены в Cordova. Метод или API нельзя использовать, если они не настроены в файле.

2.Выполните мапирование сообщений.

Плагин предоставляет методы для выполнения мапирования следующих сообщений.

(1) HmsMessaging

В файле HmsPush.js вызовите API runHmsMessaging в асинхронном режиме, чтобы передать сообщение на платформу Android. Платформа Android возвратит результат через параметр Promise.

Сообщение будет передано в класс HmsPushMessaging. Метод execute в HmsPushMessaging может передать сообщение методу для обработки в зависимости от типа действия в сообщении.

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;

Метод обработки возвращает результат в JavaScript. Результат будет записан в очередь nativeToJsMessageQueue.

callBack.sendPluginResult(new PluginResult(PluginResult.Status.OK,autoInit));

(2) HmsInstanceId

В файле HmsPush.js вызовите API runHmsInstance в асинхронном режиме, чтобы передать сообщение на платформу Android. Платформа Android возвратит результат через параметр Promise.

Сообщение будет передано в класс HmsPushInstanceId. Метод execute в HmsPushInstanceId может передать сообщение методу для обработки в зависимости от типа действия в сообщении.

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;

Точно так же метод обработки возвращает результат в JavaScript. Результат будет записан в очередь nativeToJsMessageQueue.

            callBack.sendPluginResult(new 
PluginResult(PluginResult.Status.OK,autoInit));

Этот процесс аналогичен процессу для класса HmsPushMessaging. Основное отличие состоит в том, что HmsInstanceId используется для API, связанных с HmsPushInstanceId, а HmsMessaging — для API, связанных с HmsPushMessaging.

(3) localNotification

В файле HmsLocalNotification.js вызовите API run в асинхронном режиме, чтобы передать сообщение на платформу Android. Платформа Android возвратит результат через параметр Promise.

Сообщение будет передано в класс HmsLocalNotification. Метод execute в HmsLocalNotification может передать сообщение методу для обработки в зависимости от типа действия в сообщении.

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, чтобы вернуть результат. Однако для параметра localNotification результат будет возвращен после отправки уведомления.

Выполните обратный вызов события push-сообщения

Помимо вызова метода, отправка сообщений включает прослушивание многих событий, например получение обычных сообщений, сообщений с данными и токенов.

Процесс обратного вызова начинается с Android. В Android метод обратного вызова определяется в параметре HmsPushMessageService.java. В зависимости от требований SDK вы можете переопределить некоторые методы обратного вызова, такие как onMessageReceived, onDeletedMessages и onNewToken.

При запуске события уведомление о нем отправляется в JavaScript.

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) -> {

            });
        }
    });
}

Каждое событие определяется и регистрируется в файле 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;

Хочу обратить ваше внимание, что инициализацию события нужно выполнить во время разработки приложения. В противном случае произойдет сбой при прослушивании событий. Дополнительные сведения см. в файле eventListeners.js демонстрации.

Если обратный вызов был активирован в Java, но не получен в JavaScript, проверьте, выполнена ли инициализация события.

Таким образом, когда событие запустится в Android, JavaScript сможет получить и обработать сообщение. Аналогичным образом вы можете добавить событие.

Итог

Сегодня мы рассмотрели, как плагин реализует связь между JavaScript и Java. Подобным образом можно вызвать методы большинства наборов средств разработки.

Комментарии (2)


  1. DrRaznomazov
    08.03.2022 11:56

    Спасибо за статью. Ранее с подобной концепцией сталкивалась в рамках известного фреймворка vaadin. И уже тогда сложилось впечатление, что она (концепция) хорошая для решений малого бизнеса, когда тмеет смысл экономить на веб-разработчиках. А вот для крупных проектов, таких как банки, хорошо бы разнести фронт и бек разратотки по разным точкам. Хотелось бы узнать мнение авторов, на сколько данная концепция применима в энтерпрайсе? На сколько хорошо она ложится под ci/cd ?


  1. Aidar87
    08.03.2022 16:37

    Не лучше ли использовать PWA + bubblewrap/pwabuilder ?