Pull to refresh

Заглянуть в глаза дракону: 10 вопросов к Huawei Mobile Services

Reading time 10 min
Views 32K
Привет, Хабр! С мая 2019 года из-за санкций США мы остались без приложений и API для Android от Google. Из-за этого нашим устройствам грозило будущее без push-уведомлений, магазина и облачных сервисов.

Естественно, мы не опустили руки, а разработали и запустили платформу Huawei Mobile Services, которая заменила сервисы Google для наших устройств. Чтобы вы с ней познакомились и интегрировали в свои приложения, мы собрали 10 самых популярных вопросов, которые возникают у разработчиков, впервые столкнувшихся с HMS.

1. Про GMS я прекрасно все знаю, а что включает платформа HMS?
Платформа HMS полностью заменяет GMS, поэтому почти на каждый сервис Google у нас есть альтернатива: браузер, голосовой помощник, магазин приложений, облачные сервисы и инструменты для разработчиков.
Так как мы разрабатывали сервисы с нуля, то сразу разделили их на группы:
  • Сервисы AppGallery Connect позволяют загружать в облако Huawei темы, контент, распространять приложения и собирать статистику и отчеты об их использовании и падениях.
  • Сервисы HMS Core включают 14 инструментов, которые обеспечивают базовые функции телефона и взаимодействие с пользователями: push-сообщения, рекламу, авторизацию, аналитику и обмен сообщениями.
  • Инструменты для специальных возможностей, как и у Google, включают в себя платформы для работы с VR, AR и enterprise-разработки, например, для AI и IoT.
  • Инструменты для разработчиков — это собственный плагин для Android Studio (DevEco Studio) и сервисы облачного тестирования. Также для удобства разработки есть конвертер, который преобразует для работы с HMS код, связанный с GMS. Конвертер полностью поддерживает миграцию push-сообщений, рекламы и частично — кода для inapp-покупок.
Лучше всего начать знакомство с сервисов HMS Core, так как именно с ними будет взаимодействовать большинство приложений. С их помощью можно своевременно узнавать о сбоях в приложении, отслеживать продуктовые метрики и общаться с пользователями. Например, Push Kit отсылает push-сообщения пользователям:
2. Как мне быстро адаптировать свои приложения для работы с HMS и протестировать их без телефонов Huawei или Honor??
А вот тут мы постарались: сделали облачные сервисы тестирования и дебаггинга, которым у Google нет аналога, и конвертер для адаптации готового кода для нашей платформы.
Облачные сервисы для разработки и тестирования доступны на главном экране консоли сразу после регистрации на платформе и подтверждения доступа. С их помощью можно из веб-интерфейса запускать эмулятор на серверах Huawei, чтобы не покупать ферму устройств или мощные компьютеры.
Экран с сервисами можно конфигурировать, добавляя или удаляя элементы:
В Cloud testing прямо из консоли перед релизом запускаются автотесты и отслеживаются обнаруженные баги:
В Cloud Debugging можно получить доступ к эмуляторам. Для этого нужно с помощью поиска по региону, серии, версии андроида и версии EMUI выбрать целевой телефон:
Прямо из веб-интерфейса можно загрузить приложение и покликать по нему:
В эмуляторе можно даже поиграть в китайский аналог Minecraft. Правда, прежде чем добраться до игрового экрана, придется понажимать кучу кнопок на китайском языке:
Такой способ будет удобен для разработчиков тяжеловесных приложений, так как дает возможность проводить тесты на большом количестве устройств прямо из веб-консоли.
Еще одним удобным инструментом для быстрой адаптации приложений для нашей платформы является Huawei Core ToolKit plugin для Android Studio, который конвертирует код, работающий с GMS, под нашу платформу. Установить плагин можно прямо из встроенного магазина:
После установки в трее появится пункт HMS. Чтобы начать конвертацию, нужно выбрать New Conversion:
Перед конвертацией необходимо указать директорию для резервного копирования:
И подтвердить конвертацию:
В коде проекта можно вручную отследить каждое изменение и либо применить его, либо проигнорировать. Дополнительно после конвертации в директории проекта появится отдельный модуль с README. md, где можно будет посмотреть, что делает сконвертированный код.
3. Что с аутентификацией пользователя?
По аналогии с «Sign with Google» и «Sign with Apple» у нас есть свой сервис «Sign with HUAWEI». Он является частью Account Kit и работает со всеми пользовательскими устройствами Huawei и Honor:
Сам процесс авторизации стандартный, подробную инструкцию по интеграции можно найти на сайте или в Codelab.
4. С пользователем понятно, а как идентифицировать телефон?
Мы поддерживаем работу с Android id, а для верификации по номеру телефона в Account Kit у нас есть аналог SMSRetriever. Эта функция активируется на 5 минут командой:
val task = ReadSmsManager.start(this@MainActivity)
task.addOnCompleteListener {
    if (task.isSuccessful) {
        // The service is enabled successfully. Continue with the process.
        Toast.makeText(this, "ReadSms service has been enabled.", Toast.LENGTH_LONG).show()
    } else {
        Toast.makeText(this, "The service failed to be enabled.", Toast.LENGTH_LONG).show()
    }
}
Также должен быть включен Broadcast Receiver с фильтром на READ_SMS_BROADCAST_ACTION:
val intentFilter = IntentFilter(READ_SMS_BROADCAST_ACTION)
registerReceiver(MyBroadcastReceiver(), intentFilter)
Чтобы Account Kit увидел СМС, оно должно выглядеть так:
prefix_flag short message verification code is XXXXXX hash_value
prefix_flag — это префикс сообщения. Account Kit распознает <#>, [#] и невидимые Unicode символы, например, \u200b.
short message verification code is XXXXXX — текст для пользователя.
hash_value — хеш от имени пакета.
Пользователь получит сообщение «<#> Habratest: 458329 — Just test code qkASxAkMJOE».
5. В моем приложении есть реклама. Я могу ее показывать с помощью HMS?
Пока рекламная платформа доступна только для корпоративных аккаунтов, но скоро её смогут внедрить в свои приложения все разработчики. Для этого у нас уже готов свой Ads Kit. В нем можно создавать баннеры и интегрировать их в приложение. Баннеры представляют собой объекты View в Android. Добавить их можно так:
<com.huawei.hms.ads.banner.BannerView
   android:id="@+id/hw_banner_view"
   android:layout_width="match_parent"
   android:layout_height="wrap_content"
   hwads:adId="testw6vs28auh3"
   hwads:bannerSize="BANNER_SIZE_360_57"/>
Кроме банерной рекламы, есть Native Ads, которые встраиваются через верстку:
<com.huawei.hms.ads.nativead.NativeView xmlns:android="http://schemas.android.com/apk/res/android"
   android:orientation="vertical"
   android:layout_width="match_parent"
   android:layout_height="wrap_content"
   ... >
   <RelativeLayout
       ... >
       <com.huawei.hms.ads.nativead.MediaView
           android:id="@+id/ad_media"
           ... />
       <RelativeLayout
           ... >
           <TextView
               android:id="@+id/ad_title"
               ...  />
           // Other assets.
           ...
       </RelativeLayout>
       // Other assets.
       ...
   </RelativeLayout>
</com.huawei.hms.ads.nativead.NativeView>
Также есть Rewarded Ads, Interstitial Ads и реклама на сплеш-скрине — Splash Ads, обо всем этом можно прочитать в документации:
Платформа позволяет зарабатывать на встроенных покупках. Чтобы создать этот инструмент, в консоли разработчика необходимо добавить продукт:
И в самом приложении уже добавить код покупки:
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
    @Override
    public void onItemClick(AdapterView<?> adapterView, View view, int pos, long l) {
        String productId = (String) products.get(pos).get(DemoActivity.this.item_productId);
        gotoPay(DemoActivity.this, productId, IapClient.PriceType.INAPP_CONSUMABLE);
    }
});
Если приложение использует свою систему оплаты, то будет полезно прочитать про Wallet Kit. Этот SDK позволяет хранить безопасно данные банковских, подарочных и скидочных карт, купонов и билетов на транспорт или мероприятия. Включить функции Wallet Kit также можно из консоли разработчика:
6. А приложение сможет одновременно работать и с HMS, и с GMS?
Да, проблем не будет. Подключение двух сервисов в приложении ничем не отличается от установки одной библиотеки. Единственное, лучше проверять и инициализировать библиотеки в зависимости от поддержки.
Для AppGallery не обязательно делать отдельную сборку. Можно загружать ту же сборку, что и в остальные маркеты, и, например, в рантайме выбирать, инициализировать ли HMS/GMS. Конечно, лучше разделить эти сборки, но концептуально у разработчика есть свобода выбора.
После добавлении библиотеки в семпл APK «прибавляет в весе» всего ~500кб. Для сравнения, GMS «съедают» чуть больше — примерно 600кб.
7. Тогда встает вопрос о работе на «родном» Android от Google. Как будет функционировать приложение с Push Kit от Huawei без HMS на устройстве?
Если на устройстве без HMS запустить HMS библиотеку, ничего страшного не случится. Например, если инициализировать Push Kit, в лог посыпятся ошибки вида Failed to find HMS apk, а пользователя встретит экран с просьбой установить HMS:
Лучше убирать запросы к HMS под if’ы. Например, так можно проверить, есть ли на устройстве HMS:
fun isHmsAvailable(context: Context): Boolean {
    val result =
         HuaweiApiAvailability.getInstance().isHuaweiMobileServicesAvailable(context)
    val isAvailable = ConnectionResult.SUCCESS == result
    Log.i(TAG, "isHmsAvailable: " + isAvailable);
    return isAvailable;
}
Обратная ситуация (когда GMS нет) тоже возможна:
fun isGmsAvailable(context: Context): Boolean {
   val result =
       GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(context)
   val isAvailable = ConnectionResult.SUCCESS == result
   Log.i(TAG, "isGmsAvailable: " + isAvailable);
   return isAvailable;
}
8. Давайте поговорим про аналоги сервисов Google. Чем можно заменить firebase database?
На данный момент существует сервис, очень похожий на Firebase Database — Cloud DB, который находится в Beta-доступе:
Импортировать данные можно так:
CloudDBZoneTask<Integer> upsertTask = mCloudDBZone.executeUpsert(bookInfo);
if (mUiCallBack == null) {
    return;
}
upsertTask.addOnSuccessListener(new OnSuccessListener<Integer>() {
   	@Override
	public void onSuccess(Integer cloudDBZoneResult) {
       Log.w(TAG, "upsert " + cloudDBZoneResult + " records");
    }
}).addOnFailureListener(new OnFailureListener() {
    @Override
    public void onFailure(Exception e) {
        mUiCallBack.updateUiOnError("Insert book info failed");
    }
});
Экспортировать чуть сложнее из-за особенности облачной базы данных. После регистрации слушателя устройство будет оповещено об изменении данных на сервере и обновит их у себя локально:
private OnSnapshotListener<BookInfo> mSnapshotListener = new OnSnapshotListener<BookInfo>() {
   @Override
   public void onSnapshot(CloudDBZoneSnapshot<BookInfo> cloudDBZoneSnapshot, AGConnectCloudDBException e) {
       if (e != null) {
           Log.w(TAG, "onSnapshot: " + e.getMessage());
           return;
       }
       CloudDBZoneObjectList<BookInfo> snapshotObjects = cloudDBZoneSnapshot.getSnapshotObjects();
       List<BookInfo> bookInfos = new ArrayList<>();
...
9. Ок, заинтересовали. А что у вас с магазином приложений? Как идет ревью, можно ли добавлять бета-тестировщиков в Huawei AppGallery?
Правила публикации не сильно отличаются от правил в Google Play и Apple AppStore, а сама проверка приложения занимает два рабочих дня. Правда, для рынка КНР потребуются дополнительные документы, такие как сертификат об авторском праве.
Функция бета-теста в AppGallery есть. Можно настроить ранний доступ или ограничивать установку приложения, например, по моделям Huawei/Honor:
Также для удобного релиза приложений Huawei AppGallery поддерживает загрузку App Bundle и Split APK:
10. Можно ли настроить автодеплой в Huawei AppGallery?
Да, это легко можно сделать через Publishing API AppGallery. Для начала нужно получить Upload URL:
HttpGet get = new HttpGet("https://connect-api.cloud.huawei.com/api/publish/v2/upload-url?appId=" + appId + "&suffix=" + suffix); 
get.setHeader("Authorization", "Bearer " + token); 
get.setHeader("client_id", clientId); 
HttpEntity reqEntity = MultipartEntityBuilder.create() 
        .addPart("file", bin) 
        .addTextBody("authCode", authCode) // Obtain the authentication code. 
        .addTextBody("fileCount", "1") 
        .addTextBody("parseType","1") 
        .build(); 
HttpPut put = new HttpPut(domain + "/publish/v2/app-info?appId=" + appId); 
put.setHeader("Authorization", "Bearer " + token); 
put.setHeader("client_id", clientId); 
JSONObject keyString = new JSONObject(); 
//Request Body 
keyString.put("defaultLang", "zh-CN"); 
keyString.put("isFree", 0); 
keyString.put("childType", 15); 
keyString.put("grandChildType", 10043); 
Уфф, вроде ответили. Правда, в процессе работы вопросов будет гораздо больше, но вы всегда можете найти документацию по нашим сервисам на официальном портале. Там же можно получить техническую поддержку, посмотреть обучающие видео и зарегистрировать учетную запись разработчика.


Хабр, 谢谢您的关注!
Tags:
Hubs:
+51
Comments 28
Comments Comments 28