Все началось с того, что министерство торговли США включило Huawei в список компаний, с которыми запрещено вести бизнес американским компаниям. Ответом Huawei стала операционная система Harmony OS для своих смартфонов, и отказ использовать в ней сервисы Google. И чтобы не потерять часть рынка, мы интегрировали в inDriver ее поддержку. Хотя «интеграция OS» звучит громко – наше приложение, как и любое другое, написанное под Android, запустится на Harmony, но для полноценной работы необходимо заменить Google-сервисы на аналогичные Huawei.
В inDriver мы используем сервисы Google для 3 целей:
Для начала, у Huawei есть неплохая документация. Но для быстрого старта достаточно использовать step-by-step туториал.
Пересказывать то, что там написано не буду, остановлюсь лишь на некоторых пунктах, поскольку тут необходимы комментарии.
Enabling the Service
Вас попросят установить Data Storage Location. Учтите, что его потом нельзя изменить. Локация не влияет на непосредственную работу пушей, а является лишь местом хранения и обработки данных о них.
Integrating the HMS SDK
После того как вы закончите интеграцию, у вас вероятно будут проблемы со сборкой проекта. Во всяком случае, так было у нас на билд сервере Ubuntu 16.04.5 LTS (GNU/Linux 4.4.0-174-generic x86_64), при этом локально на рабочем Mac mini (late 2018, Mojave) все работало нормально.
Исправить это можно, если добавить
в конец файла
Configuring AndroidManifest.xml
Не знаю почему, но тут не сказано про автоматическую инициализацию, про которую написано в пункте 2.6 Automatic Initialization полной документации. Это необходимо, если вы отправляете токен на сервер в методе
Sending Messages: HUAWEI Push Kit Console.
С его помощью вы можете проверить работу пушей. Интересный факт: если вы в консоли выберете
Когда я настраивал работу пушей, мне часто приходилось пользоваться консолью. И у нее, и у пушей отправленных с сервера, были задержки вплоть до 30 минут. Надеюсь, это были временные трудности, с которыми разработчики уже справились.
Теперь у нас на телефоне есть два пуш-сервиса, но как их организовать их совместную работу? Для начала надо определить, какие сервисы доступны на телефоне. Мы у себя решили, что Google-сервисы будут для нас в приоритете. Допустим, если на телефоне доступны и Google-, и Huawei-сервисы, мы работаем с Google.
На сервер мы отправляем флаг состояния сервисов с возможными значениями:
В зависимости от полученного значения, сервер будет отправлять пуш-нотификации в соответствующий сервис.
Организовать их работу является делом техники. Я поступил просто.
Обработка событий для FCM:
и HCM:
делегируется абстрактному классу:
который имеет две имплементации:
для FCM:
для HCM:
Классы Huawei имеют почти схожий интерфейс с Google-сервисами. Это «почти» лично у меня проявилось в том, что у
Определением локации может заниматься
Также мы столкнулись с тем, что запрос геолокации идет через HMS Core, а значит для корректной работы необходимо выставить права для геолокации как «Разрешить всегда».
В СНГ мы использовали OSM движок с тайлами 2ГИС. На первом этапе интеграции мы решили не работать с Map Kit из HUAWEI, а просто использовать движок OSM с тайлами OSM. Все просто.
Советую всем обратить внимание на распространенные причины отказа перед запуском вашего приложения в AppGallery.
Например, релизная команда Huawei сообщила нам о следующих нарушениях.
Non-Standard Presentation of Hong Kong and Macau
Китай щепетильно относится к суверенитету своих автономных административных районов и просит их назвать «region». Это вынудило нас изменить все заголовки, где упоминается страна на упоминание страны или региона.
Information about Third-party Competing Products in App Details
Не забудьте для оценки приложения отправить пользователя на страницу в App Gallery, а не Google Play Store :)
В целом Huawei-сервисы аналогичны Google-сервисам и поддержка их непосредственно в коде не вызывает трудностей. Вопросы могут быть только к Huawei «экосистеме» в целом, но их можно списать на ее молодость и с большой вероятностью все будет лучше со временем.
В inDriver мы используем сервисы Google для 3 целей:
- Отправление пуш уведомлений;
- Определение локации;
- Google карты.
Push Kit – отправление push-уведомлений
Для начала, у Huawei есть неплохая документация. Но для быстрого старта достаточно использовать step-by-step туториал.
Пересказывать то, что там написано не буду, остановлюсь лишь на некоторых пунктах, поскольку тут необходимы комментарии.
Enabling the Service
Вас попросят установить Data Storage Location. Учтите, что его потом нельзя изменить. Локация не влияет на непосредственную работу пушей, а является лишь местом хранения и обработки данных о них.
Integrating the HMS SDK
После того как вы закончите интеграцию, у вас вероятно будут проблемы со сборкой проекта. Во всяком случае, так было у нас на билд сервере Ubuntu 16.04.5 LTS (GNU/Linux 4.4.0-174-generic x86_64), при этом локально на рабочем Mac mini (late 2018, Mojave) все работало нормально.
Execution failed for task ':app:processIndriverReleaseManifest'. org.gradle.api.GradleException: ERROR: no manifest file found
Исправить это можно, если добавить
agcp {
manifest false
}
в конец файла
build.gradle
на уровне приложения, чтобы отключить манифест для agcp
. Тут скорее проблема в том, что agcp
ищет файл-манифест, но не может его найти и загрузить, что вероятнее всего является проблемой agconnect
. По крайней мере, именно так нам ответила официальная техническая поддержка Huawei.Configuring AndroidManifest.xml
Не знаю почему, но тут не сказано про автоматическую инициализацию, про которую написано в пункте 2.6 Automatic Initialization полной документации. Это необходимо, если вы отправляете токен на сервер в методе
public void onNewToken(String token) {}
Sending Messages: HUAWEI Push Kit Console.
С его помощью вы можете проверить работу пушей. Интересный факт: если вы в консоли выберете
Type: Notification Message
, то они в обход обработчика onMessageReceived(RemoteMessage message)
сразу будут отображены на телефоне. Когда я настраивал работу пушей, мне часто приходилось пользоваться консолью. И у нее, и у пушей отправленных с сервера, были задержки вплоть до 30 минут. Надеюсь, это были временные трудности, с которыми разработчики уже справились.
Теперь у нас на телефоне есть два пуш-сервиса, но как их организовать их совместную работу? Для начала надо определить, какие сервисы доступны на телефоне. Мы у себя решили, что Google-сервисы будут для нас в приоритете. Допустим, если на телефоне доступны и Google-, и Huawei-сервисы, мы работаем с Google.
На сервер мы отправляем флаг состояния сервисов с возможными значениями:
- UNKNOWN
- GOOGLE
- HUAWEI
fun checkServices(context: Context): PlayServicesState {
val googleAPI = GoogleApiAvailability.getInstance()
when (googleAPI.isGooglePlayServicesAvailable(context)) {
ConnectionResult.SUCCESS,
ConnectionResult.SERVICE_MISSING,
ConnectionResult.SERVICE_VERSION_UPDATE_REQUIRED,
ConnectionResult.SERVICE_DISABLED -> return PlayServicesState.GOOGLE
}
val huaweiAPI = HuaweiApiAvailability.getInstance()
when (huaweiAPI.isHuaweiMobileNoticeAvailable(context)) {
com.huawei.hms.api.ConnectionResult.SUCCESS,
com.huawei.hms.api.ConnectionResult.SERVICE_MISSING,
com.huawei.hms.api.ConnectionResult.SERVICE_VERSION_UPDATE_REQUIRED,
com.huawei.hms.api.ConnectionResult.SERVICE_DISABLED -> return PlayServicesState.HUAWEI
}
return PlayServicesState.UNKNOWN
}
В зависимости от полученного значения, сервер будет отправлять пуш-нотификации в соответствующий сервис.
Организовать их работу является делом техники. Я поступил просто.
Обработка событий для FCM:
class AppFcmListenerService : FirebaseMessagingService() {
private val cloudMessageHandler: CloudMessageHandler = GoogleMessageHandler(this)
override fun onMessageReceived(message: RemoteMessage) {
cloudMessageHandler.onMessageReceived(message)
}
}
и HCM:
class AppHmsListenerService : HmsMessageService() {
private val cloudMessageHandler: CloudMessageHandler = HuaweiMessageHandler(this)
override fun onMessageReceived(message: RemoteMessage) {
cloudMessageHandler.onMessageReceived(message)
}
}
делегируется абстрактному классу:
abstract class CloudMessageHandler {
fun onMessageReceived(message: Any) {
val data = getData(message)
onMessageReceived(data)
}
private fun onMessageReceived(data: Map<String, String>) {
//непосредственная обработка пушей
}
abstract fun getData(message: Any) : Map<String, String> {
}
который имеет две имплементации:
для FCM:
class FirebaseMessageHandler(override val context: Context) : CloudMessageHandler(context) {
override fun getData(message: Any): Map<String, String> {
return (message as RemoteMessage).data
}
}
для HCM:
class HuaweiMessageHandler(override val context: Context) : CloudMessageHandler(context) {
override fun getData(message: Any): Map<String, String> {
return (message as RemoteMessage).dataOfMap
}
}
Классы Huawei имеют почти схожий интерфейс с Google-сервисами. Это «почти» лично у меня проявилось в том, что у
RemoteMessage
из com.google.firebase.messaging
для получения Map<String, String>
нужно вызвать RemoteMessage.getData()
, а для RemoteMessage
из com.huawei.hms.push
– getDataOfMap()
.Location Kit – определение локации
Определением локации может заниматься
LOCATION_SERVICE
, который доступен без Google и Huawei сервисов. Но для сервиса пассажирских перевозок точное определение локации является важным параметром. Благо, интерфейсы классов Location Kit ничем не отличались от одноименных для Google-сервисов, значит не отличалось и их применение в коде. Однако, сервисы Huawei оказались менее точными в работе. Надеюсь, это временная проблема.Также мы столкнулись с тем, что запрос геолокации идет через HMS Core, а значит для корректной работы необходимо выставить права для геолокации как «Разрешить всегда».
Замена Google карт
В СНГ мы использовали OSM движок с тайлами 2ГИС. На первом этапе интеграции мы решили не работать с Map Kit из HUAWEI, а просто использовать движок OSM с тайлами OSM. Все просто.
Перед релизом
Советую всем обратить внимание на распространенные причины отказа перед запуском вашего приложения в AppGallery.
Например, релизная команда Huawei сообщила нам о следующих нарушениях.
Non-Standard Presentation of Hong Kong and Macau
Китай щепетильно относится к суверенитету своих автономных административных районов и просит их назвать «region». Это вынудило нас изменить все заголовки, где упоминается страна на упоминание страны или региона.
Information about Third-party Competing Products in App Details
Не забудьте для оценки приложения отправить пользователя на страницу в App Gallery, а не Google Play Store :)
В целом Huawei-сервисы аналогичны Google-сервисам и поддержка их непосредственно в коде не вызывает трудностей. Вопросы могут быть только к Huawei «экосистеме» в целом, но их можно списать на ее молодость и с большой вероятностью все будет лучше со временем.
wholeman
Не подскажете, где можно детально почитать про эту Гармошку? То есть, не общие слова, что она микроядерная, распределённая, безопасная и т.д. и не про сервисы, как у Вас, а более подробно, в частности, про структуру, низкоуровневую организацию и т.д.
Ratel3 Автор
Не искал информации ?п?р?о? ?к?и?т?а?й?с?к?и?й? ?ф?о?р?к? ?а?н?д?р?о?и?д?а? саму ОС. Но в вашем случае я бы покопался в github.com/Awesome-HarmonyOS/HarmonyOS
wholeman
Там тоже ничего конкретного. По крайней мере не на китайском. Называть Гармошку (пусть и зачёркнуто) форком Андроида странно — в ней заявлена микроядерность, на которую робот никак не тянет ибо Linux.