Compilação de APKs específicos para ABI
Este documento discute como compilar um APK que será direcionado a uma única ABI usando o Xamarin.Android.
Visão geral
Em algumas situações, pode ser vantajoso para um aplicativo ter vários APKs – cada APK é assinado com o mesmo armazenamento de chaves e compartilha o mesmo nome de pacote, mas é compilado para uma configuração do Android ou dispositivo específico. Essa não é a abordagem recomendada, pois é muito mais simples ter um APK que pode dar suporte a vários dispositivos e configurações. Há algumas situações em que criar vários APKs pode ser útil, tais como:
Reduzir o tamanho do APK – o Google Play impõe um limite de tamanho de 100 MB para arquivos APK. A criação de APKs específicos de um dispositivo pode reduzir o tamanho do APK, pois você só precisa fornecer um subconjunto de ativos e recursos para o aplicativo.
Compatível com diferentes arquiteturas de CPU – Se o aplicativo tem bibliotecas compartilhadas para CPUs específicas, você pode distribuir apenas as bibliotecas compartilhadas para essa CPU.
Vários APKs podem complicar a distribuição – um problema que é abordado pelo Google Play. O Google Play garantirá que o APK correto seja entregue a um dispositivo com base no código da versão do aplicativo e outros metadados contidos em AndroidManifest.XML. Para obter detalhes específicos e restrições no modo como o Google Play é compatível com vários APKs para um aplicativo, consulte a Documentação do Google sobre o suporte a vários APKs.
Este guia abordará como criar o script o build de múltiplos APKs para um aplicativo Xamarin.Android, cada APK direcionado a um ABI específico. Ele aborda os seguintes tópicos:
- Criar um código de versão exclusivo para o APK.
- Criar uma versão temporária de AndroidManifest.XML, que será usada para este APK.
- Compile o aplicativo usando o AndroidManifest.XML da etapa anterior.
- Prepare o APK para lançamento, assinando-o e submetendo-o a zipalign.
No final deste guia há um passo a passo que demonstra como criar o script dessas etapas usando o Rake.
Criar um código de versão para o APK
O Google recomenda um algoritmo específico para o código de versão, que usa um código de versão de sete dígitos (consulte a seção Usando um esquema de código de versão no Documento de suporte a vários APKs). Expandindo esse esquema de código da versão de oito dígitos, será possível incluir, no código de versão, algumas informações de ABI que garantirão que o Google Play distribuirá o APK correto para um dispositivo. A lista a seguir explica este formato de código de versão de oito dígitos (indexado da esquerda para a direita):
Índice 0 (vermelho no diagrama abaixo) – Um inteiro para o ABI:
- 1 –
armeabi
- 2 –
armeabi-v7a
- 6 –
x86
- 1 –
Índice 1-2 (laranja no diagrama abaixo) – O nível mínimo de API suportado pelo aplicativo.
Índice 3-4 (azul no diagrama abaixo) – Os tamanhos de tela suportados:
- 1 – pequeno
- 2 – Normal
- 3 – grande
- 4 – xlarge
Índice 5-7 (verde no diagrama abaixo) – Um número exclusivo para o código da versão. Ele é definido pelo desenvolvedor. Ele deve aumentar a cada versão pública do aplicativo.
O diagrama a seguir ilustra a posição de cada código descrito na lista acima:
O Google Play garantirá que o APK correto seja entregue ao dispositivo com base no versionCode
e na configuração de APK. O APK com o código da versão mais alto será entregue ao dispositivo. Como um exemplo, um aplicativo pode ter três APKs com os seguintes códigos de versão:
- 11413456 - O ABI é
armeabi
direcionado ao nível 14 da API, telas pequenas a grandes, com um número de versão de 456. - 21423456 - O ABI é
armeabi-v7a
alvo de API nível 14, telas grandes normais e com número de versão 456. - 61423456 - O ABI é
x86
de API nível 14, tela grande normal e com número de versão 456.
Para continuar com este exemplo, imagine que foi corrigido um bug que era específico para armeabi-v7a
. A versão do aplicativo aumenta para 457, e um novo APK é criado com o android:versionCode
definido para 21423457. Os versionCodes para as versões armeabi
e x86
permanecerão os mesmos.
Agora, imagine que a versão x86 recebe algumas atualizações ou correções de bug que se destinam a uma API mais recente (nível da API 19), tornando esta a versão 500 do aplicativo. O novo versionCode
seria alterado para 61923500, enquanto o armeabi/armeabi-v7a permaneceriam inalterados. Nesse momento, os códigos de versão seriam:
- 11413456 - O ABI é
armeabi
de API nível 14, telas pequenas a grandes, com nome de versão 456. - 21423457 - O ABI é
armeabi-v7a
o nível 14 da API, as telas grandes normais e com o nome da versão 457. - 61923500 - O ABI é
x86
alvo de API nível 19, telas grandes normais e com nome de versão 500.
Manter esses códigos de versão manualmente pode ser um fardo significativo para o desenvolvedor. O processo de calcular o android:versionCode
correto e posteriormente compilar os APKs deve ser automatizado.
Um exemplo de como fazer isso será abordado no passo a passo no final deste documento.
Criar um AndroidManifest.XML temporário
Embora não seja estritamente necessário, criar um AndroidManifest.XML temporário para cada ABI pode ajudar a evitar problemas que possam surgir com vazamento de informações um APK ao outro. Por exemplo, é crucial que o atributo android:versionCode
seja exclusivo para cada APK.
O modo como isso é feito depende do sistema de script envolvido, mas geralmente envolve fazer uma cópia do manifesto do Android usado durante o desenvolvimento, modificá-lo e, em seguida, usar esse manifesto modificado durante o processo de build.
Compilar o APK
Compilar o APK por ABI melhor é realizado usando xbuild
ou msbuild
, conforme mostrado na seguinte linha de comando de exemplo:
/Library/Frameworks/Mono.framework/Commands/xbuild /t:Package /p:AndroidSupportedAbis=<TARGET_ABI> /p:IntermediateOutputPath=obj.<TARGET_ABI>/ /p:AndroidManifest=<PATH_TO_ANDROIDMANIFEST.XML> /p:OutputPath=bin.<TARGET_ABI> /p:Configuration=Release <CSPROJ FILE>
A lista a seguir explica cada parâmetro de linha de comando:
/t:Package
– Cria um APK Android que é assinado usando o keystore debug/p:AndroidSupportedAbis=<TARGET_ABI>
– Isso a ABI para atingir. Deve ser uma entrearmeabi
,armeabi-v7a
oux86
/p:IntermediateOutputPath=obj.<TARGET_ABI>/
– Este é o diretório que irá conter os arquivos intermediários que são criados como parte da compilação. Se necessário, o Xamarin.Android criará um diretório com o nome da ABI, tal comoobj.armeabi-v7a
. É recomendável usar uma pasta para cada ABI, pois isso impede problemas resultantes do "vazamento" de arquivos de um build para o outro. Observe que esse valor é encerrado com um separador de diretório (um/
no caso de OS X)./p:AndroidManifest
– Esta propriedade especifica o caminho para o arquivo AndroidManifest.XML que será usado durante a compilação./p:OutputPath=bin.<TARGET_ABI>
– Este é o diretório que abrigará o APK final. O Xamarin.Android criará um diretório com o nome da ABI, por exemplo,bin.armeabi-v7a
./p:Configuration=Release
– Execute uma compilação Release do APK. Os builds de depuração podem não ser carregados no Google Play.<CS_PROJ FILE>
– Este é o caminho para o.csproj
arquivo para o projeto Xamarin.Android.
Assinar e efetuar o zipalign no APK
É necessário assinar o APK antes que ele possa ser distribuído por meio do Google Play. Isso pode ser feito usando o aplicativo jarsigner
, que faz parte do Kit do Desenvolvedor Java. A linha de comando a seguir demonstra como usar jarsigner
na linha de comando:
jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore <PATH/TO/KEYSTORE> -storepass <PASSWORD> -signedjar <PATH/FOR/SIGNED_JAR> <PATH/FOR/JAR/TO/SIGN> <NAME_OF_KEY_IN_KEYSTORE>
O zipalign deve ser efetuado em todos os aplicativos Xamarin.Android antes que eles sejam executados em um dispositivo. Este é o formato da linha de comando a ser usada:
zipalign -f -v 4 <SIGNED_APK_TO_ZIPALIGN> <PATH/TO/ZIP_ALIGNED.APK>
Automatização da criação de APK com o Rake
O projeto de exemplo OneABIPerAPK é um projeto Android simples, que demonstra como calcular um número de versão específico de uma ABI e compilar três APKs separados para cada uma das seguintes ABIs:
- armeabi
- armeabi-v7a
- x86
O rakefile no projeto de exemplo executa cada uma das etapas descritas nas seções anteriores:
Criar um android: versionCode para o APK.
Gravar o android: versionCode em um AndroidManifest.XML personalizado para esse APK.
Compilar um build de versão do projeto Xamarin.Android que terá como destino exclusivo a ABI, usando o AndroidManifest.XML que foi criado na etapa anterior.
Assine o APK com um repositório de chaves de produção.
Efetuar o zipalign no APK.
Para compilar todos os APKs para o aplicativo, execute a tarefa do Rake build
da linha de comando:
$ rake build
==> Building an APK for ABI armeabi with ./Properties/AndroidManifest.xml.armeabi, android:versionCode = 10814120.
==> Building an APK for ABI x86 with ./Properties/AndroidManifest.xml.x86, android:versionCode = 60814120.
==> Building an APK for ABI armeabi-v7a with ./Properties/AndroidManifest.xml.armeabi-v7a, android:versionCode = 20814120.
Após a tarefa rake ser concluída, haverá três pastas bin
com o arquivo xamarin.helloworld.apk
. A próxima captura de tela mostra cada uma dessas pastas com os respectivos conteúdos:
Observação
O processo de build descrito neste guia pode ser implementado em um dos diversos sistemas de build. Embora não tenhamos um exemplo escrito anteriormente, isso também deverá ser possível com Powershell / psake ou Fake.
Resumo
Este guia fornece algumas sugestões de como criar APKs do Android que se destinam a uma ABI específica. Ele também mostrou um esquema possível para a criação de android:versionCodes
que identificará a arquitetura de CPU à qual o APK é destinado. O passo a passo inclui um projeto de exemplo que tem o script do seu build escrito usando Rake.