Русский
Русский
English
Статистика
Реклама

Hms

Обзор HMS Core 5.0 ещё больше возможностей для ML на мобильных устройствах и новые инструменты для аудио и видео

14.09.2020 18:23:30 | Автор: admin


Привет, Хабр! Вместе с Harmony OS мы представили пятую версию HMS Core набора инструментов, с помощью которых можно разрабатывать приложения для экосистемы Huawei. Мы добавили новые возможности для работы с контентом, сделали акцент на безопасности данных, взаимодействии между устройствами и расширили возможности для AI-инструментов обо всём этом мы детально поговорили на нашей конференции HDC.Together, а в этой статье дадим обзор новых возможностей HMS.

Инструменты для работы с ML и AI


Основные сервисы для работы с AI входят в ML Kit и позволяют работать с текстом, голосом, картинками, AR/VR-технологиями. В HMS Core 5.0 мы увеличили количество поддерживаемых языков до 50 и можем выполнять перевод между 20 языками, при этом на вход принимаются как текстовые записи, так и голосовые. Также ML Kit может быть использован для отсеивания спама и всяких неприличных картинок.

С ML Kit можно конвертировать голосовые записи в текстовый формат и обратно, и мы расширили этот функционал с помощью Video Course Creator, который автоматически создаёт образовательные курсы: он берёт на вход образовательную программу, комментарии учителя и предустановленные аудио- и видеопараметры во время трансляции учитель может обращаться к нужным материалам и все записанные материалы компонуются в единый курс.



Особый акцент мы сделали на распознавание лица, жестов и поз. Благодаря этому с помощью ML Kit можно проводить аутентификацию по лицу система подключается через API и может быть использована для быстрого доступа к приложениям без каких-либо дополнительных действий.

Работать с инструментами AI и ML можно на разных уровнях:
  • Платформа для работы с технологиями искусственного интеллекта на мобильных устройствах HiAI позволяет обучать нейросети, создавать модели и конвертировать их в бинарный файл, который уже можно загрузить на NPU-чип.
  • Платформа Ability Gallery предоставляет разработчикам готовые сценарии использования AI и позволяет работать с большими данными в своих приложениях.

AR/VR


Наш AR-движок анализирует информацию об освещении, плоскости, форме объектов, типе поверхности, умеет искать заданные объекты в пространстве. Отдельно система может строить 3D-схему с помощью опорных точек и отслеживать человеческие движения, жесты и мимику. Например, для определения положения руки выделяется 21 точка, а для положения тела 23 точки. Сейчас система может распознавать 6 поз и анализировать сразу 2 человек.


С пятой версии HMS Core CameraKit обеспечивает различные режимы съёмки: широкую диафрагму, портретный режим, HDR, размытие фона, суперночной режим и иже с ними. Также появилась возможность использовать AI в фото- и видеосъемке для предварительного выбора фильтров и цветокоррекции.

Совместная работа устройств


В новой версии HMS Core появилось несколько новых движков для совместной работы разных устройств. Мы упростили взаимодействия между устройствами и умными вещами с помощью DeviceVirtualization-движка. Он преобразует периферийные устройства в виртуальные объекты и позволяет телефону работать с ними так же, как с обычными функциями.

В этом же направлении мы разработали Cast Engine, который позволяет телефону работать в мультиэкранном режиме и передавать изображение на TV с высоким разрешением. Также планируем добавить возможность работать с Cast Engine через другие приложения.

Ещё один новый движок OneHop Kit работает с NFC и позволяет безопасно передавать данные между устройствами в одно касание. С его помощью можно синхронизировать устройства Huawei между собой, передавать файлы и открывать приложения на других устройствах с теми же настройками, что и на основном. Пока он работает только между телефонами и планшетами Huawei, поэтому для связи с другими устройствами мы предоставляем Share-движок, который обеспечивает скорость до 80 Мб/c по Bluetooth.

Видео и аудио



В новой версии мы разработали несколько новых SDK-инструментов для работы с аудио и видео. Audio Kit и Video Kit поддерживают основные форматы файлов и кодеки и могут легко встраиваться в приложение и выполнять чтение, сохранение и удаление списков, последовательностей воспроизведения, регулировать скорость воспроизведения. Всё аудио и видео защищается алгоритмами шифрования.

В Audio Kit теперь есть аудиодвижок для записи звука в высоким качестве с функциями оптимизации задержки и других инструментов. Видеодвижок, в свою очередь, поддерживает основные протоколы HTTP, HTTPS, HLS, DASH. Также он позволяет организовывать стриминг со сторонних сервисов с помощью Video Kit WisePlayer SDK.

На основе нашего сервиса Huawei Meetime появился Caas Kit для видеозвонков, который обеспечивает воспроизведение и передачу HD-изображения даже при нестабильном соединении. Также движок позволяет расшаривать экран, рисовать дудлы и с помощью технологий виртуализации передавать изображения на любые другие устройства, что можно использовать для бизнес-конференций.

Картинки и 3D-рендеринг


Для обработки изображений появился Image Kit он предлагает более 20 фильтров и визуальных эффектов, включая анимацию с рендерингом. В него входят 2 SDK: Image Vision SDK для работы с цветовыми фильтрами и Image Render SDK для использования эффектов анимации.

Scene Kit предназначен для работы с 3D-объектами: он использует метод физически корректного рендеринга (PBR) и позволяет приложениям подключаться через API и получать 3D-модели сложных объектов. Движок предлагает три сценария работы: SceneView для общих сцен (не-AR), ARView для общих сцен AR и FaceView для работы с лицами в сценах AR.

Аналитика и безопасность


В Сore 5.0 Huawei мы запустили систему тегов Dynamic Tag Manager (DTM) для отслеживания маркетинговой активности пользователей: она интегрируется как с самими сервисами Huawei, так и со сторонними платформами для отправки и обработки данных. С помощью DTM можно динамически обновлять теги в пользовательском веб-интерфейсе, отслеживать определённые события и отправлять данные на сторонние аналитические платформы. В наших системах главный акцент сделан на безопасность, поэтому движок DTM также используется как antifraud-система для отслеживания подозрительной активности.

Одной из фишек новой версии HMS стала аутентификация по лицу с помощью LocalAuthentication Engine. Он работает с инфракрасной камерой, которая строит модель по опорным точкам и производит аутентификацию с помощью ML Kit.

Наконец, мы уделили внимание и защите контента: для аудиофайлов используется шифрование кеша, для видео антилитическая система и аутентификация при воспроизведении, а для работы с камерой сквозное шифрование. Все данные HMS хранит в доверенной среде TEE, в рамках которой и выполняется шифрование.



Где узнать подробности?


Все записи конференции HDC.Together доступны по ссылке. Здесь можно послушать доклады о новинках платформы, основных сценариях работы с инструментами HMS и задать технические вопросы на Huawei Developer Forum или Stackoverflow c тегом huawei-mobile-services.
Подробнее..

Таргетирование уведомлений, управление ценами в разных регионах и другие возможности HMS для интернет-платежей

08.10.2020 18:22:32 | Автор: admin


В Китае мобильным интернетом пользуется почти 900 млн человек, и 768 млн из них совершают покупки через системы онлайн-платежей. За этими огромными цифрами не только высокая нагрузка на платёжные сети и серверы, но и потребность мобильных разработчиков в удобных инструментах для работы с транзакциями. Чтобы отвечать этим запросам, на платформе Huawei Mobile Services постоянно развиваются инструменты для работы с платежами: служба для пуш-уведомлений, сервис для внутренних покупок в приложении и возможность оплачивать баллами от Huawei обо всём этом мы расскажем под катом.

In-Apps purchase


In-Apps purchase платёжный сервис, который позволяет пользователям совершать покупки внутри приложений. Например, с помощью IAP можно организовать внутриигровые платежи: игроки будут приобретать всевозможные виртуальные продукты, в том числе подписки, не выходя из игры.

Ценами и языками в In-Apps purchase управляет встроенная система Product management system (PMS): достаточно выпустить один пакет приложения, чтобы продвигать его во всех поддерживаемых регионах. Для каждого местоположения по умолчанию устанавливается одна валюта и один язык.



Чтобы защитить сообщения пользователей от перехвата или подделки, для шифрования данных используется протокол TLS, а для подписей алгоритм RSA. Перед сохранением в фоновом режиме данные зашифровываются и анонимизируются. Развертывание кластера и конструкция резервирования адаптированы для фоновых серверов, а круглосуточный мониторинг системы в режиме реального времени облегчает обнаружение неисправностей.

IAP поддерживает различные способы оплаты в 178 странах. Пользователи могут платить с помощью банковских карт, Alipay, WeChat, прямого биллинга оператора связи (DCB) и баллов Huawei Points. Huawei предоставляет ссылку на стоимость продукта в приложении для каждого местоположения на основе установленной разработчиком конвертированной цены (включая налоги) и обменного курса. Вы можете изменить цену.

Пользователи могут привязать свои карты и номера телефонов к своим идентификаторам Huawei и совершать платежи, вводя платёжные пароли, которые они установили ранее. Это гораздо удобнее, чем традиционные способы оплаты.

Push Kit


Push Kit облачная служба для рассылки пуш-уведомлений. Сервис, о котором мы недавно рассказывали подробно, поддерживает уйму полезных функций: таргетированные рассылки, отправка пушей на основе сценариев и по расписанию, автоматический выбор языка в зависимости от языка системы устройства получателя.



Отправка пуш-сообщений идёт через интерфейс AppGallery Connect. Другой вариант подключиться к серверу Push Kit через HTTPS. Сервис доставляет уведомления не только на устройства Android/iOS и в веб-приложения. И не только уведомления: с помощью Push Kit можно передавать данные напрямую в приложение. Сервис поддерживает основные кроссплатформенные среды мобильной разработки: React Native, Cordova, Xamarin, Flutter и др.

Через интерфейс Push Kit можно настраивать не только внешний вид уведомлений, но и сценарии, которые выполняются, когда пользователь открывает пуш. Банки уже давно пользуются пуш-уведомлениями для информирования клиентов о транзакциях, подтверждения совершения операций и т. п. это дешевле и проще, чем СМС.

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

Wallet Kit


Wallet Kit виртуальный кошелёк на платформе HMS, предназначенный для хранения и использования дисконтных и подарочных карт, карт клиента, купонов, билетов, ключей и т. д. Технология облегчает взаимодействие между приложениями и пользователями с помощью уведомлений на основе местоположения, обновлений статуса в реальном времени и возможностей NFC.

С помощью Wallet Kit пользователь может сохранять посадочные талоны на авиарейсы, смарт-билеты на мероприятия и электронные пропуска, подключиться к интеллектуальному замку дома или номера в отеле, а затем пользоваться телефоном в качестве ключа в режиме NFC. Точно так же можно использовать Wallet Kit вместо ключа от автомобиля. Причём такими виртуальными ключами легко делиться, например, с членами семьи.

Добавить новые карты или пропуска в кошелёк Huawei можно через веб-страницу, электронную почту, СМС-сообщение, магазин карт кошелька Huawei или приложение. Есть несколько методов доступа и аутентификации: с помощью отпечатка пальца, двойного нажатия кнопки питания, значка главного экрана или значка приложения. Поддерживаются функции AI Selected на основе протокола и местоположения.

Huawei Points


Huawei Points это баллы Huawei, которые можно использовать для покупок виртуальных товаров и оплаты дополнительных услуг в приложениях HMS, включая AppGallery, Huawei GameCentre, Themes, Video, Music, Mobile Cloud и т. д.

Huawei Points начисляются за определённые действия. Чтобы начать их зарабатывать, понадобится телефон Huawei. В нём заходим в Настройки, далее Учётная запись Huawei, где надо получить доступ с идентификатором Huawei. В разделе платежей и покупок появится доступ к Huawei Points и все необходимые для их получения опции.

Там, где указано количество баллов, находим раздел под названием Получать Huawei Points, в котором предложены варианты получения вознаграждения. Так, бывает возможность заработать баллы только за загрузку приложений. В других вариантах необходимо вкладывать деньги, например совершать покупки в приложениях, за что будут начисляться премиальные. Баллы необходимо запросить в течение 15 дней после зачисления на счёт, в противном случае вознаграждение будет аннулировано.

Huawei Points нельзя обменять на наличные или использовать для покупки телефонов, планшетов, гарнитур и других физических товаров. Но покупка облачного хранилища, подписка на тарифный план Huawei Video или приобретение платных приложений это уже кое-что. Если между Huawei и разработчиком приложения будет заключено соответствующее соглашение, то баллы можно менять на внутриигровую валюту золотые монеты, бриллианты и пр. Чтобы оплатить любую из этих услуг, выполняем обычный процесс покупки, только выбираем не карту, а Huawei Points.

Проверка приложений


Безопасность платежей в AppGallery обеспечивает кошёлек Huawei Wallet, который прошёл сертификацию PCI-DSS. Но перед попаданием в AppGallery каждое приложение проходит серию проверок на наличие троянов, червей и вирусов и прочих вредоносных файлов при помощи платформы обнаружения угроз SecDroid из антивирусного облака Huawei. Кроме того, мы используем антивирусные ядра от Avast и других известных поставщиков.

Перед релизом приложения в AppGallery в обязательном порядке проводится проверка личности разработчика или компании. Применительно к России и другим странам, кроме КНР, это означает, что частное лицо предоставляет банковскую карту и документ, удостоверяющий личность, например паспорт. Компаниям необходимо предоставить бизнес-лицензию или персональный номер DUNS.

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

EMUI имеет встроенную песочницу, позволяющую приложениям работать в изолированной программной среде: система выделяет персональный каталог, к которому другие приложения не могут получить доступ. EMUI также предоставляет ASLR и DEP, что лишает злоумышленников возможности пользоваться уязвимостями памяти.

Как эти сервисы применяют в России


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

Выходим на рынок Huawei, или Как мы адаптировали приложение для работы с HMS

15.03.2021 12:08:42 | Автор: admin


Привет, Хабр! Меня зовут Георгий Гигаури, я разрабатываю Android-приложение Delivery Club. Эта статья появилась после доклада на конференции Mobius 2020, где мы выступали вместе с Павлом Борзиковым. Для тех, кто любит видео, ищите его в конце статьи.

Почему мы вообще обратили внимание на Huawei-устройства? Всё началось с того, что Huawei теперь не может распространять свои устройства с сервисами Google Play. Да, они могут использовать ОС Android, так как это открытая операционная система, но чтобы распространять устройства с сервисами Google Play, необходимо иметь лицензию. К сожалению, Huawei не может получить её из-за разногласий между Китаем и США. Поэтому Huawei приходится разрабатывать свои собственные Mobile Services. Справедливости ради, они этим занимались уже давно, но теперь им приходится расширять кодовую базу, активно увеличивать количество сервисов.

Почему стоит обратить внимание на экосистему Huawei


Смартфоны Huawei очень популярны: в 2020 году в России они занимали почти 18% рынка (Рис.1), а в мире 11% (Рис.2), (источник). Huawei заявила, что более 490 млн человек в более чем в 170 странах мира пользуются AppGallery (источник). Поскольку аудитория у Huawei-устройств огромная, мы не можем это игнорировать и решили поддержать пользователей нашего приложения. Далее поэтапно рассмотрим, что же нужно сделать.


Рис.1


Рис.2

Этап 1: проверка наличия Services


Если у вас в приложении при входе есть проверка наличия Google Services, то придётся от этого отказаться, и проверять наличие соответствующих сервисов только по мере необходимости.

fun Context.getMobileServiceSource(): MobileServicesSource {    val googleApi = GoogleApiAvailability.getInstance()    if (googleApi.isGooglePlayServicesAvailable(this) == com.google.android.gms.common.ConnectionResult.SUCCESS) {        return MobileServicesSource.GOOGLE    }    val huaweiApi = HuaweiApiAvailability.getInstance()    if (huaweiApi.isHuaweiMobileServicesAvailable(this) == com.huawei.hms.api.ConnectionResult.SUCCESS) {        return MobileServicesSource.HMS    }    return MobileServicesSource.NONE}enum class MobileServicesSource {    GOOGLE,    HMS,    NONE}

Пример реализации: добавляем extension, возвращающий конкретный доступный сервис, а в момент использования функциональности проверяем, что на устройстве есть нужные нам сервисы.

Этап 2: карты


В приложении Delivery Club три основные страницы:

  • карта с местоположением клиента;
  • информация о ресторане, который будет готовить заказ, с указанием его местоположения на карте;
  • карта с отслеживанием местоположения курьера, везущего заказ.

На устройствах Huawei все эти карты не работают. Чтобы это исправить, можно просто заменить зависимости: вместо пакета com.google.android.gms использовать com.huawei.hms:





Конечно, есть нюансы, но мы уже сделали большую часть работы. Huawei сделала Maps SDK с контрактами, по большей части соответствующий Google Maps SDK. Однако у Google есть deprecated-методы, если вы их используете, то аналогов у Huawei может и не найтись. Например, для получения местоположения пользователя мы используем:

LocationServices.FusedLocationApi.getLastLocation(googleApiClien)

Такой подход считается deprecated, и если мы просто скопируем код для Huawei Maps и заменим зависимости, то работать не будет. Нужно поменять так:

LocationServices.getFusedLocationProviderClient().getLastLocation().addOnSuccessListener()

PolyUtil. Расшифровка с помощью Polyline


Теперь нам нужно отображать перемещение курьера. Для этого нам нужно расшифровывать строку, которая приходит с сервера. Для этого воспользуемся тем же алгоритмом от Google, с помощью которого строка кодировалась.



После расшифровки мы получили список координат курьера.

Реализация поддержки двух карт


Для поддержки нескольких карт необходимо создать обёртку для самих карт и для объекта.

Добавляем общий интерфейс, например, IMapWidget. Не забываем сделать общий класс для LatLng список координат курьера. У Google он лежит в пакете com.google.android.gms.maps.model.LatLng, а у Huawei в com.huawei.hms.maps.model.LatLng. Кладём список в PolyLineOptions и задаём ширину и цвет линии маршрута.

interface IMapWidget {    void animateCamera(...);    void setListener(OnMapEventListener listener);    void setMapPadding(...);    MapMarker addMarker(...);    ...}

Добавляем Custom Map View реализующего интерфейс IMapWidget:



Добавляем обёртку, которая позволяет нам указать, где мы хотим отрисовывать карту:

class MapWrapper : FrameLayout() {    fun setupMap(widget: IMapWidget) {        removeAllViews()        addView(widget as View)    }}

И в нужном месте вызываем метод добавления карты.

override fun onCreateView(...) {    ...    val map: IMapWidget = MapFactory.createMap()    viewMapWrapper.setupMap(map)    ...}

Такие обёртки класса нужно создать для всего: объектов, маркеров, PolyUtil, PolyLine и т.д.

Проблема: Карта не работает




Однажды нам сообщили о баге. Пользователь с устройством Huawei, находившийся в центре Москвы (Рис.3), открыл приложение, нажал на кнопку Переместиться на своё местоположение, и его перенесло в пустоту (Рис.4). Пользователь не видит, ни улиц, ни зданий, и он решил, что карта не работает.

Мы попробовали воспроизвести у себя эту проблему. И действительно попадали в неопределённое пространство. Когда попробовали чуть-чуть уменьшить масштаб карты, то оказалось, что мы попали в пригород Мариуполя (Рис.5). То есть из московских координат (55.819207, 37.493424) перенеслись в мариупольские (47.187447, 37.593137). Мы были в полном недоумении. Может быть, где-то у нас с числами что-то не то происходит. Возможно, происходят некие вычитания наших координат. Очень долго искали решение этой проблемы или хотя бы причину. Оказалось, что мы заменили импорты из Google-карт, и поэтому всё перестало работать. В конце концов мы добрались до paddingа.



Давайте быстро вспомним, что такое padding у карты. На (Рис.6) показан экран авторизации, карта занимает всю область экрана, даже под плашкой ручного ввода адреса. В таком случае, если мы не добавим padding карте, её центр будет находиться на месте зелёного треугольника, но мы хотим, чтобы он был в центре рабочей области карты. Padding сужает рабочую область (Рис.7). Не видимую, а именно рабочую. Карта будет по-прежнему занимать весь экран, но размер её рабочей области изменится. И когда вы будете переходить в новую координату, она будет принимать положение новой рабочей карты. Как оказалось, баг был именно из-за этого.

Первое решение: убрать padding. Как вы понимаете, такой вариант нам не подошёл. Мы хотели, чтобы всё отображалось красиво.

Второе решение проблемы: использовать анимированное перемещение, но с масштабированием.

val zoom = map.cameraPosition.zoommap.animateCamera(CameraUpdateFactory.newLatLngZoom(position, zoom))

При переходе с изменением масштаба карты всё работало правильно. Здорово! Мы подумали, что это нам подходит. На самом деле нет. У нас ещё есть третий экран, на котором нужно увеличивать карту относительно двух маркеров, чтобы zoom сам рассчитывался, поэтому мы не можем задать какое-то константное масштабирование. То есть такой вариант нам тоже не подошёл. Начали думать дальше и нашли новое решение.

Третье решение проблемы: вообще отказаться от анимации. Как оказалось, если вместо animateCamera сделать просто move, то перемещение будет происходить правильно. Так мы и сделали. Надеемся, в скором времени Huawei устранит эту проблему.

Этап 3: push-сервис


Идём дальше. На Huawei-устройства не приходят уведомления нашего приложения. Дело в том, что мы не можем получить токен. Давайте его получим. В Google мы получаем задачу и извлекаем токены так:

FirebaseMessaging.getInstance().token.addOnCompleteListener { task ->    if (task.isSuccessful) {        val token = task.result    }}

Наше решение:

class ImplementationHuaweiMessagingService : HmsMessageService() {    override fun onNewToken(token: String?) {        val commonApi = getComponentFactory().get(CommonApi::class.java)        commonApi.settingsManager().setPushToken(token)    }    override fun onMessageReceived(message: RemoteMessage?) {        message?.let {            val appManagersComponent = getComponentFactory().get(AppManagersApi::class.java)            appManagersComponent.pushManager().handle(it.dataOfMap)        }    }

Выглядит всё так же, как и с реализацией FirebaseMessagingService(), даже есть callbackи onNewToken и onMessageReceived. Однако без нюансов не обойтись. Случается, что на некоторых редких устройствах onMessageReceived вызывается в главном потоке, поэтому лучше не использовать здесь долго выполняющиеся задачи.

Получаем токены на Huawei:

val token = HmsInstanceId.getInstance(context)    .getToken(appId, com.huawei.hms.push.HmsMessaging.DEFAULT_TOKEN_SCOPE)public static final String DEFAULT_TOKEN_SCOPE = "HCM";

Обратите внимание, что метод выполняется в главном потоке. И для получения токена нужно отдельно реализовать поток. У Google такой подход уже считается устаревшим, возможно, Huawei придёт к тому же.

Мы можем вообще не использовать getToken, а прописать в манифесте автоматическую инициализацию или в коде методом setAutoInitEnabled() и всегда получать token в onNewToken (подробнее). Это решит ещё одну проблему: getToken в версиях EMUI ниже 10 вообще возвращает null.

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

Этап 4: Chrome Custom Tabs


Наше приложение при запуске регулярно вылетает с ошибкой ActivityNotFoundException. Чтобы от этого избавиться, нужно обработать отсутствие Chrome Tabs.

fun Context.openLink(url: String, customTabsSession: CustomTabsSession? = null): Boolean {    try {        openLinkInCustomTab(url, customTabsSession)        return true    } catch (throwable: Throwable) {        Timber.tag("Context::openLink").e(throwable, "CustomTabsIntent error on url: $url")    }    return openLinkInBrowser(url)}@Throws(Throwable::class)fun Context.openLinkInCustomTab(url: String, customTabsSession: CustomTabsSession? = null) {    CustomTabsIntent.Builder(customTabsSession)        .build()        .launchUrl(this, Uri.parse(url))}private fun Context.openLinkInBrowser(url: String): Boolean {    val intent: Intent = Intent(Intent.ACTION_VIEW, Uri.parse(url)).apply {        addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY or Intent.FLAG_ACTIVITY_NEW_DOCUMENT)    }    if (intent.resolveActivity(packageManager) != null) {        startActivity(intent)        return true    }    return false}

Мы просто обернули openLinkInCustomTab() в try catch и в случае ошибки пытаемся открыть в браузере. Но бывает такого, чтобы на устройстве не было подходящего браузера, способного обработать наш неявный intent. Поэтому если метод openLinkInBrowser() возвращает false, мы открываем страницу в webview.

Этап 5: аналитика


Аналитика у Huawei похожа на Google Analytics. Покажу замену на примере Firebase. Сначала инициализируем: HiAnalytics.getInstance(context). Затем с помощью HAEventType.STARTCHECKOUT копируем все наши события из Firebase в отдельный файл huaweiAnalytics:

huaweiAnalytics.onEvent(name, bundle)

Системные параметры: HAParamType.PRICE, HAParamType.CURRNAME

Даже если у вас нет Firebase, добавить аналитику в Huawei очень просто. У них отличная документация, контракт соблюдается. Также у Huawei есть отличные инструменты для исследования аудитории.

Этап 6: crashlytics


Следующий инструмент, который нам тоже стало интересно попробовать, это Crashlytics от Huawei, которая называется AGConnectCrash. Она позволяет с минимальными усилиями собирать и анализировать информацию о падении приложения.

Инициализируем crashlytics:

AGConnectCrash.getInstance().enableCrashCollection(true)

Добавляем свои ключи и журналируем нужные события:

AGConnectCrash.getInstance().setUserId("testuser")AGConnectCrash.getInstance().log(Log.DEBUG, "set debug log.")AGConnectCrash.getInstance().log(Log.INFO, "set info log.")AGConnectCrash.getInstance().log(Log.WARN, "set warning log.")AGConnectCrash.getInstance().log(Log.ERROR, "set error log.")AGConnectCrash.getInstance().setCustomKey("stringKey", "Hello world")AGConnectCrash.getInstance().setCustomKey("booleanKey", false)AGConnectCrash.getInstance().setCustomKey("doubleKey", 1.1)AGConnectCrash.getInstance().setCustomKey("floatKey", 1.1f)AGConnectCrash.getInstance().setCustomKey("intKey", 0)AGConnectCrash.getInstance().setCustomKey("longKey", 11L)

Этап 7: покупки в приложении


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

Всё очень похоже на реализацию Google. При запуске приложения запрашиваем все прошлые покупки пользователя:

fun getOwnedPurchases(    activity: Activity,    ownedPurchasesResultOnSuccessListener: OnSuccessListener<OwnedPurchasesResult>,    failureListener: OnFailureListener) {    val ownedPurchasesReq = OwnedPurchasesReq()    // priceType: 0: consumable; 1: non-consumable; 2: auto-renewable subscription    ownedPurchasesReq.priceType = IapClient.PriceType.IN_APP_SUBSCRIPTION    // To get the Activity instance that calls this API.    val task: Task<OwnedPurchasesResult> = Iap.getIapClient(activity)        .obtainOwnedPurchases(ownedPurchasesReq)    task.addOnSuccessListener(ownedPurchasesResultOnSuccessListener)        .addOnFailureListener(failureListener)}

Если какой-то товар был куплен, мы разблокируем его функциональность. Потом запрашиваем подробности по товарам, доступным для продажи цену и описание:

fun loadProduct(    context: Context,    productInfoResultOnSuccessListener: OnSuccessListener<ProductInfoResult>,    onFailureListener: OnFailureListener) {    // obtain in-app product details configured in AppGallery Connect, and then show the products    val iapClient: IapClient = Iap.getIapClient(context)    val task: Task<ProductInfoResult> = iapClient.obtainProductInfo(createProductInfoReq())    task.addOnSuccessListener(productInfoResultOnSuccessListener)        .addOnFailureListener(onFailureListener)}private fun createProductInfoReq(): ProductInfoReq {    val req = ProductInfoReq()    // 0: consumable ; 1: non-consumable ; 2: auto-renewable subscription    req.priceType = IapClient.PriceType.IN_APP_SUBSCRIPTION    val productIds = ArrayList<String>()    productIds.add("PRODUCT_ID")    req.productIds = productIds    return req}

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

fun gotoPay(activity: Activity, productId: String, type: Int) {    val client: IapClient = Iap.getIapClient(activity)    val task: Task<PurchaseIntentResult> = client.createPurchaseIntent(createPurchaseIntentReq(type, productId))    task.addOnSuccessListener { result ->        result?.let {            val status: Status = result.status            if (status.hasResolution()) {                try {                    status.startResolutionForResult(activity, PAY_RESULT_ARG)                } catch (exception: SendIntentException) {                    Timber.e(exception)                }            } else {                Timber.d("intent is null")            }        }    }.addOnFailureListener { exception ->        Timber.e(exception)    }}

Так как это Activity, мы передаём ему аргумент, по которому можно отловить OnActivityResult и понять, успешно ли прошла оплата и как закончилась транзакция:

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {    super.onActivityResult(requestCode, resultCode, data)    if (resultCode == PAY_RESULT_ARG) {        val purchaseResultInfo: PurchaseResultInfo = Iap.getIapClient(this).parsePurchaseResultInfoFromIntent(data)        when (purchaseResultInfo.returnCode) {            OrderStatusCode.ORDER_STATE_SUCCESS -> {                successResult(purchaseResultInfo)            }            OrderStatusCode.ORDER_STATE_CANCEL -> {            }            OrderStatusCode.ORDER_PRODUCT_OWNED -> {            }        }    }}

У нас есть специальные статусы: ORDER_SUCCESS, CANCEL, OWNED. Первый означает успешную оплату. Второй пользователь просто закрыл страницу без покупки, тогда мы обрабатываем этот callback и предлагаем скидку, чтобы уговорить на покупку. А третий статус означает, что товар уже куплен пользователем. Если товар разовый или подписочный, то на этом моменте нужно остановиться, в противном случае виртуально доставить покупку.

В случае успешной оплаты доставляем пользователю купленный товар:

private fun successResult(purchaseResultInfo: PurchaseResultInfo) {    val inAppPurchaseData = InAppPurchaseData(purchaseResultInfo.inAppPurchaseData)    val req = ConsumeOwnedPurchaseReq()    req.purchaseToken = inAppPurchaseData.purchaseToken    val client: IapClient = Iap.getIapClient(this)    val task: Task<ConsumeOwnedPurchaseResult> =        client.consumeOwnedPurchase(req)    task.addOnSuccessListener {        // Consume success    }.addOnFailureListener { exception ->        Timber.e(exception)    }}

Если не сделать доставку, то функциональность товара будет у пользователя заблокирована, а деньги возвращены. В Google Play Billing Library до третьей версии этого делать не нужно было, но потом Google тоже это добавил, и если мы не доставим товар, через 48 часов покупка отменится, а деньги вернутся пользователю. То есть в Huawei покупки реализованы как в третьей версии Google Play Billing.

Выводы


На реализацию поддержки Huawei-устройств не уйдёт много времени. Даже без реальных устройств вы сможете проверить работоспособность вашего приложение: у Huawei есть своя тестовая лаборатория с виртуальными устройствами наподобие Samsung Remote test lab. Количество пользователей быстро растёт, и бизнесу может оказаться выгодным вложиться в доработку продуктов, а отличная документация поможет разработчикам всё сделать быстро. Поддержка HMS активно отвечает на любые вопросы, если вы не сможете в документации что-то найти.

Видеозапись доклада с конференции Mobius 2020.

Полезные ссылки


Подробнее..

За двумя мобильными сервисами HMS и GMS в одном приложении

05.10.2020 10:14:40 | Автор: admin


Привет, Хабр! Меня зовут Андрей, я делаю приложение Кошелёк для Android. Уже больше полугода мы помогаем пользователям смартфонов Huawei оплачивать покупки банковскими картами бесконтактно через NFC. Для этого нам потребовалось добавить поддержку HMS: Push Kit, Map Kit и Safety Detect. Под катом я расскажу, какие проблемы нам пришлось решать при разработке, почему именно так и что из этого вышло, а также поделюсь тестовым проектом для более быстрого погружения в тему.

Для того, чтобы предоставить всем пользователям новых смартфонов Huawei возможность бесконтактной оплаты из коробки и обеспечить лучший пользовательский опыт в остальных сценариях, в январе 2020 года мы начали работы по поддержке новых пушей, карт и проверок на безопасность. Результатом должно было стать появление в AppGallery версии Кошелька с родными для телефонов Huawei мобильными сервисами.

Вот что удалось выяснить на этапе первоначальной проработки


  • Huawei распространяет AppGallery и HMS без ограничений можно скачать и установить их на устройства других производителей;
  • После того, как мы установили AppGallery на Xiaomi Mi A1, все обновления начали подтягиваться в первую очередь с новой площадки. Сложилось впечатление, что AppGallery успевает обновлять приложения быстрее конкурентов;
  • Сейчас Huawei стремится как можно быстрее наполнить AppGallery приложениями. Чтобы ускорить миграцию на HMS, они решили предоставить разработчикам уже знакомый (похожий на GMS) API;
  • На первых порах, пока экосистема Huawei для разработчиков не заработает на полную мощность, отсутствие Google-сервисов скорее всего будет являться главной проблемой для пользователей новых смартфонов Huawei, и они будут всеми способами пытаться их установить.

Мы решили делать одну общую версию приложения для всех площадок распространения. Она должна уметь определять и использовать подходящий тип мобильных сервисов в рантайме. Этот вариант казался медленнее в реализации, чем отдельная версия под каждый тип сервисов, но мы рассчитывали выиграть в другом:

  • Исключается риск попадания версии, предназначенной для Google Play, на девайсы Huawei и наоборот;
  • Можно внедрить любой алгоритм выбора мобильных сервисов, в том числе с использованием feature toggle;
  • Тестировать одно приложение проще, чем два;
  • Каждый релиз можно выкладывать на все площадки распространения;
  • Не приходится переключаться с написания кода на управление сборкой проекта при разработке/модификации.

Для работы с разными реализациями мобильных сервисов в одной версии приложения необходимо:

  1. Спрятать все обращения за абстракцию, сохранив работу с GMS;
  2. Добавить реализацию для HMS;
  3. Разработать механизм выбора реализации сервисов в рантайме.

Методика внедрения поддержки Push Kit и Safety Detect значительно отличается от Map Kit, поэтому рассмотрим их отдельно.

Поддержка Push Kit и Safety Detect


Как и положено в таких случаях, процесс интеграции начался с изучения документации. В разделе предостережений обнаружились вот такие пункты:
  • If the EMUI version is 10.0 or later on a Huawei device, a token will be returned through the getToken method. If the getToken method fails to be called, HUAWEI Push Kit automatically caches the token request and calls the method again. A token will then be returned through the onNewToken method.
  • If the EMUI version on a Huawei device is earlier than 10.0 and no token is returned using the getToken method, a token will be returned using the onNewToken method.
  • For an app with the automatic initialization capability, the getToken method does not need to be called explicitly to apply for a token. The HMS Core Push SDK will automatically apply for a token and call the onNewToken method to return the token.

Главное, что нужно вынести из этих предостережений существует разница в получении пуш-токена на разных версиях EMUI. После вызова метода getToken(), реальный токен может быть возвращен через вызов метода onNewToken() сервиса. Наши испытания на реальных устройствах показали, что телефоны с EMUI < 10.0 на вызов метода getToken возвращают null или пустую строку, после чего происходит вызов метода onNewToken() сервиса. Телефоны с EMUI >= 10.0 всегда возвращали пуш-токен из метода getToken().

Можно реализовать вот такой источник данных, чтобы привести логику работы к единому виду:
class HmsDataSource(   private val hmsInstanceId: HmsInstanceId,   private val agConnectServicesConfig: AGConnectServicesConfig) {   private val currentPushToken = BehaviorSubject.create<String>()   fun getHmsPushToken(): Single<String> = Maybe       .merge(           getHmsPushTokenFromSingleton(),           currentPushToken.firstElement()       )       .firstOrError()   fun onPushTokenUpdated(token: String): Completable = Completable       .fromCallable { currentPushToken.onNext(token) }   private fun getHmsPushTokenFromSingleton(): Maybe<String> = Maybe       .fromCallable<String> {           val appId = agConnectServicesConfig.getString("client/app_id")           hmsInstanceId.getToken(appId, "HCM").takeIf { it.isNotEmpty() }       }       .onErrorComplete()}

class AppHmsMessagingService : HmsMessageService() {   val onPushTokenUpdated: OnPushTokenUpdated = Di.onPushTokenUpdated   override fun onMessageReceived(remoteMessage: RemoteMessage?) {       super.onMessageReceived(remoteMessage)       Log.d(LOG_TAG, "onMessageReceived remoteMessage=$remoteMessage")   }   override fun onNewToken(token: String?) {       super.onNewToken(token)       Log.d(LOG_TAG, "onNewToken: token=$token")       if (token?.isNotEmpty() == true) {           onPushTokenUpdated(token, MobileServiceType.Huawei)               .subscribe({},{                   Log.e(LOG_TAG, "Error deliver updated token", it)               })       }   }}

Важные замечания:

  • Предложенное решение работает не во всех случаях. При тестировании на физических устройствах проблем выявлено не было, но на пуле устройств, предоставляемых AppGallery для онлайн-дебаггинга, подход не срабатывает. Причём не срабатывает из за того, что вызова метода HmsMessageService.onNewToken() не происходит, что, кажется, не соответствует документации. Причина такого поведения по сей день остаётся для нас невыясненной;
  • Оказалось, что на некоторых устройствах метод HmsMessageService.onMessageReceived() может вызываться на main потоке, поэтому будьте аккуратнее с походами в БД и сеть из него;
  • Как только вы добавите зависимость от библиотеки com.huawei.hms:push, в манифесте проекта после сборки будет объявлен сервис com.huawei.hms.support.api.push.service.HmsMsgService, сконфигурированный для работы в отдельном процессе :pushservice. С этого момента, при порождении каждого процесса, в нём будет создаваться свой экземпляр класса Application. Это принципиально важно осознавать, если вы обращаетесь к файлам или БД или, например, собираете данные о скорости инициализации приложения через Firebase Performance. Мы встретились с порождением второго процесса только на не-Huawei устройствах, куда были установлены AppGallery и HMS.

Для случаев поддержки работы приложения с пуш-токеном и проверки устройства на безопасность общий алгоритм будет одинаковым:


  • Создаём по отдельному источнику данных для каждого типа сервисов;
  • Добавляем по репозиторию для пушей и безопасности, принимающих на вход тип мобильных сервисов и выбирающих конкретный источник данных;
  • Некая сущность бизнес-логики определяет, какой тип мобильных сервисов (из доступных) уместно использовать в конкретном случае.

Разработка механизма выбора реализации сервисов в рантайме


Как действовать, если на устройстве установлен всего один тип сервисов или их нет вовсе, понятно, а вот что делать, если одновременно установлены и Google-, и Huawei-сервисы?

Вот что мы обнаружили и из чего исходили:

  • При внедрении любой новой технологии её нужно использовать в приоритете, если устройство пользователя полностью соответствует всем требованиям;
  • На устройствах с EMUI >= 10.0 алгоритм получения пуш-токена отличается от предыдущих версий;
  • Подавляющее большинство устройств Huawei без Google-сервисов будут иметь версию EMUI 10.0 и выше;
  • На новые устройства Huawei пользователи будут пытаться установить Google-сервисы, чтобы пользоваться всеми привычными приложениями. Надёжного способа сделать это нет, поэтому мы не должны рассчитывать на стабильную и корректную работу Google-сервисов на таких устройствах;
  • Технически пользователи смартфонов других вендоров могут установить себе AppGallery и Huawei-сервисы, но мы предполагаем, что на текущий момент таких пользователей очень мало.

Разработка алгоритма оказалась, наверное, самым выматывающим делом. Здесь в одну точку сошлось множество технических и бизнесовых факторов, но в конечном итоге нам удалось прийти к наилучшему для нашего продукта решению. Сейчас даже немного странно, что описание самой обсуждаемой части алгоритма помещается в одно предложение, но я рад, что в конечном итоге получилось просто:
В случае, если на устройстве установлены оба типа сервисов и удалось определить, что версия EMUI < 10 используем Google, иначе используем Huawei.

Для реализации итогового алгоритма требуется найти способ определить версию EMUI на устройстве пользователя.
Один из способов сделать это прочитать системные свойства:
class EmuiDataSource {    @SuppressLint("PrivateApi")    fun getEmuiApiLevel(): Maybe<Int> = Maybe        .fromCallable<Int> {            val clazz = Class.forName("android.os.SystemProperties")            val get = clazz.getMethod("getInt", String::class.java, Int::class.java)            val currentApiLevel = get.invoke(                    clazz,                    "ro.build.hw_emui_api_level",                    UNKNOWN_API_LEVEL            ) as Int            currentApiLevel.takeIf { it != UNKNOWN_API_LEVEL }        }        .onErrorComplete()    private companion object {        const val UNKNOWN_API_LEVEL = -1    }}

Для правильного выполнения проверок на безопасность дополнительно нужно учесть, что состояние сервисов не должно требовать обновления.

Итоговая реализация алгоритма, учитывающая тип операции, для которой выбирается сервис, и определение версии EMUI устройства, может выглядеть так:
sealed class MobileServiceEnvironment(   val mobileServiceType: MobileServiceType) {   abstract val isUpdateRequired: Boolean   data class GoogleMobileServices(       override val isUpdateRequired: Boolean   ) : MobileServiceEnvironment(MobileServiceType.Google)   data class HuaweiMobileServices(       override val isUpdateRequired: Boolean,       val emuiApiLevel: Int?   ) : MobileServiceEnvironment(MobileServiceType.Huawei)}

class SelectMobileServiceType(        private val mobileServicesRepository: MobileServicesRepository) {    operator fun invoke(            case: Case    ): Maybe<MobileServiceType> = mobileServicesRepository            .getAvailableServices()            .map { excludeEnvironmentsByCase(case, it) }            .flatMapMaybe { selectEnvironment(it) }            .map { it.mobileServiceType }    private fun excludeEnvironmentsByCase(            case: Case,            envs: Set<MobileServiceEnvironment>    ): Iterable<MobileServiceEnvironment> = when (case) {        Case.Push, Case.Map -> envs        Case.Security       -> envs.filter { !it.isUpdateRequired }    }    private fun selectEnvironment(            envs: Iterable<MobileServiceEnvironment>    ): Maybe<MobileServiceEnvironment> = Maybe            .fromCallable {                envs.firstOrNull {                    it is HuaweiMobileServices                            && (it.emuiApiLevel == null || it.emuiApiLevel >= 21)                }                        ?: envs.firstOrNull { it is GoogleMobileServices }                        ?: envs.firstOrNull { it is HuaweiMobileServices }            }    enum class Case {        Push, Map, Security    }}

Поддержка Map Kit


После реализации алгоритма выбора сервисов в рантайме, алгоритм добавления поддержки базового функционала карт выглядит тривиально:

  1. Определить тип сервисов для отображения карт;
  2. Заинфлейтить соответствующий layout и работать с конкретной реализацией карт.

Однако здесь есть одна особенность, о которой хочется рассказать. Rx головного мозга позволяет практически куда угодно добавить любую асинхронную операцию без риска переписать всё приложение, но накладывает и свои ограничения. Например, в данном случае для определения соответствующего лэйаута, скорее всего, потребуется вызвать .blockingGet() где-нибудь на Main потоке, что совсем нехорошо. Решить эту проблему можно, например, с помощью дочерних фрагментов:

class MapFragment : Fragment(),   OnGeoMapReadyCallback {   override fun onActivityCreated(savedInstanceState: Bundle?) {       super.onActivityCreated(savedInstanceState)       ViewModelProvider(this)[MapViewModel::class.java].apply {           mobileServiceType.observe(viewLifecycleOwner, Observer { result ->               val fragment = when (result.getOrNull()) {                   Google -> GoogleMapFragment.newInstance()                   Huawei -> HuaweiMapFragment.newInstance()                   else -> NoServicesMapFragment.newInstance()               }               replaceFragment(fragment)           })       }   }   override fun onMapReady(geoMap: GeoMap) {       geoMap.uiSettings.isZoomControlsEnabled = true   }}

class GoogleMapFragment : Fragment(),   OnMapReadyCallback {   private var callback: OnGeoMapReadyCallback? = null   override fun onAttach(context: Context) {       super.onAttach(context)       callback = parentFragment as? OnGeoMapReadyCallback   }   override fun onDetach() {       super.onDetach()       callback = null   }   override fun onMapReady(googleMap: GoogleMap?) {       if (googleMap != null) {           val geoMap = geoMapFactory.create(googleMap)           callback?.onMapReady(geoMap)       }   }}

class HuaweiMapFragment : Fragment(),   OnMapReadyCallback {   private var callback: OnGeoMapReadyCallback? = null   override fun onAttach(context: Context) {       super.onAttach(context)       callback = parentFragment as? OnGeoMapReadyCallback   }   override fun onDetach() {       super.onDetach()       callback = null   }   override fun onMapReady(huaweiMap: HuaweiMap?) {       if (huaweiMap != null) {           val geoMap = geoMapFactory.create(huaweiMap)           callback?.onMapReady(geoMap)       }   }}

Теперь можно написать отдельную реализацию для работы с картой для каждого отдельного фрагмента. Если потребуется реализовать одинаковую логику, то можно поступить по знакомому алгоритму подогнать работу с каждым типом карт под один интерфейс и передать одну из реализаций этого интерфейса в родительский фрагмент, как это сделано в MapFragment.onMapReady()

Что из этого вышло


В первые дни после релиза обновленной версии приложения число установок достигло 1 млн. Мы связываем это отчасти с фичерингом со стороны AppGallery, а отчасти с тем, что наш релиз подсветило несколько СМИ и блогеров. А ещё со скоростью обновления приложений ведь в AppGallery на протяжении двух недель лежала версия с самым высоким versionCode.

Мы получаем полезные отзывы о работе приложения в общем и о токенизации банковских карт в частности от пользователей в нашей ветке на 4pda. После релиза Pay-функциональности для Huawei посетителей на форуме прибавилось, и проблем, с которыми они сталкиваются, тоже. Мы продолжаем работать над всеми обращениями, но массовых проблем при этом не наблюдаем.

В целом, релиз приложения в AppGallery прошёл успешно и можно сделать вывод, что наш подход к решению задачи оказался рабочим. Благодаря выбранному методу реализации у нас сохранилась возможность выкладывать все релизы приложения как в Google Play, так и в AppGallery.

Пользуясь этим методом, мы уже добавили в приложение Analytics Kit, APM, работаем над поддержкой Account Kit и не планируем на этом останавливаться, тем более, что с каждой новой версией HMS становится доступно всё больше возможностей.

Послесловие


Регистрация аккаунта разработчика в AppGallery представляет собой гораздо более сложную процедуру, чем в случае с Google. У меня, например, этап проверки подтверждения личности занял 9 дней. Не думаю что так происходит со всеми, но любая задержка способна поубавить оптимизма. Поэтому вместе с полным кодом всего демо-решения, описанного в статье, я закоммитил в репозиторий и все ключи приложения, чтобы у вас была возможность не только оценить решение целиком, но и прямо сейчас испытать и усовершенствовать предложенный подход.

Пользуясь выходом в публичное пространство, хочу поблагодарить всю команду Кошелька и особенно umpteenthdev, Артёма Кулакова и Егора Аганина за неоценимый вклад в интеграцию HMS в Кошелёк!

Полезные ссылки


  • Полный код демонстрационного проекта на GitHub;
  • Скачать AppGallery на телефон любого производителя. Актуальную версию приложения HMS-Core можно загрузить из AppGallery;
  • Push Kit codelab;
  • Map Kit codelab;
  • Safety Detect codelab;
  • Инструкция к сервису онлайн-дебаггинга своих приложений на устройствах Huawei. Возможность использования появляется после регистрации в AppGallery Connect;
  • Ветка приложения Кошелёк на 4PDA.
Подробнее..

Джентльменский набор от Huawei для разработчика мобильных игр Game Service и инструменты для быстрой интеграции HMS

23.10.2020 14:16:54 | Автор: admin

Привет, Хабр! Меня зовут Михаил, я занимаюсь технической поддержкой разработчиков в области интеграции Huawei Mobile Service. И сегодня я хочу рассказать про наши инструменты, которые могут быть полезны разработчикам мобильных игр. Про то, как можно быстро адаптировать игру, уже рассказывали наши друзья из Azur Games. В этой статье я более детально расскажу про Huawei Game Service, реализующий базовые внутриигровые функции, а также про инструменты для монетизации приложений, работы с рекламой и аналитикой.

Huawei Game Service на уровне приложений


Huawei Game Service это часть экосистемы HMS для работы c играми. Она работает на уровне приложения и на уровне системы. На уровне приложения HGS (Huawei Game Service) позволяет:

  • Реализовать систему внутриигровых достижений. Можно настроить до 200 ачивок для максимального вовлечения пользователей в игру. В Game Service можно добавлять новые достижения и задавать новые челленджи для пользователей, когда они уже прошли игру. Сами достижения включают ID, краткое название, описание, иконку, состояние. Состояние, в свою очередь, может быть трёх типов: скрытое достижение открывается после определённого этапа или покупки; открытое достижение показывается игроку, но он его ещё не заработал; разблокированное достижение заработано, о чём пользователь получает уведомление во всплывающем окне.
  • Получать статистику игроков. Статистика показывает активность игрока, основное время, когда он играет, и другие параметры. Тем, кто давно не заходил в приложение, можно выслать пуш-напоминание. Также можно оценить среднее время игры и количество совершённых покупок.
  • Получать сообщения о событиях. С их помощью можно дополнять статистические данные и ориентироваться уже на конкретные сценарии. Например, понять, что игрок дошёл до такого-то уровня, и предложить ему внутриигровую покупку или участие в акции.
  • Строить таблицы лидеров. В Game Service предусмотрено 70 таблиц лидеров, которые ранжируются автоматически и могут загружаться во время игры или после по разным параметрам.
  • Работать с сохранениями. Игровой процесс сохраняется на Huawei Drive, что позволяет расшаривать данные игры между устройствами и получить доступ к ним в случае утери / поломки телефона.

Системные функции Huawei Game Services



Huawei Game Service базируется на движке GameTurbo Engine, который связывает между собой операционную систему и само приложение. Это позволяет регулировать нагрузки при ограниченных ресурсах системы приложение может передавать игровую сцену, конфигурацию и другую информацию для системы, чтобы динамически распределять ресурсы. Система, в свою очередь, предоставляет информацию о своём статусе, чтобы можно было изменить параметры работы приложения и адаптироваться для бесшовного взаимодействия пользователя с игрой.

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

Инструменты для монетизации


При работе с платёжными сервисами экосистема Huawei требует обязательную регистрацию юридического лица. После подтверждения данных будет доступна работа с рекламой и покупками в приложении. Для этого используются:

  • Ads Kit, который позволяет внедрять персонализированную рекламу. Он интегрируется со сторонними рекламными платформами (например, с adjust), что позволяет отслеживать конверсию и трафик, при этом не нарушая требования конфиденциальности каждый пользователь имеет уникальный зашифрованный OAID.
  • In-App Purchases (IAP) система встроенных покупок. В играх она позволяет организовать внутриигровые платежи: покупку виртуальных товаров, подписок прямо внутри игры. С помощью сервиса можно настроить многоуровневые варианты подписки. IAP поддерживает 78 языков и доступен более чем в 170 странах. Конкретная валюта отображается автоматически в зависимости от местоположения пользователя, разработчикам надо лишь загрузить нужный пакет. К тому же IAP принимает почти все варианты оплаты, включая баллы Huawei.

Инструменты для увеличения активности пользователей


В экосистеме Huawei есть несколько способов, которыми можно стимулировать активность пользователей. Для увеличения вовлечённости в игру мы предлагаем использовать Push Kit, который позволяет отправлять персонализированные уведомления с автоматическим выбором языка. В свою очередь, разработчики могут видеть полный отчёт о просмотре и доставке уведомлений. Для уведомлений можно настроить персонализированные группы, информацию о которых Push Kit может брать с Analytics Kit. Разработчики могут настроить разные событийные сценарии для отправки уведомлений и высылать новые на основе кеша прошлых уведомлений. Также есть возможность визуальной кастомизации пушей.

С помощью Gift-модуля можно настроить систему подарков, которые игроки будут получать за определённые действия в игре или за само скачивание приложения. Подарки могут иметь уникальный серийный номер, и для их получения пользователю необходимо будет выполнить инструкцию, либо без серийного номера, и тогда их будут получать все, кто совершил определённое действие.

Еще одним способом поощрения пользователей являются Huawei Points внутренняя валюта, с помощью которой можно расплачиваться в приложения и играх. Система удобна для увеличения покупок внутри игры и для привлечения большего количества игроков. Они могут прийти со своим баллами и сразу произвести покупки в рамках игрового процесса либо заработать баллы и использовать их для покупок в других приложениях Huawei, что повышает мотивацию к игре.

На данный момент баллы могут быть использованы для покупки платных приложений, виртуальных товаров, привилегий или услуг в приложениях, обмена на внутриигровую валюту (такую как золотые монеты и бриллианты), а также для платной подписки на Huawei Video, Huawei Music и Huawei Themes.

Инструменты для работы с игровыми данными


Сейчас в ядре HMS есть около 30 разных китов для работы с различными функциями. Для большинства игр будет достаточно подключить всего три из них:

  • С помощью Analytics Kit можно собирать данные по более чем 500 параметрам, включая разные сценарии поведения пользователей, их вовлечённость в игровой процесс. Также можно находить ключевые точки, которые влияют на поведение пользователя, и облегчать взаимодействие в тех моментах, после которых большинство пользователей уходят из приложения. Помимо рекламных целей это может быть полезно для отлаживания работы приложений и быстрого реагирования на возникающие проблемы.
  • Через Account Kit можно настроить двухфакторную аутентификацию в один клик (SMS-подтверждение считывается автоматически) или подключить Huawei ID, чтобы пользователи входили без процесса регистрации. Также с помощью этого кита можно настроить прямой вход в приложение через QR-код.
  • Хранить данные игр можно с помощью Drive Kit, который представляет собой облачное хранилище. У Drive есть свой API, с помощью которого можно взаимодействовать с облаком не только через системы Huawei или Android. В рамках игровых приложение кит может быть использован для синхронизации данных прохождения игры между устройствами.

Инструменты для адаптации игр


Как правило, адаптация приложений для HMS занимает не так много сил, и основная задача сводится к обеспечению работы сразу с двумя платформами: от Google и от Huawei, и об этом на Хабре уже была статья.

Если у вас игра на движке Unity, то ускорить внедрение HMS можно с помощью плагина для Android Studio или Unity Distribution Portal, который позволяет создавать единый APK сразу для нескольких платформ, в том числе и AppGallery.Также есть прямая интеграция с Cocos Engine.

Для небольших команд будет удобно использовать облачные сервисы тестирования и дебаггинга, которые позволяют проверить приложение без физического доступа к телефонам Huawei. О них будет одна из наших следующих статей.

Как опубликовать свою игру


Для работы с AppGallery необходимо выполнить следующие шаги:

  • Зарегистрироваться в AppGallery Connect. Это универсальная консоль для приложений (в том числе и игр), которая позволяет публиковать, давать ранний доступ, получать статистику. Для регистрации необходимо указать своё юридическое лицо и добавить платёжные данные. Процесс проверки может занять до 4 дней.
  • Создать проект.
  • Добавить приложение в проект.

  • Добавить первичные интеграции с разными сервисами Huawei по выбору. Добавить скрипты и сертификаты для взаимодействия с другими китами.
  • Опубликовать приложение.

На этом пока всё. Если у вас возникли вопросы о возможностях нашей платформы, выводе своего приложения в AppGallery или технические вопросы по инструментам от Huawei, задавайте их в комментариях.
Подробнее..

Как использовать облачную ферму устройств Huawei для тестирования и отладки в Anrdoid Studio

11.05.2021 14:17:08 | Автор: admin

Как ни странно, мало кто знает о том, что у Huawei есть ферма устройств в облаке, которую можно использовать для отладки и тестирования. И речь идет не об отладке через веб-интерфейс, что является более-менее известной фичёй консоли разработчика Huawei. Мы поговорим об отладке непосредственно из студии, с возможностью пользоваться ADB.

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

Следующим шагом открываем студию и устанавливаем плагин HMS Toolkit из магазин плагинов в самой студии (File -> Settings -> Plugins).

В верхнем меню появится пункт HMS, в котором будет всё, относящееся к Huawei Mobile Services, но нас сейчас интересует именно Cloud Debugging.

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

Лично я предпочитаю логиниться по QR-коду, но опять же, сейчас это неважно. После успешного логина нам надо будет подтвердить, что мы выполняем логин для HMS Toolkit.

Далее нам будет показана страница с результатом, и мы переключимся в студию где откроется страница с выбором устройства.

Выбираем нужное нам устройство, если оно не занято, подключаемся. Перед каждым использованием устройство сбрасывается, так что нам необходимо будет пройти на нём быстрый онбординг и можно использовать. Можно запускать своё приложение, можно подключаться к процессу и отлаживаться.

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

Мне эта ферма помогла отладить своё приложение на разных моделях телефонов от Huawei. Когда-то в ней были и телефоны Honor, но сейчас когда бизнес Honor продан этих телефонов в ферме уже нет.

Если кому-то интересно, устройства в ферме все реальные, можно включить камеру с подсветкой и увидеть даже соседние девайсы.

В качестве заключения хочу добавить. Конечно, полноценно использовать облачное устройство не получится. Более того, в чём-то его возможности даже уступают эмулятору, так как будет затруднительно на устройстве тестировать кейсы с поворотами устройства, сложными жестами и другими действиями, требующими доступа непосредственно к устройству. Но для беглых смоук-тестов и для отладки на живом устройстве вполне подходит.

Подробнее..

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru