Как устроен Push Kit от Huawei

    Привет, Хабр! В мае прошлого года, оставшись без сервисов и API гугла, мы основательно взялись за работу над своей платформой Huawei Mobile Services. Это наш давний проект, к которому мы вернулись после введения американских санкций. Проблема «отрезанных» сервисов постепенно сошла на нет. Мы добавили недостающие компоненты: почтовый клиент, свои карты и другие сервисы, и HMS Core — набор API, SDK и прочих сервисов для разработки, и улучшения приложений. В этот набор входит Push Kit — облачная служба для рассылки уведомлений — и не только. Под катом расскажем, как устроен этот инструмент, чем выделяется и как его можно использовать.

    Главная функция Push Kit (об остальных поговорим дальше) — доставлять на устройство пользователя уведомления от приложений. Этот процесс организован так:

    • сервер приложения подключается к API-интерфейсу Push Kit и загружает туда зашифрованные сообщения;

    • из облака Push Kit сообщения пересылаются на устройство с целевым приложением.

    Кроме того, у Push Kit есть множество интересных и полезных фич:

    • Таргетирование рассылки по темам сообщений и другим критериям, в том числе с помощью Huawei Analytics Kit;

    • Отправка пуш-сообщений на основе сценариев одному или нескольким пользователям одновременно, рассылка по расписанию;

    • Отправка пуш-сообщений через консоль в интерфейсе AppGallery Connect.

    • Доступ к серверу Push Kit через HTTPS;

    • Отправка пуш-сообщений пользователям, которые пользуются разными профилями на одном Android-устройстве;

    • Отправка пуш-сообщений на устройства Android/iOS и веб-приложения;

    • Автоматический выбор языка пуш-сообщения в зависимости от языка системы устройства получателя;

    • Кэширование и повторная отправка – в случае, если пуш-сообщение не доставлено из-за отсутствия сети.

    Что и как можно послать через Push Kit

    С помощью Push Kit можно не только доставлять уведомления, но и передавать данные напрямую в приложение. В этом случае на пользовательское устройство приходит «послание», которое активирует в программе-адресате определённое действие. Функция может оказаться полезной, например, для соцсетей, когда вы получаете запрос добавиться в друзья или входящие вызовы по VoIP. Кроме того, с её помощью можно загружать в сообщения в мессенджеры, чтобы они уже были внутри, когда вы запустите программу.

    Но всё-таки главной задачей является доставка пуш-уведомлений, внешний вид которых настраивается через интерфейс Push Kit. Это может быть обычный текст, текст с большой или маленькой картинкой, с иконкой приложения и т. д. Можно менять размеры элементов и их расположение, выбирать тип звукового сигнала, а также программировать сценарии — действия, которые выполняются, когда пользователь открывает уведомление.

    Если группа уведомлений от одного приложения в статус-баре свёрнута, по умолчанию в нём будут показаны первые два пуша — их количество можно расширить до восьми. Такая группа может содержать до 24 пуш-уведомлений в EMUI 10 и до 49 в EMUI 9. Если сообщений больше, будет виден счётчик оставшихся уведомлений и следующее появится только после удаления одного из отображаемых пушей.

    Имя пакета, отправляемого Push Kit, может содержать до 128 байт, а максимальный размер сообщения составляет 4 Кб.

    Если у целевого устройства нет проблем с сетью, доставка пушей должна происходить не дольше, чем за 1 секунду. Если же девайс получателя не в сети, Push Kit кеширует сообщение и отправляет его после того, как устройство переходит в онлайн.

    Особенности Push Kit

    Уведомления через Push Kit приходят быстро и снижают энергопотребление устройства. Операционки большинства мобильных девайсов автоматически закрывают приложения, которые долгое время не проявляют активности. Но чтобы программа могла показывать свои пуши, зачастую ей нужно работать — хотя бы в фоне. Так что системе приходится перезапускать нужный ей софт, чтобы вывести пуш на экран.

    Push Kit позволяет этого не делать: сообщения попадают в его центр уведомлений (NC), минуя целевые приложения. За это отвечает специальный компонент под названием Push Service. В итоге программа запускается только тогда, когда это предусмотрено сценарием, например после нажатия на уведомление.

    Отсюда и высокая скорость доставки: благодаря Push Service пользователь может прочитать сообщение практически сразу после того, как оно попадёт на телефон.

    Push Kit предоставляет канал системного уровня, способный одновременно отправлять десятки миллионов сообщений в секунду и десятки миллиардов в день. При этом 99 % пушей доставляются пользователям в течение 10 минут, даже если приложение не запущено. По сути, уведомления не доходят, только если устройство получателя выключено или находится вне сети.

    Push Service устанавливается на все мобильные устройства с EMUI, так что на них уведомления отображаются в унифицированном виде.

    Служба «Центр уведомлений» доступна на некоторых устройствах Huawei с EMUI 4 и на всех начиная с EMUI 5. А вот на гаджетах сторонних производителей эта функция недоступна, но если установить на них HMS Core, эти телефоны тоже научатся принимать уведомления, отправленные через Huawei Push Kit. Увы, из-за системных ограничений скорость доставки на телефоны других марок может снизиться.

    Push Kit поддерживает основные кроссплатформенные среды разработки мобильных приложений, включая React Native, Cordova, Xamarin и Flutter. Чтобы разрабатывать на одном языке приложение, которое будет работать и на iOS, и на Android, нужно только интегрировать соответствующий пакет подключаемого модуля SDK.

    После получения сообщений через Push Kit пользовательские устройства информируют об этом ваш сервер, помогая отслеживать ход рассылки в режиме реального времени. Благодаря этому можно быть в курсе статуса каждого уведомления и иметь возможность оперативно реагировать на неудачную доставку. Например, отправить SMS человеку, до которого не доходят пуши.

    Push Kit автоматически показывает пуши на языке, который установлен в устройстве пользователя. Охват Push Kit — более 200 стран и регионов, поэтому такая функция будет очень полезна.

    Под капотом Push Kit: немного практики

    Чтобы воспользоваться сервисом, надо зарегистрировать аккаунт разработчика на сайте Huawei Developers. Кроме этого понадобятся:

    • компьютер на Windows с установленным пакетом Java JDK 1.8, Android Studio и Android SDK;

    • смартфон Huawei с USB-кабелем и установленным HMS Core не ниже 4-й версии.

    На схеме показан процесс разработки приложения под Android. iOS и веб-приложения поддерживаются в бета-режиме.

    Первым делом:

    • создаём приложение в AppGallery Connect и проект в Android Studio;

    • генерируем криптографический ключ SHA-256;

    • сохраняем файл конфигурации приложения;

    • подключаем к приложению модуль AppGallery Connect;

    • добавляем репозиторий Maven в файл build.gradle.

    Подробнее об этих шагах можно почитать здесь, правда, на английском.

    Важный момент: чтобы использовать Push Kit для веб-приложений, нужно настроить его через приложение для Android. Кроме того, существуют Quick Apps — приложения, не требующие установки, которые можно использовать на мобильных телефонах более 12 крупных производителей в Китае. Все они доступны в AppGallery и поддерживают Push Kit.

    Чтобы использовать Push Kit, укажите место для хранения данных вашего проекта. Если его не задать, будут недоступны таргетирование по темам сообщений, рассылка через агент WebPush и работа с iOS.

    Если место хранения данных отличается от местоположения вашего сервера или региона пользователя, время доставки пушей увеличится.

    Чтобы уменьшить задержку, есть смысл хранить данные неподалёку от пользователей. Например, если вы в России разрабатываете приложение для жителей из Евросоюза, оптимальным местом для сервера будет Германия.

    Интеграция HMS Core SDK

    Добавим файл конфигурации вашего приложения в AppGallery Connect.

    1. В AppGallery Connect кликаем My project.

    2. Находим и выбираем приложение, в которое хотим интегрировать HMS Core SDK.

    3. Переходим в Project Setting → General information. В App information загружаем файл agconnect-services.json.

    4. Копируем файл agconnect-services.json в корневой каталог приложения нашего проекта Android Studio.

    Добавим связи сборки. Для этого открываем файл build.gradle в каталоге приложения.

    Прописываем в разделе dependencies:

    dependencies {
        implementation fileTree(dir: 'libs', include: ['*.jar'])
        implementation 'androidx.appcompat:appcompat:1.0.2'
        implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
        testImplementation 'junit:junit:4.12'
        androidTestImplementation 'androidx.test:runner:1.1.1'
        androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
    
        // Add the following line
        implementation 'com.huawei.hms:push:5.0.0.300'
    }

    5.0.0.300 заменим на последнюю версию HMS Core Push SDK.

    Нажимаем Sync Now, чтобы синхронизировать файл build.gradle.

    Если отображается synced successfully, всё прошло хорошо.

    Настройка файла Manifest

    Чтобы устройства могли получать токен push и сообщения, отправленные сервером Push Kit, нужно изменить файл AndroidManifest.xml. Определяем класс MyPushService, он наследуется от класса HmsMessageService.

    <service
        android:name=".MyPushService"
        android:exported="false">
        <intent-filter>
            <action android:name="com.huawei.push.action.MESSAGING_EVENT" />
        </intent-filter>
    </service>

    В этом примере кода нужно только изменить MyPushService в android: name = ". MyPushService" на имя класса, наследуемого от класса HmsMessageService. Всё остальное сохраняем.

    Настройка сценариев шифрования

    Открываем файл конфигурации обфускации proguard-rules.pro проекта Android Studio. Добавляем параметры, исключающие из этого процесса HMS Core SDK.

    -ignorewarnings
    -keepattributes *Annotation*
    -keepattributes Exceptions
    -keepattributes InnerClasses
    -keepattributes Signature
    -keepattributes SourceFile,LineNumberTable
    -keep class com.hianalytics.android.**{*;}
    -keep class com.huawei.updatesdk.**{*;}
    -keep class com.huawei.hms.**{*;}

    Если мы используем AndResGuard, его надо добавить в список разрешений в файле c конфигурацией обфускации.

    "R.string.agc*",
    "R.string.hms*",
    "R.string.connect_server_fail_prompt_toast",
    "R.string.getting_message_fail_prompt_toast",
    "R.string.no_available_network_prompt_toast",
    "R.string.third_app_*",
    "R.string.upsdk_*",
    "R.layout.hms*",
    "R.layout.upsdk_*",
    "R.drawable.upsdk*",
    "R.color.upsdk*",
    "R.dimen.upsdk*",
    "R.style.upsdk*"

    Разрабатываем демо

    Ниже показан общий код проекта и структура ресурсов.

    Открываем наш проект в Android Studio, создаём виджет и разворачиваем TextView в MainActivity, чтобы отобразить токен. Там же, в MainActivity, программируем метод обновления токена в TextView.

    public class MainActivity extends AppCompatActivity {
        private TextView tvToken;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            tvToken = findViewById(R.id.tv_log);
    
            MyReceiver receiver = new MyReceiver();
            IntentFilter filter=new IntentFilter();
            filter.addAction("com.huawei.codelabpush.ON_NEW_TOKEN");
            MainActivity.this.registerReceiver(receiver,filter);
        }
    
        public class MyReceiver extends BroadcastReceiver {
    
            @Override
            public void onReceive(Context context, Intent intent) {
                if ("com.huawei.codelabpush.ON_NEW_TOKEN".equals(intent.getAction())) {
                    String token = intent.getStringExtra("token");
                    tvToken.setText(token);
                }
            }
        }
    }

    Для подачи заявки на токен объявляем <meta-data> в файле AndroidManifest.xml.

    <application
        <meta-data
            android:name="push_kit_auto_init_enabled"
            android:value="true" />
    </application>

    Name и value в meta-data копируем без изменений. Push SDK будет подавать заявку на получение токена при запуске приложения.

    Токен получается методом onNewToken в thMyPushService*ce class.

    MyPushService.java

    public class MyPushService extends HmsMessageService {
        private static final String TAG = "PushDemoLog";
        @Override
        public void onNewToken(String token) {
            super.onNewToken(token);
            Log.i(TAG, "receive token:" + token);
            sendTokenToDisplay(token);
        }
    
        private void sendTokenToDisplay(String token) {
            Intent intent = new Intent("com.huawei.push.codelab.ON_NEW_TOKEN");
            intent.putExtra("token", token);
            sendBroadcast(intent);
        }
    }

    Класс MyPushService наследуется от HmsMessageService. Он, в свою очередь, переопределяет метод для подтверждения онлайн-статуса устройства — onNewToken.

    Сборка, загрузка и отладка приложения

    Подключаем телефон Huawei к компьютеру.

    Способ 1. Нажимаем Play (зелёный треугольник), чтобы начать компиляцию и сборку. Устанавливаем APK на телефон.

    Способ 2. Используем Android Studio, чтобы упаковать APK.

    Затем используем инструмент ADB, чтобы установить APK на телефон для отладки.

    adb install D:\WorkSpace\CodeLab\pushdemo1\app\release\app-release.apk

    После запуска демо убеждаемся, что телефон подключён к сети. Метод onNewToken вызывается для возврата токена AFcSAHhhnxdrMCYBxth2QOG9IgY2VydAM61DTThqNux3KBC_hgzQQT *******.

    Токен записывается в журнал демонстрации. Его можно просмотреть, найдя PushDemoLog.

    Отправка пуш-уведомлений

    В интерфейсе Push Kit в AppGallery Connect можно редактировать сообщения и отправлять их на устройства, подключённые к сети. Перед отправкой уведомлений находим приложение по названию. В этом примере имя APK — com.huawei.codelabpush. Подробнее можно прочитать здесь.

    Если всё прошло удачно, на экране телефона увидим уведомление.

    Коммерческие возможности Push Kit

    Почти все известные нам российские кейсы связаны с банковскими учреждениями.

    Первой отечественной и второй в мире компанией, интегрировавшей наш Push Kit, стала mfms°: их решения по доставке пуш-уведомлений используют ВТБ, Альфа-Банк, Сбер и другие финансовые учреждения России. 

    Например, в ВТБ пушами клиентам сообщают о денежных операциях в реальном времени. Такие уведомления стоят сильно дешевле SMS, а затраты на внедрение минимальны: с SDK, которое предоставляет mfms°, не надо интегрировать APNs, FCM и Huawei Push Kit «с нуля».

    Пуши используются не только для рассылки. На основе Push Kit в mfms° разработали фичу, которая позволяет клиентам банков получать уведомления с подтверждением денежных операций. Такие сообщения рассылаются через SDK и заменяют SMS с кодами для оплаты. Более того, mfms° научились превращать эти пуши в красивые уведомления на русском языке с брендированным названием, логотипом и категорией магазина, в котором пользователь совершил оплату.

    Какие ещё сферы применения можно найти для пуш-уведомлений и как извлечь из Push Kit больше пользы — вопросы не такие уж и сложные, но для нас чрезвычайно интересные. Давайте их обсудим в комментариях: ждём ваши идеи, варианты использования платформы или, возможно, предсказания о будущем пуш-уведомлений.

    Huawei
    Компания

    Комментарии 12

      0
      -keep class com.hianalytics.android.**{*;}
      -keep class com.huawei.updatesdk.**{*;}
      -keep class com.huawei.hms.**{*;}

      Почему именно такие правила? Вам лень пройтись по всей библиотеке и выписать всю рефлексию? А еще R8 уже поддерживает упаковку правил прямо в jar, а не только в aar.

        +1
        github.com/appleboy/gorush уже запилили поддержку.
          0
          Все больше разработчиков интегрирует Push Kit в свои решения и это нормальная ситуация. Процент HMS смартфонов на рынке растёт, да и интеграция не занимает большого количества времени.
          0

          Все конечно красиво описано, но зачем было делать обновление токена походами по сети раз в полчаса, когда можно было сделать как в FCM, где используются клиентские сертификаты?
          И когда, наконец, починят резолв AAAA для oauth-login.cloud.huawei.com из России (dig oauth-login.cloud.huawei.com AAAA работает секунды 4 с разных провайдеров, а dig @1.1.1.1 oauth-login.cloud.huawei.com AAAA — 50мс), хотя A-записи нормально резолвятся.

            +1
            1. В статье action-ы передачи токена в UI не совпадают:
              com.huawei.codelabpush.ON_NEW_TOKEN
              com.huawei.push.codelab.ON_NEW_TOKEN


            2. Есть намного более простой способ получения токена:
              https://developer.huawei.com/consumer/en/doc/development/HMS-Plugin-Guides-V1/applypushtoken-0000001050136500-V1


            –2
            1. Сделайте это приложение удаляемое. Нам юзерам, оно точно ненужно, только батерею высасывает за сутки до 25%.
            2. Зачем вы нам с этим приложением наставили еще пачку ненужных приложений? Я.гомосятины, зеркало, и т.п. Почему Вы так не уважаете своих пользователей, думаете что они тупые и не знают, какие нужны им программы какие нет. Вы себя ведете очень стремно.
              0
              Не совсем понимаю, что вы имеете ввиду.
              0
              Неплохо бы еще доделать возможность использовать «large notification icons», как в гугловском Firebase API. Чтобы не только из внешнего URL подтягивать иконки, как сейчас, но из локальных ресурсов (из res/drawable).

              Заказчику уж очень хочется, ему понравилось, что для аппаратов других производителей в пуше показываются красивые иконки :)

              Кстати, еще один российский «кейс» — в одном из крупных ритейлеров пуши используются в мобильном приложении для сотрудников, им рассылаются уведомления о поступивших заказах, предстоящих отгрузках и т.п. Приложение сделано на Ionic Framework, в качестве runtime задействован Capacitor, к нему я сделал плагин-переходник к Huawei Push Kit. (Все думаю, надо бы этот плагин «причесать» и открыть исходники на гитхабе :))
                0

                Здравствуйте!
                Мы сейчас адаптируем свою библиотеку для сервиса авторизации и нотификации для работы с HMS.
                В связи с этим у нас возникла потребность в аналогичном функционале:
                https://firebase.google.com/docs/cloud-messaging/concept-options#receiving-messages-from-multiple-senders


                Не могли бы подсказать, есть ли аналогичное решение в HMS ?


                Кратко говоря суть задачи в следующем:
                Мы из Firebase из своего аккаунта можем отправлять пуши клиентам встроившим библиотеку и им для этого не приходится сообщать нам app id/ app secret.


                А если HMS не поддерживает такой способ отправки пушей то для корректной работы библиотеки нам придется просить клиентов предоставлять нам appId/app secret от их боевых приложений и хранить их у себя и отправлять пуши уже от имени этих приложений. Что уже не очень приятно как клиентам так и нам

                  0

                  Самой полезной возможностью gcm/firebase cloude message была возможность как раз таки пробудить приложение и выполнить в нем некоторую операцию даже если оно выключено — пример — охранное приложение по пушу с тревожной кнопки будило приложение, то запускало геолокацию и отдавало координаты пользователя. И это не единственный сценарий в котором фича "запустить приложение с пуша" была жизненно необходима. Я так понимаю тут её решили не реализовывать судя по коду и тексту статьи?

                    0

                    я тут обнаружил что в методе: getToken можно передать любую чушь и все равно получишь токен:


                    У меня пуштокен возвращается даже при:
                    val token = HmsInstanceId.getInstance(context).getToken("any value instead of appId :) ", "HCM")


                    в декомпилированных исходниках библиотеки можно обнаружить:
                    if (TextUtils.isEmpty(var0)) {
                    var3.setAppId(Util.getAppId(var2));
                    }
                    где var0 — appId
                    больше нигде ни для чего передаваемый appId не используется, так что главное что бы он не был пустым


                    единственный способ задать appId сейчас это файл agconnect-services.json
                    Поэтому пока что этот способ отправки пушей недоступен:
                    https://firebase.google.com/docs/cloud-messaging/concept-options#receiving-messages-from-multiple-senders

                    Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                    Самое читаемое