Google Play Instantâneo. Refatoração ao longo da vida

Quando você se envolve no Programa de Acesso Antecipado, nunca sabe com antecedência o que acontecerá no final. Obviamente, você espera que a tecnologia decole e seu aplicativo fique à frente do mercado e receba uma parte do PR no Google I / O. E é uma boa motivação para ler códigos-fonte em vez de documentação no estágio inicial, que, além disso, deve ser baixado do arquivo secreto.

No AppsConf, Yevgeny Saturov mostrou a que participação no Acesso Antecipado poderia levar como exemplo de desenvolvimento de um aplicativo com inicialização instantânea, explicando todos os recursos do Google Play Instant ao longo do caminho. Ao decifrar o relatório, descobriremos de onde vieram os pacotes de aplicativos para Android e o que o Dynamic Delivery tem a ver com isso, familiarizar-se com os novos plug-ins Gradle e aprender a lidar com as surpresas que os desenvolvedores do SDK nos prepararam.


Sobre o palestrante: Evgeny Saturov ( saturovv ) trabalha para a Surf, uma empresa especializada no desenvolvimento personalizado de Android e iOS e, mais recentemente, no Flutter. Eugene Flutter é um entusiasta e fundador do FlutterDevPodcast.

Uma breve excursão pela história



Há dois anos, um cara maravilhoso veio até nós na Surf e disse: “Temos uma tecnologia que até agora poucas pessoas conhecem. E você tem clientes e casos interessantes. Vamos fornecer a nossa tecnologia, você a integra em algum lugar e obtém uma simbiose interessante. Promoveremos isso no Google I / O e todos ficarão bem. ”

De fato, trabalhar com o Programa de Acesso Antecipado é uma porcaria . Você precisa trabalhar com código bruto, o qual, é claro, nem sempre funciona como pretendido e descrito. No nosso caso:

  • Todos os artefatos foram entregues na forma de um arquivo ZIP, que precisava ser baixado a cada poucos dias de um armazenamento super secreto e atualizado em uma máquina local apenas manualmente.
  • Você pode trabalhar apenas no "canário".
  • Quase não existe documentação, apenas Google Docs não estruturado disperso, mais frequentemente semelhante ao fluxo de pensamentos dos desenvolvedores.
  • A implantação na comida, é claro, é impossível - isso só é possível depois que a tecnologia chega ao público. Ou seja, toda a implantação é apenas na faixa alfa.
  • É provável que, após um lançamento público, o SDK tenha sido completamente reescrito sem suporte à compatibilidade com versões anteriores. Você obtém interfaces e APIs completamente diferentes - é necessário refazer tudo novamente.

Este é um breve resumo de como participamos do Programa de Acesso Antecipado.

Tudo isso se tornou possível graças ao nosso parceiro regular - a empresa Labyrinth - a maior loja on-line de livros e artigos de papelaria da Rússia. Eles se juntaram ao projeto, nem mesmo tendo certeza se haveria algum benefício no final. E o fato de que em 2017 o Surf, como estúdio, fazia parte do Programa de Agência Certificada do Google. Infelizmente, o programa foi fechado este ano.

Aplicativos instantâneos do Android


Em 2017, para que o aplicativo fosse executado sem instalação, ele precisou ser serrado nos módulos corretamente.



Temos novos plugins Gradle que geram os artefatos correspondentes:

  • Instant App Module - um plugin de aplicativo que gerou um arquivo ZIP com um APK, um para cada módulo de recurso do aplicativo;
  • Módulo de aplicativo instalável - APK gerado.

Uma hierarquia de dois níveis dos módulos de recursos apareceu. Sempre poderia haver apenas um módulo de recurso básico e continha todo o código básico disponível para todos os recursos, recursos, dependências etc. O módulo de recursos de nível superior continha a implementação de telas específicas.

Mas foi longo e caro por vários motivos:

  • A estrutura modular rígida em si é uma grande limitação. É difícil imaginar que qualquer empresa grande transformará seu aplicativo em desenvolvimento e que funcione perfeitamente em uma pilha de módulos para fumar ao longo dos anos apenas para apoiar uma nova tecnologia que ainda é desconhecida, se ela será ou não decolada.
  • Restrição rigorosa ao tamanho da montagem, ou seja, um recurso não deve exceder 4 MB. Esse é um limite objetivamente pequeno e, às vezes, completamente inatingível, por exemplo, devido a dependências pesadas ou algo assim.
  • Certifique-se de usar o AppLinks, porque esta é a única maneira de acessar o Instant App. O usuário clicou no link no correio, no messenger, nos resultados da pesquisa e chegou à sua tela através da interceptação do link.
  • Finalmente, um grande número de limitações técnicas. No começo, era impossível usar o NDK. Você não pode enviar notificações por push, receber dados confidenciais, alterar configurações do dispositivo e iniciar processos em segundo plano. Não foi possível usar serviços, receptores de transmissão e provedores de conteúdo. Somente atividade.

A principal missão do Instant App é apenas uma demonstração da interface do usuário e nada mais. A refatoração foi muito dolorosa e, portanto, essa história quase nunca é encontrada na produção.

Mas, para ser justo, a implementação do Instant App no ​​Labirinto deu um aumento de 5% nas compras por meio do cliente móvel.

2019. Google Play Instantâneo


Dois anos se passaram, no quintal de 2019 - o Instant Apps ainda existe, mas não como uma tecnologia independente. Ainda é muito raro na produção, não o procurei de propósito, mas conheço apenas alguns exemplos: Sports.ru, Vimeo. É improvável que o Google estivesse contando com esse resultado ao anunciar essa tecnologia.

Agora, o Instant App é chamado de maneira diferente - Google Play Instant. A mudança de nome ajudou a eliminar a documentação irrelevante. Se você vir o Android Instant App, fica claro imediatamente que isso não é mais relevante.

Além do nome, tudo mudou, incluindo a estrutura modular. As demandas se tornaram mais leais . A tecnologia se integra de maneira completamente diferente ao projeto e não requer uma refatoração tão dolorosa, o que certamente é bom.
Mas o que é menos óbvio e, na minha opinião, muito mais importante é que essa tecnologia, permanecendo muito nicho e rara, tornou-se a progenitora de toda uma família de tecnologias da qual agora faz parte.
Inicialmente, o Google posicionou o Instant App como uma tecnologia que atrai pessoas para os negócios, não aplicativos. Havia uma diretriz de design que proibia aplicativos de pouso com um único botão "Baixar aplicativo completo". Mas outro problema fundamental foi resolvido de lado e suspeito que isso tenha acontecido por acidente.

Em fevereiro deste ano, o notável dispositivo Samsung Galaxy S10 + com 1 TB de memória a bordo viu a luz. Basta pensar nisso - um terabyte! Por que você precisa tanto ?!

Segundo as estatísticas oficiais do Google, nos últimos 7 anos, o tamanho médio dos APKs aumentou 5,5 vezes.



O tamanho da construção é realmente importante, a pesquisa nessas estatísticas mostra:

  • todos os 6 Mb adicionais de montagem reduzem a conversão na instalação em 1%;
  • 70% dos usuários verificam o tamanho do aplicativo antes de fazer o download;
  • 50% dos usuários estão interessados ​​em quanto espaço o aplicativo ocupará no dispositivo após a instalação.

Isso é ainda mais importante se seu público-alvo for maior de idade ou com renda não muito alta ou se forem mercados emergentes.

Estes últimos são cada vez mais difíceis de ignorar, porque em 2018 foi a Índia que mostrou um aumento incrível nas instalações.



Observe que existem muito poucos iOS e o número total de instalações de aplicativos Android excede o número combinado nos EUA, Brasil e Indonésia.

Agora está claro que problema pode ser resolvido com o Google Play Instantâneo. Você pode acessar termos incompreensíveis.

Pacote de aplicativos para Android


Pacote de aplicativos para Android - um novo formato para publicar aplicativos no Google Play. Por dentro, nem tudo é muito diferente do APK: todos os mesmos arquivos dex, manifesto, recursos, ativos etc. etc. Mas também há metadados, que não chegam ao dispositivo do usuário.



Os metadados são representados por três arquivos: resources.pb, assets.pb, native.pb. De fato, são tabelas de correspondência de recursos que estão nas configurações de montagem e configuração dos dispositivos.

Entrega dinâmica para Android


Todo mundo sabe sobre a existência do App Signing pelo Google Play. Mas nem todo mundo está pronto para armazenar a chave de lançamento do aplicativo no Google Play, porque não haverá como voltar atrás. Sair da assinatura do aplicativo pelo Google Play é impossível.

Depois de fornecer a chave de liberação para o Google Play, você nunca poderá assinar seu aplicativo como antes, do seu lado. Mas, em troca disso, você pode aproveitar ao máximo o Android App Bundle como um formato. E o processo de assinatura da montagem agora será um pouco diferente.



Você ainda assinará a montagem antes do lançamento no Google Play, mas assinará com a chave de upload, que não é exclusiva. Ele pode ser recuperado do console, relançado se estiver comprometido ou perdido. Você entrega sua chave de liberação ao console e se despede - o Google agora assinará a montagem e promete que manterá sua chave em segurança.

No entanto, se você não fornecer a chave de liberação para o Google Play, não poderá usar nada no seu projeto que seja discutido mais adiante. O Google aperta os parafusos, e até o Instant App, sem revelar a chave, falhará na implantação.

Na verdade, isso não é nada engraçado, porque as pessoas que compraram a promoção Instant App e entraram na história toda refatoraram seus aplicativos, mas, por algum motivo, não podem fornecer sua chave para o Google Play (ou o departamento de segurança é categoricamente contra ou por outras razões objetivas) se viram em uma situação em que não podem mais apoiar essa decisão. Centenas de horas de trabalho foram realmente jogadas no lixo.

2014. Suporte para Split APK aparece no Android Lollipop


Como hoje somos nostálgicos, voltaremos ainda mais ao passado - em 2014.

Ainda me lembro de como no meu NEXUS 5, o melhor celular do mundo, a montagem do Android Lollipop chegou com um incrível design de material que parecia apenas bombardeio. Mas houve mudanças que passaram despercebidas por muitos - este é o suporte para o APK Split.

Dividir APK - um mecanismo que permite dividir o aplicativo em pequenos APKs e, instalando em um dispositivo, faça com que eles se comportem como um único aplicativo.

Lembre-se disso e siga em frente.

A Entrega dinâmica do Android é um novo formato de distribuição de aplicativos no Google Play.



Costumávamos ter um APK, agora o pacote de aplicativos para Android está aparecendo, até agora como uma alternativa. A AAB atua como um gerador-incubador desses APKs muito divididos. A AAB lança o coque do APK, que pode ser usado como aplicativo regular, instalando-o em paralelo.

Vamos ver que tipo de APK é esse.



No mínimo, esse é o APK básico, que desempenha o mesmo papel do Instant App: é o código básico, os recursos básicos e a lógica de negócios que são vasculhados entre todos os recursos.

Também aparecem:

  • APKs, em nome dos quais há suspeitas semelhantes aos prefixos de modificadores de recursos gráficos (a linha superior do diagrama).
  • Outra família de APKs nos lembra arquiteturas de processador.
  • APKs de localização.

Cerca de dois anos atrás, quando os gráficos vetoriais não eram tão difundidos, muitos aplicativos continham principalmente recursos de varredura, que foram cortados em diferentes densidades de pixel nas telas. A assembléia pode se tornar bastante pesada. Os usuários baixaram todos esses recursos e a maioria deles foi armazenada no dispositivo com peso morto.

Agora, esse mecanismo permite que o usuário receba apenas o conjunto de recursos necessários especificamente para o seu dispositivo. Uma pessoa acessa o Google Play, seleciona o aplicativo, o Google Play entende as características do dispositivo do usuário e fornece o conjunto de APKs divididos necessários - um APK de cada categoria.

Tipos de entrega dinâmica APK:

  • Um e apenas um APK base.
  • O APK de configuração tem no máximo três tipos: res * x, recursos * y, lib * z. Aqui: x é o número de modificadores de recursos usados; y é o número de tipos de arquiteturas usadas; z é o número de localizações de idiomas. Se, por exemplo, o projeto não usar código nativo e bibliotecas nativas, não haverá categoria associada ao código nativo e dois APKs permanecerão.
  • Recurso dinâmico ilimitado APK.

O recurso dinâmico APK será discutido com mais detalhes abaixo. Mas primeiro, vamos nos despedir do bloco de Split.

Adeus Split


Você pode argumentar que anteriormente você poderia fazer algo semelhante, gerando manualmente um monte de APKs com apenas o conjunto certo de recursos e, em seguida, tudo foi implantado manualmente no Google Play.

android { splits { density { enable true exclude "ldpi", "xxhdpi", "xxxhdpi" compatibleScreens 'small', 'normal', 'large', 'xlarge' } } } 

Esse empreendimento em si é bastante duvidoso, e agora tudo isso é simplesmente ignorado. Se você criar o Android App Bundle, um bloco Bundle será exibido, o que permitirá que você desabilite manualmente a divisão do projeto em uma das categorias.

 android { bundle { language { enableSplit = false } density { enableSplit = true } abi { enableSplit = true } } } 

Você pode especificar que o aplicativo ofereça suporte, por exemplo, apenas russo ou apenas inglês e pular esta etapa durante a montagem.

Os mais atentos, provavelmente, agora estão pensando no que fazer com os pré-pirulitos. Somente no Android 5 apareceu suporte para o APK Split. De alguma forma, precisamos sair dessa situação, porque o SDK mínimo não é de todo o 21º.

Para os pré-pirulitos, a situação é bastante desajeitada, mas apenas possível. O Google Play coleta vários APKs para pré-pirulitos, que incluem todos os tipos de combinações de APKs de configuração. Existe apenas um APK, mas há muitas opções.

O pacote de aplicativos para Android muda nossa vida


E muito significativo. Em primeiro lugar, pode ser muito mais fácil criar um projeto, especialmente se você costumava criar manualmente o APK Split. Mas, de acordo com minhas observações, não existem muitas pessoas assim.

Em segundo lugar, você não corre mais o risco de perder ou comprometer a chave de lançamento. Não haverá grande tragédia; se você perder sua chave de upload, poderá recuperá-la e reeditá-la.

Não apontaremos o dedo - no topo do Google Play russo, há aplicativos que possuem chaves de lançamento por um longo tempo no w3bsit3-dns.com, todos os assemblies personalizados são assinados com uma chave de lançamento e não há nada a ser feito nos próximos cinco anos. Resta aguardar a transição para a assinatura V3, que apareceu com apenas 28 API.
A vantagem indiscutível do Android App Bundle: os usuários param de gastar tráfego e espaço em disco em recursos que não precisam. Isso aprimora muito a retenção do aplicativo.
Mas se você tiver todos os gráficos do vetor, duas localizações e nenhuma biblioteca nativa, o benefício será microscópico.

Módulo de Recurso Dinâmico


O Dynamic Feature Module é um módulo funcional que não é fornecido durante a instalação do aplicativo, mas é baixado do Google Play e instalado somente sob demanda.

Esses módulos estão a par do APK básico.



É importante que cada um desses módulos de recursos também contenha um conjunto de APKs divididos de configuração. Assim, o número total de APKs pode aumentar além da medida. Mas isso não é da sua conta, o Google Play está fazendo isso.

Aplicativos para módulos de recursos dinâmicos:


Recursos usados ​​por uma porcentagem muito pequena do público , mas ainda assim importantes para o seu produto. Por exemplo, este é um aplicativo de entretenimento de conteúdo e 95% de seus usuários consomem conteúdo. Mas há uma porcentagem muito pequena de editores que geram conteúdo. Para eles, existe um editor de vídeo interessante que realmente pesa muito, funciona incrivelmente legal. Então não faz sentido ponderar a montagem para todos e todos, você pode colocar esse recurso no Dynamic Feature Module e fornecê-lo apenas para aqueles que precisam, fazendo o download mais tarde.

Recursos pesados ​​que não estão relacionados ao cenário de uso do aplicativo principal. Por exemplo, navegação de AR em um serviço de mapa. Qualquer recurso de AR é o máximo para colocá-lo no Dynamic Feature Module.

Recursos que devem estar disponíveis para os usuários sem instalar o aplicativo em si (por exemplo, selecionando um produto no catálogo e fazendo um pedido). É verdade que isso é algo muito suspeito que lembra tudo.
O Android Instant Apps agora é o Módulo de recurso dinâmico ativado por instante.
Assim, verifica-se que existem dois tipos de módulos de recursos dinâmicos:

  • Módulos de recurso dinâmico comuns são módulos de função que são baixados e instalados em um dispositivo separadamente do aplicativo principal. Eles moram lá enquanto o aplicativo em si vive. Até você excluí-lo, o Dynamic Feature Module será.
  • Módulos de recursos dinâmicos com ativação instantânea - módulos de função disponíveis para execução sem instalação no dispositivo. Este módulo vive por um tempo limitado.

O segundo tipo de aplicativos no Google Play pode ser distinguido pela presença do botão Try. Quando você clica nele, o URL padrão é substituído e você pode ver como o aplicativo se parece pelo menos como um exemplo de um recurso principal.

Isso geralmente pode ser encontrado na seção com jogos. Isso é conveniente e ainda mais aplicável do que aos aplicativos, porque você pode fazer o download de um pequeno pedaço do jogo como demonstração e ver do que se trata, se vale a pena gastar seu tráfego e tempo.

Estrutura modular


Eu já disse que a estrutura modular foi simplificada. Vamos ver como.

Inicialmente, tínhamos uma estrutura bastante monstruosa. Entre outras coisas, ele tinha módulos vazios, por exemplo, o Instant App Module estava sempre vazio, não tinha código, recursos, mas apenas o arquivo build.gradle e foi isso.

Os desenvolvedores pensaram, por que, então, produzem módulos extras apenas para coletar artefatos de um determinado tipo. E eles serraram, e a funcionalidade foi transferida para o App Module.

Mas eles foram ainda mais longe e pensaram - por que precisamos do Módulo de Recursos Base? Existem alguns problemas dele, porque inicializamos tudo lá, e o ID do aplicativo é diferente. As muletas vêm daqui, por exemplo, transferindo o ID do aplicativo do Módulo de aplicativo para o Módulo de recursos base e substituindo-o como um ID de aplicativo real do aplicativo, para que tudo seja rastreado em Crashlytics, etc.

Como resultado, ficou claro que sim.



Eles deixaram o App Module, anexado em cima dele Feature Modules - e pronto!

Não transmita minhas emoções quando descobri isso. Os caras do grande palco disseram que têm uma tecnologia interessante: "Vamos todos cortar aplicativos nessa estrutura!" Mas isso não funciona por 5 minutos, mas funciona com grandes consequências.

Em 2017, ter uma aplicação monolítica ainda não era uma vergonha. O labirinto era assim, então nem chegara ao lançamento público, mas estava na versão beta. No momento em que nos envolvemos no Programa de Acesso Antecipado, já havia cerca de 90 telas lá. Passamos mais dois meses para refatorar, testar e garantir que tudo realmente funcione.

E depois disso eles dizem: "Somos espertos demais, isso pode ser feito muito mais fácil" .

Mas voltando à prosa.

Configuração Gradle


Para oferecer suporte à nova configuração, primeiro precisamos listar todos os Módulos de recurso dinâmico no arquivo build.gradle do módulo de aplicativo no bloco Android:

 //  build.gradle app- android { dynamicFeatures = [":dynamic_feature", M:dynamic_feature2M] } 

Depois disso, no arquivo build.gradle de cada módulo de recurso dinâmico, escreva a dependência no módulo de aplicativo:

 //  build.gradle  dynamic feature- dependencies { implementation project(':app') } 

Em princípio, nada complicado. Mas há também uma configuração de manifestos.

Configuração de manifesto


No manifesto do módulo do aplicativo, podemos definir o sinalizador true para indicar que há pelo menos um recurso ativado por instante neste aplicativo:

 //   app- <dist:module dist:instant="true|false" /> 

Se esse sinalizador não estiver presente, não será possível incorporar-se à faixa correspondente no Google Play.

Além disso, há também uma configuração de manifesto para cada módulo de recurso dinâmico individualmente, na qual há mais configurações:

 //    dynamic feature- <dist:module dist:instant="true|false" // Instant-Enabled  dist:onDemand="false|true" // ,         dist:title="@string/feature_modulejnstall_name"> //   <dist:fusing dist:include="true |false" /> //,      APK  preLollipop </dist:module> 

Os dois primeiros sinalizadores são um pouco mutuamente exclusivos, porque onDemand é o recurso básico usual e instant é o mesmo recurso Instalável.

Título - o nome técnico do módulo, de acordo com o qual posteriormente, depois de codificado em nosso aplicativo, bombearemos este módulo do Google Play.

O parâmetro include é um parâmetro para preLollipops. Se você configurá-lo como falso, os usuários do preLollipops nunca verão esse recurso e não poderão usá-lo.

Configuração de projetos Gradle


A vida do plug-in instantapp e do recurso foi bastante curta, mas vibrante. Eles duraram menos de dois anos. Desde março deste ano, eles não são mais suportados.

Agora, existe apenas um módulo de recurso dinâmico que usamos:
 apply plugin: 'com.android.dynamic-feature' 

Configuração do projeto apenas no módulo de aplicativo


Um ponto importante: todas as configurações relacionadas à assinatura (configuração de assinatura), montagem (configuração ProGuard), versionCode e versionName precisam ser feitas apenas no módulo de aplicativo build.gradle.
Caso contrário, eles serão ignorados. Evite especificar qualquer um desses blocos de configuração nos arquivos build.gradle dos módulos de recursos dinâmicos.

Google play instantâneo


Agora temos o seguinte.

Os requisitos para a estrutura modular foram simplificados o máximo possível. Esta é realmente uma boa notícia para aqueles que ainda não se envolveram. Agora você pode tentar, mesmo se tiver um aplicativo com sua própria estrutura. Isso não afetará você, basta conectar o módulo na parte superior e tudo funcionará bem.

Restrições no tamanho da montagem tornaram-se mais leais. Se antes tinha 4 MB, agora:

  • Os módulos de recursos dinâmicos geralmente não têm tamanho limitado;
  • Os módulos de recursos dinâmicos com ativação instantânea podem levar até 10 MB.

Mas agora há uma escala progressiva.



Se o seu recurso:

  • mais de 10 MB, então me desculpe;
  • de 4 a 10 Mb - acessível pelo botão "Experimentar" no Google Play e pronto;
  • menos de 4 MB - todos os meios de atrair usuários para o módulo Instant-Enabled estão disponíveis (iniciados pela publicidade, por link, por mensagens etc.).

Um mecanismo para carregar módulos apareceu - Play Core API. Poucas pessoas sabem que o Instant App costumava ser instalado através do Chrome.

 @Override public boolean maybeLaunchInstantApp(Tab tab, String url, String referrerUrl, boolean isIncomingRedirect) { if (tab == null || tab.getWebContents() == null) return false; InstantAppsHandler handler = InstantAppsHandler.getInstance(); Intent intent = tab.getTabRedirectHandler() != null ? tab.getTabRedirectHandler().getInitialIntent() : null; if (isIncomingRedirect && intent != null && intent.getAction() == Intent.ACTION_VIEW) { Intent resolvedIntent = new Intent(intent); resolvedIntent.setData(Uri.parse(url)); return handler.handleIncomingIntent(getAvailableContext(), resolvedIntent, ChromeLauncherActivity.isCustomTabIntent(resolvedIntent)); } else { ... } return false; } 

Este é um código real do Chrome para Android, que interceptou o link para o seu Instant App, foi para o Google Play e substituiu o Instant Apps a partir daí. Se o Instant App foi detectado, ele abriu a atividade, de onde o Instant App foi iniciado.

Portanto, houve enormes problemas ao rolar esse recurso. Com a Samsung, essa é uma história completamente diferente, suspeito que o navegador interno tenha um pouco mais de privilégios que o Chrome. O Instant App não funcionou lá até o último.

O Play Core Library permite que você esqueça os problemas de entrega. Você apenas o conecta como um pacote:

 implementation 'com.google.android.play:core:1.4.0' 

E faça o download dos módulos de recursos necessários no Google Play.

A biblioteca possui uma sintaxe bastante funcional que permite baixar módulos um de cada vez:

 val splitInstallManager = SplitInstallManagerFactory.create(context) 

Ou imediatamente um pacote de vários:

 val request = SplitInstallRequest .newBuilder() .addModule("feature1") .addModule("feature2") .build() 

Desligue o ouvinte:

 splitInstallManager .startInstall(request) .addOnSuccessListener { sessionId -> ... } .addOnFailureListener { exception -> ... } 


Mostre isso na interface do usuário e reaja ao fato de o módulo ter sido instalado.

A Play Core Library é um bom começo:

  • Finalmente, você pode parar de esperar talvez diante do Google Chrome.
  • Você pode demonstrar o carregamento dos módulos na interface do usuário da maneira que desejar.
  • É possível carregar os módulos de recursos em lotes.
  • Existe uma maneira de lidar com flexibilidade com erros que ocorrem ao baixar e instalar o módulo de recursos.
  • Você nem precisa reiniciar o aplicativo após a instalação do recurso, porque existe SplitCompat.install() - chame-o e você pode acessar imediatamente as classes a partir do recurso recém-instalado imediatamente.

Mas eu te enganaria se dissesse que a Play Core Library não fará você sofrer:

  • O código é ofuscado e não está documentado de forma alguma.
  • Os eventos de todas as sessões de carregamento ativas chegam a um SplitInstallStateUpdatedListener - você precisa classificá-los manualmente. É necessário salvar a ID da sessão em algum lugar com antecedência, o que acaba resultando em um código não muito bonito.
  • Gerenciamento de estado desajeitado e redundante e tratamento de erros: 9 estados possíveis, 10 erros possíveis. As combinações desses erros e estados podem ser interpretadas de maneira diferente, todos os estados e erros são retornados como int.
  • Não há possibilidade de teste normal de download e instalação de recursos em um dispositivo local - isso é simplesmente impossível.

A única opção é incorporar sua compilação no Google Play ao canal de testes internos e tentar o que aconteceu. Se você encontrar algum tipo de bug, inicie todo o processo novamente, implante atualizações e tente mais. Se você quiser verificar como funciona sem uma compilação, receberá o erro "-2" e poderá adivinhar o que isso significa. Esse é o problema mais comum no repositório com amostras oficiais dos Recursos dinâmicos do Google.

Não há boas práticas para navegar entre os módulos de recursos. Nos exemplos oficiais, que mostram como ocorre a interação entre os módulos de recursos, eles sugerem que a situação seja resolvida com muita simplicidade: ative a dependência de um módulo para outro. Cada direção tem sua própria dependência, por que voltar?



Mas todos os benefícios da divisão em módulos são perdidos. Mudamos para os módulos muito antes de surgir a necessidade de resolver esses problemas. E eles fizeram isso em parte porque simplifica o trabalho com a base de código para desenvolvedores inexperientes que, devido à inexperiência, podem usar a atividade de assinatura com a atividade-base - então, procuram uma revisão de código.

Se você conectar todos os módulos com dependências para cima e para baixo, somente o Google será bom nisso, o que não terá que pensar em nada sobre navegação.

Pensamos durante muito tempo no que fazer com isso e, no final, decidimos por uma solução que ainda me faz tremer. Ele é chamado Class.forName - instanciando uma classe usando o ClassPath completo, que é interrompido por qualquer renomeação da classe de qualquer pacote pelo caminho, etc.

 abstract class ActivityCrossFeatureRoute { override fun prepareIntent(context: Context): Intent? { try { return Intent(context, Class.forName(targetClassPath())) } catch (e: ClassNotFoundException) { Logger.e("Activity with the following classpath was not found in the current " + "application: ${targetClassPath()}. If this activity is the part of Dynamic Feature, " + "please check if this Dynamic Feature is downloaded and installed on the device" + "successfully.") } return null } } 

Eu tinha vergonha de contar a alguém sobre isso até entrar no repositório de aplicativos do Plaid e ver que eles haviam resolvido o problema de navegação da mesma maneira e aconselhando todos a fazê-lo no Stack Overflow.

O Plaid é um dos casos mais interessantes, com eles o Google tenta todas as últimas tendências, animações interessantes, truques de design, os mais recentes componentes de interface do usuário e, em particular, modularidade.

Muitos, realmente muitos erros, sub-engenharia, aspereza. Você não precisará procurar erros por muito tempo.

  • O acesso aos recursos do módulo de aplicativo é possível apenas ao longo do caminho completo.

Em vez de escrever assim: R.string.primaryColor , você precisa escrever assim toda vez no código: ru.appname.package.R.string.primaryColor . De uma maneira diferente, a compilação não funcionará e aqui está o link para o rastreador oficial de problemas.


 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { Intent serviceIntent = new Intent(this, TestJobSchedulerService.class); startService(serviceIntent); } 

  • Manifesto de congelamento de erro ao conectar bibliotecas de terceiros, por exemplo, Firebase, Fabric, pacotes AndroidX, etc.

Todos eles usam IDs de aplicativo de espaços reservados no manifesto. O ID do aplicativo está inserido incorretamente, por causa do qual o manifesto não congela, o Android Studio não consegue encontrar a atividade padrão e você procura o problema por um longo tempo até encontrar conselhos no rastreador oficial de problemas - redefina todos os provedores e especifique seu ID do aplicativo.

 <provider android:name="com.crashlytics.android.CrashlyticsInitProvider" android:authorities="ru.app.name.crashlyticsinitprovider" tools:replace="android:authorities" /> <provider android:name="com.google.firebase.provider.FirebaseInitProvider" android:authorities="ru.app.name.firebaseinitprovider" tools:replace="android:authorities" /> <provider android:name="androidx.core.content.FileProvider" android:authorities="ru.app.name.fileprovide" tools:replace="android:authorities" /> 

  • A impossibilidade de múltiplas dependências em pacotes de terceiros é um dos meus pontos favoritos.

Suponha que dois módulos de recursos dependam de uma biblioteca de terceiros. Mas você não pode fazer uma dependência direta porque obtém: org.gradle.api.GradleException: [:feature1, :feature2] all package the same library [com.lib.Name:VeryGoodLib] . Resposta oficial : e se nesses módulos forem indicadas diferentes versões da biblioteca.

Os desenvolvedores aconselham: adicione um módulo de recurso à hierarquia, no qual não há nada além de uma dependência de uma biblioteca de terceiros, e torne-o dependente de dois módulos de recursos de origem.

  • O cache de chamadas de InstantApps.isInstantApp (contexto) em attachBaseContext ().

Os exemplos de código da documentação dos desenvolvedores do Android attachBaseContext() , simplesmente porque eles oferecem o attachBaseContext() para acessar o contexto por meio this e, se context==null , você não pode verificar se o InstantApps está sendo executado no momento ou não.

 override fun attachBaseContext(base: Context) { super.attachBaseContext(base) if (!InstantApps.isInstantApp(this)) { SplitCompat.install(this) } } 

  • ConstraintLayout exibe ConstraintLayout ao usar Groups e Barriers .

Imagine que você passou por tudo: montou a montagem, imaginou que ela precisava ser incorporada no canal de teste no Google Play, o Google Play não exibiu uma caixa de diálogo vermelha. Com as mãos trêmulas, você instala esta montagem no dispositivo, instala o recurso, acessa a tela - e vê que todo o layout se reuniu em uma pilha no canto superior esquerdo. Isso ocorre porque, se você usar Groups e Barriers , existe um maravilhoso método getPackageName que, por algum motivo, incorretamente. Como resultado, todas as suas visualizações simplesmente não estão posicionadas. Todas as restrições desaparecem e tudo fica ao acaso na tela.

Finalmente, depois de superar isso, você verá que ...

Os recursos dinâmicos ainda estão na versão beta! Você não pode ficar parado na produção. Você foi um testador gratuito do Google o tempo todo!



Mas não de acordo com o Google. Se você deseja se tornar um, pode preencher o Formulário de Interesse e talvez tenha sorte e tenha acesso a ser bloqueado na produção.
Acredita-se que o Instant Apps tenha perdido essa batalha. É improvável que isso seja anunciado nos próximos anos, mas o aumento da atividade de informações em torno da AMP confirma isso secretamente.
O pensamento que eu queria lembrar você e eu - escreva para as pessoas . Pense três vezes antes de tomar qualquer decisão, especialmente se você estiver desenvolvendo ferramentas que outros desenvolvedores usarão. Todas as suas decisões e ações afetarão alguém e, possivelmente, estragarão um pouco de sangue. Eu não gostaria de causar um colapso para alguém.

Links úteis



Criamos o programa Saint AppsConf , que já é de 21 a 22 de outubro em São Petersburgo, ainda mais agitado e diversificado do que na primavera. Confira!

Ou assine a newsletter , telegrama , fb - aqui falamos sobre relatórios e preparativos individuais para a conferência.

Source: https://habr.com/ru/post/pt462511/


All Articles