Como criar vários APKs para texturas GL diferentes

Se você publicar seu app no Google Play, será necessário criar e fazer upload de um Android App Bundle. Quando você faz isso, o Google Play gera e exibe 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 está publicando no Google Play, mas precisa criar, assinar e gerenciar cada APK.

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 suporte a um subconjunto diferente de formatos de textura OpenGL. 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 app que funcione em todos os dispositivos Android disponíveis, é natural que você queira que seu app tenha a melhor aparência em cada dispositivo, independentemente de nem todos serem compatíveis com o mesmo conjunto de texturas GL. 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 desenvolvedores de APKs múltiplos traz algumas informações úteis sobre como fazer isso com um único APK, incluindo como detectar formatos de textura compatíveis durante a execução. Dependendo da sua situação, pode ser mais fácil agrupar todos os formatos com seu aplicativo e simplesmente escolher qual deles usar no momento da execução.

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

O Guia para desenvolvedores Android oferece uma referência útil de algumas texturas comuns com suporte na página supports-gl-texture. Esta página também contém algumas dicas sobre quais smartphones (ou famílias de smartphones) oferecem suporte a formatos de textura específicos. É recomendável que um dos seus APKs seja compatível com o ETC1, pois esse formato de textura é compatível com todos os dispositivos Android compatíveis com a especificação OpenGL ES 2.0.

Como a maioria dos dispositivos Android é compatível com mais de um formato de textura, você precisa estabelecer uma ordem de preferência. Crie um gráfico com todos os formatos compatíveis com seu aplicativo. A célula mais à esquerda terá a prioridade mais baixa. Provavelmente será a ETC1, um padrão sólido em termos de desempenho e compatibilidade. Em seguida, coloque cores no gráfico de forma que cada célula represente um APK.

ETC1 ATI PowerVR

A coloração no gráfico faz mais do que apenas tornar este guia menos monocromático. Ela também tem uma maneira de facilitar a comunicação interna da equipe. Agora, você pode simplesmente se referir a cada APK como "azul", "verde" ou "vermelho", em vez de "O que oferece suporte aos formatos de textura ETC1", etc.

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

Independentemente de estar modificando um aplicativo para Android existente ou começando do zero, essa é a primeira coisa que você precisará fazer no codebase e, de longe, a mais importante. Tudo o 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, verifique sua base de código para cada arquivo de string localizado, lista de valores, cores de tema, ícones de menu e layout que não vão mudar entre os 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, é importante tentar tanto quanto possível 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. Além disso, cada APK precisa ter o mesmo nome de pacote, embora não seja necessário compartilhar o nome do pacote com a biblioteca necessariamente. 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 dá a você a chance 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 no Google Play, o APK correto a ser usado é escolhido usando algumas regras simples:

  • O manifesto precisa mostrar que determinado APK é qualificado.
  • Dos APKs qualificados, o número de versão mais alto ganha.
  • Se qualquer um dos formatos de textura listados no seu APK for compatível com o dispositivo no mercado, esse dispositivo será considerado qualificado.

Com relação às texturas GL, essa última regra é importante. Isso significa que você precisa ter muito cuidado com o uso de formatos GL diferentes no mesmo aplicativo. Se você usasse o PowerVR 99% das vezes, mas usasse o ETC1 para, digamos, sua tela de apresentação… Seu manifesto indicaria necessariamente compatibilidade com os dois formatos. Um dispositivo que apenas oferece suporte ao ETC1 seria considerado compatível, o download do app seria feito e o usuário receberia mensagens de erro assustadoras. O caso comum é que, se você estiver usando vários APKs especificamente para segmentar dispositivos diferentes com base no suporte a texturas GL, haverá um formato de textura por APK.

Isso faz com que a compatibilidade com a textura seja um pouco diferente das outras duas dimensões de vários APKs, do nível da API e do tamanho da tela. Todos os dispositivos só têm um nível de API e um tamanho de tela, e cabe ao APK ser compatível com um intervalo deles. Com as texturas, o APK geralmente é compatível com uma textura, e o dispositivo é compatível com várias. Muitas vezes, haverá sobreposição em que um dispositivo é compatível com muitos APKs, mas a solução é a mesma: códigos de versão.

Como exemplo, use alguns dispositivos e veja quantos dos APKs definidos anteriormente servem para cada dispositivo.

FooPhone Nexus S Evo
ETC1 ETC1 ETC1
PowerVR ATI TC

Supondo que os formatos PowerVR e ATI sejam preferidos ao ETC1 quando disponíveis, de acordo com a regra "o número de versão mais alto vence", se definirmos o atributo versionCode em cada APK de modo que vermelho ≥ verde ≥ azul, então vermelho e verde serão sempre escolhidos em vez de azul em dispositivos compatíveis. Se um dispositivo for compatível com vermelho e verde, o vermelho será escolhido.

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 do desenvolvedor. Como o conjunto de exemplos de APKs lida apenas com uma das três dimensões possíveis, seria suficiente separar cada APK por 1.000 e incrementar a partir daí. O resultado será algo como o seguinte:

Azul: 1001, 1002, 1003, 1004…
Verde: 2001, 2002, 2003, 2004...
Vermelho:3001, 3002, 3003, 3004...

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="1001" android:versionName="1.0" package="com.example.foo">
    <supports-gl-texture android:name="GL_OES_compressed_ETC1_RGB8_texture" />
    ...

Verde:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    android:versionCode="2001" android:versionName="1.0" package="com.example.foo">
    <supports-gl-texture android:name="GL_AMD_compressed_ATC_texture" />
    ...

Vermelho:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    android:versionCode="3001" android:versionName="1.0" package="com.example.foo">
    <supports-gl-texture android:name="GL_IMG_texture_compression_pvrtc" />
    ...

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.
  • 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 ao 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: '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 será invisível para a maioria dos dispositivos, se não para todos.

Por quê? Ao adicionar a permissão SEND_SMS necessária, o requisito de recurso de android.hardware.telephony é adicionado implicitamente. Como a maioria dos dispositivos extra grandes (se não todos) são tablets sem hardware de telefonia, o Google Play filtrará esse APK nesses casos até que apareçam novos dispositivos grandes o suficiente para informar um tamanho de tela extra grande e que tenham hardware de telefonia.

Felizmente, isso é facilmente corrigido 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!