Como adicionamos o suporte do Harmony OS ao aplicativo inDriver para Android

Tudo começou com o fato de o Departamento de Comércio dos EUA incluir a Huawei na lista de empresas com as quais é proibido realizar negócios com empresas americanas . A resposta da Huawei foi o sistema operacional Harmony OS para seus smartphones e a recusa em usar os serviços do Google. E para não perder parte do mercado, integramos seu suporte no inDriver. Embora a "integração do SO" pareça alta - nosso aplicativo, como qualquer outro escrito para Android, será executado no Harmony, mas, para todo o trabalho, é necessário substituir os serviços do Google por outros da Huawei.



No inDriver, usamos os serviços do Google para três propósitos:

  • Envio de notificações push;
  • Definição de localização;
  • Google maps.

Push Kit - enviar notificações push


Para iniciantes, a Huawei possui uma documentação muito boa . Mas, para começar rapidamente, basta usar o tutorial passo a passo .

Não vou recontar o que está escrito lá, vou me debruçar apenas em alguns pontos, pois são necessários comentários aqui.

Ativando o serviço

Você será solicitado a configurar o local de armazenamento de dados. Observe que você não pode alterá- lo mais tarde . O local não afeta a operação direta do envio, mas é apenas um local para armazenar e processar dados sobre eles.

Integrando o SDK do HMS

Depois de concluir a integração, você provavelmente terá problemas para criar o projeto. De qualquer forma, esse foi o caso em nosso servidor de compilação Ubuntu 16.04.5 LTS (GNU / Linux 4.4.0-174-generic x86_64), enquanto localmente no Mac mini (final de 2018, Mojave) funcionava bem. Você pode corrigir isso se adicionar

Execution failed for task ':app:processIndriverReleaseManifest'. org.gradle.api.GradleException: ERROR: no manifest file found



agcp {
   manifest false
}

no final do arquivo build.gradleno nível do aplicativo para o qual desativar o manifesto agcp. O problema aqui é que ele está agcpprocurando um arquivo de manifesto, mas não pode encontrá-lo e carregá-lo, o que provavelmente é um problema agconnect. Pelo menos foi assim que o suporte técnico oficial da Huawei nos respondeu.

Configurando o AndroidManifest.xml

Não sei por que, mas não diz sobre a inicialização automática, descrita na seção 2.6 Inicialização automática da documentação completa. Isso é necessário se você enviar um token para o servidor no método

public void onNewToken(String token) {}

Enviando mensagens: HUAWEI Push Kit Console.

Com ele, você pode verificar o funcionamento do push. Um fato interessante: se você selecionar no consoleType: Notification Message, elesonMessageReceived(RemoteMessage message)serão exibidos imediatamente no telefone,ignorando o manipulador.

Quando configurei o push, muitas vezes tive que usar o console. Ela e os envios enviados pelo servidor tiveram atrasos de até 30 minutos. Espero que tenham sido dificuldades temporárias com as quais os desenvolvedores já lidaram.

Agora, temos dois serviços push no telefone, mas como podemos organizar o trabalho conjunto deles? Primeiro, você precisa determinar quais serviços estão disponíveis no telefone. Em nosso lugar, decidimos que os serviços do Google seriam uma prioridade para nós. Suponha que, se os serviços do Google e da Huawei estiverem disponíveis no telefone, trabalhamos com o Google.

Enviamos o sinalizador de status dos serviços para o servidor com valores possíveis:

- 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
}

Dependendo do valor recebido, o servidor enviará notificações push para o serviço correspondente.

Organizar seu trabalho é uma questão de tecnologia. Eu fiz exatamente isso.

Manipulação de Eventos para FCM:

class AppFcmListenerService : FirebaseMessagingService() {
   private val cloudMessageHandler: CloudMessageHandler = GoogleMessageHandler(this)
   override fun onMessageReceived(message: RemoteMessage) {
       cloudMessageHandler.onMessageReceived(message)
   }
}

e HCM:

class AppHmsListenerService : HmsMessageService() {
   private val cloudMessageHandler: CloudMessageHandler = HuaweiMessageHandler(this)
   override fun onMessageReceived(message: RemoteMessage) {
       cloudMessageHandler.onMessageReceived(message)
   }
}

delegado à classe abstrata:

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> {
}

que possui duas implementações:

para FCM:

class FirebaseMessageHandler(override val context: Context) : CloudMessageHandler(context) {
   override fun getData(message: Any): Map<String, String> {
       return (message as RemoteMessage).data
   }
}

para HCM:

class HuaweiMessageHandler(override val context: Context) : CloudMessageHandler(context) {
   override fun getData(message: Any): Map<String, String> {
       return (message as RemoteMessage).dataOfMap
   }
}

As aulas da Huawei têm uma interface quase semelhante aos serviços do Google. Este "quase" Eu pessoalmente tenho manifesta no fato de que RemoteMessagefora com.google.firebase.messagingpara Map<String, String>que você deseja chamar RemoteMessage.getData(), e para RemoteMessagefora com.huawei.hms.push- getDataOfMap().

Kit de localização - determinação da localização


É possível lidar com locais LOCATION_SERVICE, disponíveis sem os serviços do Google e da Huawei. Porém, para o serviço de transporte de passageiros, a determinação precisa da localização é um parâmetro importante. Felizmente, as interfaces das classes do Kit de Localização não eram diferentes das de mesmo nome para os serviços do Google; portanto, seu aplicativo no código não era diferente. No entanto, os serviços da Huawei eram menos precisos em operação. Espero que este seja um problema temporário.
Também descobrimos o fato de que a solicitação de geolocalização é enviada pelo HMS Core, o que significa que, para uma operação correta, é necessário definir os direitos da geolocalização como "Sempre permitir".

localização

Substituindo o Google Maps


No CIS, usamos um mecanismo OSM com blocos 2GIS. No primeiro estágio da integração, decidimos não trabalhar com o Map Kit da HUAWEI, mas simplesmente usar o mecanismo OSM com blocos OSM. Tudo é simples.

Antes do lançamento


Aconselho a todos que prestem atenção às causas comuns de falha antes de iniciar seu aplicativo no AppGallery.

Por exemplo, a equipe de lançamento da Huawei nos informou das seguintes violações.

Apresentação não padronizada de Hong Kong e Macau A

China é escrupulosa quanto à soberania de suas regiões administrativas autônomas e pede que elas sejam chamadas de "região". Isso nos forçou a mudar todos os títulos que mencionam o país para mencionar o país ou região.



Informações sobre produtos concorrentes de terceiros nos detalhes do aplicativo

Não se esqueça de classificar o aplicativo enviando o usuário para a página na App Gallery, não na Google Play Store :)

Em geral, os serviços da Huawei são semelhantes aos serviços do Google e o suporte direto no código não causa dificuldades. As perguntas só podem ser do “ecossistema” da Huawei como um todo, mas podem ser atribuídas à sua juventude e, com uma alta probabilidade, tudo ficará melhor com o tempo.

All Articles