Criar vários APKs para diferentes níveis de API

Se você publicar seu aplicativo no Google Play, será necessário criar e fazer upload de um Android App Bundle. Quando você faz isso, o Google Play gera e disponibiliza automaticamente APKs otimizados para a configuração do dispositivo de cada usuário, para que eles façam o download apenas do código e dos recursos necessários para executar o app. A publicação de vários APKs é útil se você não for publicar no Google Play, mas será preciso criar, assinar e gerenciar cada APK por conta própria.

Ao desenvolver seu aplicativo Android para aproveitar vários APKs no Google Play, é importante adotar algumas práticas recomendadas desde o início e evitar dores de cabeça desnecessárias no processo de desenvolvimento. Esta lição mostra como criar vários APKs do seu app, cada um com uma faixa ligeiramente diferente de níveis de API. Você também terá algumas ferramentas necessárias para simplificar o máximo possível a manutenção de um codebase de vários APKs.

Confirmar que você precisa de vários APKs

Ao tentar criar um aplicativo que funcione em várias gerações da Plataforma Android, é natural que você queira que seu aplicativo aproveite os novos recursos dos novos dispositivos sem perder a compatibilidade com versões anteriores. No início, pode parecer que a compatibilidade com vários APKs é a melhor solução, mas esse geralmente não é o caso. A seção Como usar um único APK do guia de desenvolvimento de APKs múltiplos traz algumas informações úteis sobre como fazer isso com um único APK, incluindo o uso da nossa biblioteca de suporte. Você também pode aprender a escrever códigos que são executados apenas em determinados níveis de API em um único APK sem recorrer a técnicas caras da perspectiva computacional, como reflexão, neste artigo.

Se possível, a limitação do seu aplicativo a um único APK tem várias vantagens, incluindo:

  • É mais fácil fazer publicações e testes.
  • Há apenas um codebase para manter.
  • Seu aplicativo pode se adaptar às mudanças de configuração do dispositivo.
  • A restauração de apps é funcional em vários dispositivos.
  • Você não precisa se preocupar com a preferência de mercado, o comportamento de "upgrades" de um APK para o próximo ou qual APK combina com cada classe de dispositivos.

O restante da lição considera que você já pesquisou o assunto, estudou o material nos recursos indicados e determinou que usar vários APKs é o caminho certo para seu aplicativo.

Organizar seus requisitos

Comece criando um gráfico simples para determinar rapidamente de quantos APKs você precisa e o intervalo de API que cada APK abrange. Como referência útil, a página Versões da plataforma do site para desenvolvedores Android fornece dados sobre o número relativo de dispositivos ativos executando uma determinada versão da plataforma Android. Além disso, embora pareça fácil no início, acompanhar o conjunto de níveis de API ao qual cada APK é destinado fica mais difícil rapidamente, em especial se houver alguma sobreposição (geralmente há). Felizmente, não é difícil mapear seus requisitos de maneira rápida, fácil e ter uma referência simples para uso posterior.

Para criar seu gráfico de vários APKs, comece com uma linha de células que representa os diversos níveis de API da plataforma Android. Adicione uma célula extra no final para representar versões futuras do Android.

3 4 5 6 7 8 9 10 11 12 13 +

Agora, basta colorir o gráfico de forma que cada cor represente um APK. Confira um exemplo de como aplicar cada APK a um determinado intervalo de níveis de API.

3 4 5 6 7 8 9 10 11 12 13 +

Depois de criar o gráfico, distribua-o para sua equipe. A comunicação da equipe do seu projeto acabou de ficar mais simples, já que em vez de perguntar "Como é o APK para os níveis de API 3 a 6, sabe, do Android 1.x. Como é mesmo?" Você pode simplesmente dizer "Como está o APK azul?".

Colocar todos os códigos e recursos comuns em um projeto de biblioteca

Independentemente de estar modificando um aplicativo Android existente ou começando do zero, essa é a primeira coisa que você precisa fazer no codebase e, de longe, a mais importante. Tudo que entra no projeto da biblioteca só precisa ser atualizado uma única vez (pense em strings localizadas por idioma, temas de cor e bugs corrigidos no código compartilhado), o que melhora o tempo de desenvolvimento e reduz a probabilidade de erros que poderiam ser facilmente evitados.

Observação:embora os detalhes de implementação de como criar e incluir projetos de biblioteca estejam fora do escopo desta lição, você pode se orientar lendo Criar uma biblioteca Android.

Se você estiver convertendo um aplicativo existente para usar o suporte a vários APKs, procure na sua base de código todos os arquivos de string localizados, listas de valores, cores de tema, ícones de menu e layout que não serão modificados em APKs e coloque tudo no projeto da biblioteca. O código que não muda muito também precisa ser incluído no projeto da biblioteca. Você provavelmente vai estender essas classes para adicionar um método ou dois de APK para APK.

Se, por outro lado, você estiver criando o aplicativo do zero, tente escrever o código no projeto da biblioteca primeiro e, em seguida, movê-lo apenas para um APK individual, se necessário. Isso é muito mais fácil de gerenciar a longo prazo do que adicioná-lo a um, depois a outro, depois outro e meses depois tentar descobrir se esse blob pode ser movido para a seção da biblioteca sem estragar tudo.

Criar novos projetos de APK

Haverá um projeto Android diferente para cada APK que você gerará. Para facilitar a organização, coloque o projeto da biblioteca e todos os projetos de APK relacionados na mesma pasta mãe. Lembre-se também de que cada APK precisa ter o mesmo nome de pacote, embora não precise necessariamente compartilhar o nome do pacote com a biblioteca. Se você tivesse três APKs seguindo o esquema descrito anteriormente, seu diretório raiz seria algo assim:

alexlucas:~/code/multi-apks-root$ ls
foo-blue
foo-green
foo-lib
foo-red

Depois que os projetos forem criados, adicione o projeto da biblioteca como referência para cada projeto de APK. Se possível, defina a atividade inicial no projeto da biblioteca e estenda essa atividade no projeto do APK. Ter uma atividade inicial definida no projeto da biblioteca oferece a oportunidade de colocar toda a inicialização do aplicativo em um só lugar, para que cada APK não precise reimplementar tarefas "universais", como inicializar o Google Analytics, executar verificações de licenciamento e qualquer outro procedimento de inicialização que não mude muito de APK para APK.

Ajustar os manifestos

Quando um usuário faz o download de um aplicativo que usa vários APKs por meio do Google Play, o APK correto a ser usado é escolhido usando duas regras simples:

  • O manifesto precisa mostrar que determinado APK é qualificado.
  • Dos APKs qualificados, o número de versão mais alto ganha.

Por exemplo, vamos usar o conjunto de vários APKs descrito anteriormente e presumir que não definimos um nível máximo de API para os APKs. Tomados individualmente, o possível intervalo de cada APK seria assim:

3 4 5 6 7 8 9 10 11 12 13 +
3 4 5 6 7 8 9 10 11 12 13 +
3 4 5 6 7 8 9 10 11 12 13 +

Como é necessário que um APK com uma minSdkVersion posterior também tenha um código de versão posterior, sabemos que, em termos de valores de versionCode, vermelho ≥ verde ≥ azul. Portanto, podemos recolher o gráfico da seguinte maneira:

3 4 5 6 7 8 9 10 11 12 13 +

Agora, vamos supor que o APK vermelho tem alguns requisitos que os outros dois não têm. A página Filtros no Google Play do guia do desenvolvedor Android tem uma lista de possíveis culpados. Por exemplo, vamos supor que o vermelho exija uma câmera frontal. Na verdade, o objetivo do APK vermelho é combinar a câmera frontal com funcionalidades novas que foram adicionadas na API 11. Entretanto, nem todos os dispositivos com API de nível 11 ou superior têm câmeras frontais. Que horror!

Felizmente, se um usuário estiver navegando no Google Play em um desses dispositivos, o Google Play analisará o manifesto, verá que o vermelho lista a câmera frontal como requisito e o ignorará silenciosamente após determinar que o vermelho e esse dispositivo não nasceram para ficar juntos. Então, ele vai notar que o verde não é apenas compatível com versões futuras de dispositivos com a API de nível 11 (já que nenhuma maxSdkVersion foi definida), mas também não se importa se há ou não uma câmera frontal. O usuário ainda poderá fazer o download do app no Google Play porque, apesar de todo o contratempo com a câmera frontal, havia um APK compatível com esse nível específico de API.

Para manter todos os seus APKs em "faixas" separadas, é importante ter um bom esquema de código de versão. O recomendado pode ser encontrado na área de Códigos de versão do nosso guia para desenvolvedores. Como o exemplo de conjunto de APKs só lida com uma das três dimensões possíveis, seria suficiente separar cada APK por 1.000, definir os primeiros dígitos para a minSdkVersion para o APK específico e incrementar a partir desse ponto. O resultado será algo como o seguinte:

Azul: 03001, 03002, 03003, 03004…
Verde: 07001, 07002, 07003, 07004…
Vermelho:11001, 11002, 11003, 11004…

Juntando tudo isso, os manifestos do Android provavelmente teriam esta aparência:

Azul:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    android:versionCode="03001" android:versionName="1.0" package="com.example.foo">
    <uses-sdk android:minSdkVersion="3" />
    ...

Verde:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    android:versionCode="07001" android:versionName="1.0" package="com.example.foo">
    <uses-sdk android:minSdkVersion="7" />
    ...

Vermelho:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    android:versionCode="11001" android:versionName="1.0" package="com.example.foo">
    <uses-sdk android:minSdkVersion="11" />
    ...

Analisar a lista de verificação de pré-lançamento

Antes de fazer upload para o Google Play, verifique os itens a seguir. Lembre-se de que esses itens são especificamente relevantes para vários APKs e não representam uma lista de verificação completa para todos os aplicativos enviados ao Google Play.

  • Todos os APKs precisam ter o mesmo nome de pacote.
  • Todos os APKs precisam ser assinados com o mesmo certificado.
  • Se houver sobreposição de APKs na versão da plataforma, o que tiver a minSdkVersion mais recente precisa ter um código de versão posterior.
  • Verifique seus filtros de manifesto em busca de informações conflitantes. Um APK que só aceita o Android Cupcake em telas extra grandes, por exemplo, não será visto por ninguém.
  • Cada manifesto do APK precisa ser exclusivo em pelo menos um dos tipos de tela, textura OpenGL ou versão da plataforma compatível.
  • Tente testar cada APK em pelo menos um dispositivo. Fazendo isso, você terá um dos emuladores de dispositivos mais personalizáveis do mercado na sua máquina de desenvolvimento. O céu é o limite!

Também vale a pena inspecionar o APK compilado antes de enviar para o mercado para garantir que não haja surpresas que possam ocultar seu aplicativo no Google Play. É bem simples fazer isso usando a ferramenta "aapt". Aapt (a ferramenta Android Asset Packaging Tool) faz parte do processo de build para criar e empacotar seus aplicativos Android e também é uma ferramenta muito útil para inspecionar esses apps.

>aapt dump badging
package: name='com.example.hello' versionCode='1' versionName='1.0'
sdkVersion:'11'
uses-permission:'android.permission.SEND_SMS'
application-label:'Hello'
application-icon-120:'res/drawable-ldpi/icon.png'
application-icon-160:'res/drawable-mdpi/icon.png'
application-icon-240:'res/drawable-hdpi/icon.png'
application: label='Hello' icon='res/drawable-mdpi/icon.png'
launchable-activity: name='com.example.hello.HelloActivity'  label='Hello' icon=''
uses-feature:'android.hardware.telephony'
uses-feature:'android.hardware.touchscreen'
main
supports-screens: 'small' 'normal' 'large' 'xlarge'
supports-any-density: 'true'
locales: '--_--'
densities: '120' '160' '240'

Ao examinar a saída do aapt, verifique se não há valores conflitantes para supports-screens e compatible-screens e se não há valores "uses-feature" não intencionais que foram adicionados como resultado de permissões definidas no manifesto. No exemplo acima, o APK não vai ser visível para muitos dispositivos.

Por quê? Ao adicionar a permissão necessária SEND_SMS, o requisito de recurso de android.hardware.telephony é adicionado implicitamente. Como a API de nível 11 é o Honeycomb (versão do Android otimizada especialmente para tablets) e nenhum dispositivo Honeycomb tem hardware de telefonia, o Google Play filtrará esse APK em todos os casos até o surgimento de dispositivos futuros com níveis de API mais altos e também com hardware de telefonia.

Felizmente, isso é corrigido de forma simples adicionando o seguinte ao seu manifesto:

<uses-feature android:name="android.hardware.telephony" android:required="false" />

O requisito android.hardware.touchscreen também é adicionado implicitamente. Se você quiser que seu APK fique visível em TVs que não tenham tela touchscreen, adicione o seguinte ao manifesto:

<uses-feature android:name="android.hardware.touchscreen" android:required="false" />

Depois de concluir a lista de verificação de pré-lançamento, faça upload dos seus APKs para o Google Play. Pode demorar um pouco para o aplicativo aparecer ao navegar pelo Google Play, mas, quando isso acontecer, faça uma última verificação. Faça o download do aplicativo em qualquer dispositivo de teste para verificar se os APKs estão segmentando os dispositivos pretendidos. Parabéns, você terminou!