С конца 2019 Huawei поставляет Android-смартфоны без сервисов Google, в том числе без привычного всем магазина приложений Google Play. В качестве альтернативы китайская компания предлагает собственные разработки — Huawei Mobile Services (HMS), а также магазин AppGallery. В этом тексте я — разработчик Технократии Алина Саетова — расскажу, как с этим жить и работать.
В статье мы рассмотрим:
начало работы c Huawei-системой
внедрение Huawei Mobile Services в приложение
отладка и тестирование на удаленных устройствах Huawei
публикация в AppGallery
Видеоверсию статьи смотрите здесь на канале Технократии.
С чего начать?
Чтобы взаимодействовать с Huawei-системой, нужно завести Huawei ID. Это аналог google-аккаунта, с помощью которого предоставляется доступ к сервисам системы. Далее нужно зарегистрировать аккаунт разработчика: индивидуальный или корпоративный.
Индивидуальному разработчику нужно ввести свои ФИО, адрес, телефон, почту. В отличие от регистрации аккаунта разработчика в Google Play, нужны также сканы паспорта и банковской карты. Да-да, документы требуются для удостоверения личности. Huawei обещает удалить их после регистрации.
Для регистрации корпоративного аккаунта требуются данные компании, либо DUNS number (международный идентификатор юридических лиц), либо бизнес лицензия.
Ждем одобрения аккаунта. За 1-2 дня Huawei обещают проверить наши данные. После этого можно подключать приложение к HMS. Для этого заходим в консоль AppGallery Connect.
Создаем проект, а в нем добавляем приложение
Обращаем внимание, что для приложения, в котором используются HMS, название пакета должно оканчиваться на “.huawei”.
2.Помещаем конфигурационный файл agconnect-services.json в корневую папку приложения. Также сохраняем хэш SHA-256. Он потребуется для аутентификации приложения, когда оно попытается получить доступ к службам HMS Core.
Примечание. Для того, чтобы получить SHA-256, можно выполнить команду в терминале, подставив необходимые данные из вашего keystore:
keytool -list -v -keystore <keystore path> -alias <key alias> -storepass <store password> -keypass <key password>
Для работы некоторых сервисов нужно указать место хранения данных:
3.Добавляем зависимости в проект Android Studio.В build.gradle на уровне проекта:
buildscript {
repositories {
google()
jcenter()
maven { url 'https://developer.huawei.com/repo/' }
}
dependencies {
....
classpath 'com.huawei.agconnect:agcp:1.4.2.301'
}
}
allprojects {
repositories {
google()
jcenter()
maven {url 'https://developer.huawei.com/repo/'}
}
}
В build.gradle в модуле app:
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-kapt'
...
apply plugin: 'com.huawei.agconnect'
android {
...
}
dependencies {
...
implementation "com.huawei.agconnect:agconnect-core:1.4.1.300”
...
}
4.Для предотвращения обфускации AppGallery Connect сервисов, Huawei рекомендует прописать следующие правила в файле proguard-rules.pro на уровне модуля app:
Для ProGuard:
-ignorewarnings
-keep class com.huawei.agconnect.**{*;}
Для DexGuard:
-ignorewarnings
-keep class com.huawei.agconnect.** {*;}
-keepresourcexmlelements **
-keepresources */*
Первоначальная настройка проекта с Huawei Mobile Services завершена.
Внедряем HMS сервисы в проект
Почти на каждый сервис Google у Huawei есть альтернатива:
Push Kit. Отправка пуш-уведомлений пользователям.
Auth Service. В дополнение к привычным способам аутентификации здесь присутствует вход по Huawei ID.
Crash Service. Cервис для отслеживания крашей приложения.
Cloud Storage, Cloud DB. Хранение различных файлов и база данных.
Location Kit. Получение местоположения пользователя.
Analytics Kit. Анализ статистических данных приложения.
In-App Purchases. Совершение покупок в приложении.
Cloud Testing, Cloud Debugging. Тестирование приложений на удаленных устройствах Huawei.
Этот список можно продолжать долго — у Huawei довольно обширный перечень сервисов. Как же подключить их в наш проект?
Прежде всего, нам нужно определиться, как мы будем внедрять сервисы. Есть несколько вариантов:
Полностью заменяем GMS сервисы на HMS сервисы
Делаем комбинацию GMS и HMS сервисов в одном проекте
В этом деле нам пригодится плагин HMS Toolkit. Он поможет интегрировать HMS Core с минимальными затратами и высокой эффективностью. К сожалению, HMS Toolkit поддерживает конвертацию не всех сервисов, и лучше заранее уточнить, сможет ли он перенести работу ваших.
Нам нужен инструмент Convertor. Он проанализирует проект на наличие GMS сервисов и покажет места, где требуется заменить код с GMS на HMS.
В меню выбираем HMS > Convertor > New Conversion:
2.В появившемся окошке указываем директорию, где создастся бэкап проекта до конвертации.
3.Здесь плагин представляет результаты анализа проекта: какие GMS сервисы у нас содержатся и какие из них конвертируемые. Также нам предлагается проверить sdk version для соответствия требованиям HMS.
На этом шаге мы должны выбрать стратегию конвертации:
Add HMS API. На основе существующих в проекте GMS APIs генерируется XMS adapter (как дополнительный модуль в проекте). Он представляет собой прослойку между нашим кодом и непосредственно вызовом сервисов. Это такие Extension-классы, в которых лежит код, поддерживающий HMS и GMS сервисы одновременно. В runtime определяется поддерживаемый девайсом вид сервисов и вызываются соответствующие методы.
To HMS API – полностью заменяются GMS APIs на HMS APIs.
4.После анализа проекта, мы видим список мест в коде, где необходима конвертация.
По клику на каждый пункт произойдет навигация в файл, где будет предложена конвертация:
Если был выбран способ Add HMS API, мы можем посмотреть на сгенерированный xms адаптер. Вот так, например, выглядит метод из класса ExtensionUser:
А вот размер xms адаптер модуля при использовании лишь одного API с аутентификацией пользователя:
По итогу, APK нашего приложения увеличивается (old size - это APK приложения с only GMS, new size - APK с GMS и HMS одновременно):
Не сказать, что разница велика, но если в приложении будет использоваться несколько API?
Подводные камни
В политике Google Play есть замечание:
“Any existing app that is currently using an alternative billing system will need to remove it to comply with this update. For those apps, we are offering an extended grace period until September 30, 2021 to make any required changes. New apps submitted after January 20, 2021 will need to be in compliance.”
Что это значит для нас? Теперь, если приложение одновременно поддерживает HMS и GMS сервисы, и в нем есть In-App Purchases, то Google Play не допустит его публикации, а существующим приложениям придется удалить этот функционал.В итоге, если был выбран первый способ конвертации (Add HMS API), мы имеем:
Большое количество сгенерированных классов.
Увеличенный размер APK приложения.
Невозможность публикации приложения в Google Play, если в нем есть In-App Purchases.
Неполную поддержку одновременной работы HMS & GMS для некоторых сервисов.
Решение: Более привлекательным вариантом кажется второй способ конвертации — простая замена GMS APIs на HMS APIs. Но вместе с этим используем product flavors, чтобы получать сборки приложения отдельно для Google Play и AppGallery.
Product Flavors
Создадим два product flavor - “hms” и “gms”:
Общий код будет располагаться в директории main/
Укажем sourceSets в файлах build.gradle модулей (только там, где необходимо разделение на hms и gms)
Код с GMS имплементацией будет в папке gms/, а с HMS соответственно в hms/
У hms flavor’a указываем applicationIdSuffix = ‘.huawei’
Если же нет необходимости заводить целые файлы отдельно для каждого flavor’a, то можно проверять текущий flavor через BuildConfig.FLAVOR
android {
…
flavorDimensions 'services'
productFlavors {
hms {
dimension 'services'
applicationIdSuffix '.huawei'
}
gms {
dimension 'services'
}
}
}
По умолчанию, Android Studio заводит sourceSet main, в котором содержатся общие файлы с кодом. Создаем папки для каждого flavor’a:
New -> Folder -> Выбираем нужный тип папки:
Затем в build.gradle того модуля, где мы создали папку, должен автоматически вставиться следующий код (например, если мы выбрали hms):
android {
…
productFlavors {
...
}
sourceSets {
hms {
java {
srcDirs 'src/hms/java'
}
...
}
}
}
Теперь Gradle будет включать в сборку файлы, соответствующие выбранному flavor’у. Важно, чтобы файлы в этих директориях имели одинаковое название и лежали в пакетах с одним и тем же названием.
Пример. Мы используем Auth API. У нас будет абстракция — интерфейс AuthRepository, хранящийся в main/, а его имплементации для разных сервисов лежат в gms/ и hms/ директориях — тогда в сборку, например, для HMS, попадет именно имплементация с huawei сервисами.
Если проект многомодульный, то в каждом модуле необходимо прописать flavor’ы и при необходимости source sets. Код с flavor’ами можно вынести в отдельный файл.
Создадем .gradle файл в корневой папке проекта, назовем его flavors.gradle:
ext.flavorConfig = {
flavorDimensions 'services'
productFlavors {
hms {
dimension 'services'
ext.mApplicationIdSuffix = '.huawei'
}
gms {
dimension 'services'
}
}
productFlavors.all { flavor ->
if (flavor.hasProperty('mApplicationIdSuffix') && isApplicationProject()) {
flavor.applicationIdSuffix = flavor.mApplicationIdSuffix
}
}
}
def isApplicationProject() {
return
project.android.class.simpleName.startsWith('BaseAppModuleExtension')
}
Помимо самих flavor’ов, в экстеншене flavorConfig лежит код с циклом по flavor’ам — там будет определяться app модуль, которому присваивается applicationIdSuffix.
Затем в каждом модуле прописываем следующее:
apply from: "../flavors.gradle"
android {
buildTypes {
...
}
...
with flavorConfig
}
Для использования подходящих плагинов во время процесса компиляции можем добавлять такие if-else конструкции:
apply plugin: 'kotlin-kapt'
...
if(getGradle().getStartParameter().getTaskNames().toString().toLowerCase().contains("hms")) {
apply plugin: 'com.huawei.agconnect'
} else {
apply plugin: 'com.google.gms.google-services'
apply plugin: 'com.google.firebase.crashlytics'
}
...
Для каждого flavor’а мы можем включать dependencies, необходимые только ему. Перед implementation прописываем его название:
// Firebase
gmsImplementation platform('com.google.firebase:firebase-bom:26.1.0')
gmsImplementation 'com.google.firebase:firebase-crashlytics-ktx'
gmsImplementation 'com.google.firebase:firebase-analytics-ktx'
// Huawei services
hmsImplementation 'com.huawei.agconnect:agconnect-core:1.4.2.300'
hmsImplementation 'com.huawei.hms:push:5.0.4.302'
hmsImplementation 'com.huawei.hms:hwid:5.0.3.301'
Тестируем и отлаживаем приложение
После того, как мы внедрили Huawei сервисы в приложение, нам нужно протестировать его работоспособность.
У Huawei есть облачная платформа DigiX Lab, в которой представлены 2 сервиса.
С помощью сервиса облачного тестирования проверяем совместимость, стабильность, производительность и энергопотребление приложения на удаленных устройствах Huawei. Краткое описание тестов можно увидеть на картинке.
По окончании каждого теста доступен подробный отчет. Можно узнать о сбоях, ANR, утечках ресурсов, также увидеть загрузку процессора, использование памяти и многое другое. Плюсом будут доступны скриншоты, которые снимаются во время тестирования и журналы Logcat.
Тесты можно запускать либо с помощью плагина в Android Studio:
Либо в консоли AppGallery, выгрузив туда свой APK:
Служба облачной отладки решает проблему отсутствия реальных устройств Huawei. Предоставляется список удаленных устройств, а разовый сеанс работы до 2 часов. Сервис дает 24 часа работы бесплатно после подтверждения личности. Можно подавать заявки на продление срока действия неограниченное количество раз. Отладка также доступна из Android Studio и консоли.
Публикуем приложение в AppGallery
После внедрения сервисов и успешного тестирования приложения, мы готовы публиковаться в AppGallery.
1.Переходим в AppGallery Connect и заполняем данные:
2.Грузим иконку приложения и скриншоты. Есть возможность прикрепить видео.
3.Указываем страны/регионы для публикации и грузим APK приложения. Кроме того, нужно загрузить подпись приложения.
4.Отмечаем способ покупок в приложении и рейтинг.
5.Грузим политику конфиденциальности (обязательно) и предоставляем данные тестового аккаунта, если это необходимо. Указываем дату публикации.
6.Нажимаем кнопочку “Отправить на проверку” и ждем! Проверка по регламенту занимает около 3-5 дней.
Основные причины отказа в публикации
Политика конфиденциальности не соответствует стандарту
Отсутствует ссылка на политику конфиденциальности.
Ссылка на политику конфиденциальности недоступна.
Ссылка на политику конфиденциальности ведет на официальный сайт компании, на котором нет ссылки на политику конфиденциальности.
Указанный статус Гонконга и Макао не соответствует стандарту.Гонконг и Макао не могут быть указаны как страны на странице выбора региона. Китай очень трепетно относится к этому. Пример:
3.Приведены ссылки на сторонние магазины приложений
Функция для оценки и написания отзыва в приложении содержит ссылку на сторонние магазины приложений без ссылки на AppGallery
Итоги
Huawei выстроили удобный процесс адаптации приложения под свои сервисы. Максимально безболезненный переход к HMS, тестирование и отладка на удаленных устройствах, а также знакомый процесс публикации приложения значительно облегчат жизнь разработчику. И пока что в AppGallery не такая серьезная конкуренция как в других магазинах приложений, самое время присоединяться к Huawei сообществу.
Полезные ссылки
Подписывайтесь на наш Telegram-канал «Голос Технократии», где мы пишем о новостях из мира ИТ и высказываем свое мнение о важных событиях.
Astonesh
Маленький шаг, толчок к конкуренции
lunacyrcus
Это скорее шаг к захвату Huawei/AppGallery именно российского рынка (если говорить о нем, а не о каком-нибудь индийском или африканском к примеру, которые слегка далеко отсюда) и отсутствия конкуренции на нем, учитывая отношение российских властей к западным платформам. Т.к. ни Google ни Apple от этого в целом вроде особо не холодно и не жарко, на западном рынке все равно достаточного доверия к китайским платформам (а значит и их существенного распространения и конкуренции) не будет. Как и в самом Китае аналогично относятся к западным сервисам у себя.