Participe do evento ⁠#Android11: apresentação de lançamento da versão Beta no dia 3 de junho.

Compatível com arquiteturas de 64 bits

A partir de 1º de agosto de 2019, seus apps publicados no Google Play precisarão ser compatíveis com arquiteturas de 64 bits (link em inglês). As CPUs de 64 bits oferecem experiências mais rápidas e aprimoradas para os usuários. A adição de uma versão de 64 bits do seu app proporciona melhorias de desempenho, abre caminho para inovações futuras e faz com que seu app possa ser executado em hardware com 64 bits.

Este guia explica as etapas que você pode seguir para garantir que seu app de 32 bits seja compatível com dispositivos de 64 bits.

Avaliar o app

Se seu app usa apenas código escrito na linguagem de programação Java ou Kotlin, incluindo quaisquer bibliotecas ou SDKs, ele já está pronto para dispositivos de 64 bits. Se seu app usa código nativo ou se você não sabe se ele usa, avalie o app e tome as providências necessárias.

Verificação rápida de status

Uma maneira rápida de verificar se o app está pronto para o requisito de 64 bits é acessar o Play Console e dar uma olhada nas versões existentes para verificar se são compatíveis:

O Play Console também exibirá avisos que se aplicam às suas versões de rascunho se houver algum problema relacionado ao requisito de 64 bits. Veja um exemplo:

Se você vir um alerta, siga as etapas abaixo para preparar seu app.

O app usa código nativo?

A primeira coisa a fazer é verificar se seu app usa código nativo. Seu app usa código nativo se ele:

  • usa qualquer código C/C++ (nativo);
  • vincula-se a qualquer biblioteca nativa de terceiros;
  • é feito por um criador de apps de terceiros que usa bibliotecas nativas.

O app inclui bibliotecas de 64 bits?

A maneira mais simples de verificar a existência de bibliotecas de 64 bits é inspecionar a estrutura do seu arquivo APK. Quando criado, o APK é empacotado com as bibliotecas nativas necessárias para o app. As bibliotecas nativas são armazenadas em várias pastas na ABI. Não é necessário que haja compatibilidade com todas as arquiteturas de 64 bits, mas para cada arquitetura nativa de 32 bits compatível, você precisa incluir a arquitetura de 64 bits correspondente.

Para a arquitetura ARM, as bibliotecas de 32 bits estão localizadas em armeabi-v7a. O equivalente para 64 bits é arm64-v8a.

Para a arquitetura x86, procure x86 para 32 bits e x86_64 para 64 bits.

A primeira coisa a fazer é garantir que haja bibliotecas nativas nas duas pastas. Em resumo:

Plataforma Pasta de bibliotecas de 32 bits Pasta de bibliotecas de 64 bits
ARM lib/armeabi-v7a lib/arm64-v8a
x86 lib/x86 lib/x86_64

Dependendo do seu app, pode haver ou não exatamente o mesmo conjunto de bibliotecas em cada pasta. O objetivo é garantir que seu app seja executado da forma correta em um ambiente de 64 bits.

Em um caso comum, um APK ou pacote criado para arquiteturas de 32 e 64 bits tem pastas para as duas ABIs, cada uma com um conjunto correspondente de bibliotecas nativas. Se não houver compatibilidade com 64 bits, você provavelmente verá uma pasta ABI de 32 bits, mas não uma de 64.

Procurar bibliotecas nativas usando o APK Analyzer

O APK Analyzer é uma ferramenta que permite que você avalie vários aspectos de um APK criado. No nosso caso, vamos usá-lo para encontrar bibliotecas nativas e garantir que as bibliotecas de 64 bits estejam presentes.

  1. Inicie o Android Studio e abra qualquer projeto.
  2. No menu, selecione Build > Analyze APK…

    iniciar o APK Analyzer

  3. Escolha o APK que você quer avaliar.

  4. Procure na pasta lib, onde você encontrará todos os arquivos ".so". Se não encontrar nenhum arquivo ".so" no seu app, isso significa que o app já está pronto e não é necessária nenhuma outra ação. Se você vir armeabi-v7a ou x86, isso significa que tem bibliotecas de 32 bits.

  5. Verifique se há arquivos ".so" semelhantes na pasta arm64-v8a ou x86_64.

    iniciar o APK Analyzer

  6. Se não houver nenhuma biblioteca arm64-v8a ou x86_64, será necessário atualizar seu processo de compilação para começar a criar e empacotar esses artefatos no seu APK.

  7. Se as duas bibliotecas já estiverem sendo empacotadas, você pode avançar para Testar seu app em um dispositivo de 64 bits.

Procurar bibliotecas nativas descompactando APKs

Os arquivos APK são estruturados como arquivos ZIP e também podem ser extraídos da mesma forma que eles. Você também pode usar uma linha de comando ou qualquer outra ferramenta de extração para descompactar o APK, se preferir.

Basta descompactar o arquivo APK (dependendo da ferramenta de extração, talvez seja necessário renomeá-lo para .zip) e procurar os arquivos extraídos, seguindo as orientações acima para descobrir se você está pronto para dispositivos de 64 bits.

Por exemplo, você pode executar o seguinte comando na linha de comando:

:: Command Line
    > zipinfo -1 YOUR_APK_FILE.apk | grep \.so$
    lib/armeabi-v7a/libmain.so
    lib/armeabi-v7a/libmono.so
    lib/armeabi-v7a/libunity.so
    lib/arm64-v8a/libmain.so
    lib/arm64-v8a/libmono.so
    lib/arm64-v8a/libunity.so
    

Observe nesse exemplo a presença de bibliotecas armeabi-v7a e arm64-v8a, o que significa que o app é compatível com arquiteturas de 64 bits.

Criar o app com bibliotecas de 64 bits

Veja a seguir algumas instruções para criar bibliotecas de 64 bits. Isto abrangerá apenas o código de criação e as bibliotecas que você pode criar a partir da origem.

Se você estiver usando bibliotecas ou SDKs externos, siga as etapas acima para verificar se as versões de 64 bits estão sendo utilizadas. Entre em contato com o proprietário do SDK ou da biblioteca se uma versão de 64 bits não estiver disponível e leve isso em consideração ao planejar sua compatibilidade com dispositivos de 64 bits.

Criar com o Android Studio ou o Gradle

A maioria dos projetos do Android Studio usa o Gradle como sistema de criação subjacente, então, esta seção se aplica aos dois casos. A ativação de versões para seu código nativo é tão simples quanto adicionar o arm64-v8a e/ou x86_64 à configuração ndk.abiFilters (link em inglês) no arquivo "build.gradle" do seu app, dependendo das arquiteturas para as quais você quer oferecer compatibilidade:

// Your app's build.gradle
    apply plugin: 'com.android.app'

    android {
       compileSdkVersion 27
       defaultConfig {
           appId "com.google.example.64bit"
           minSdkVersion 15
           targetSdkVersion 28
           versionCode 1
           versionName "1.0"
           ndk.abiFilters 'armeabi-v7a','arm64-v8a','x86','x86_64'
    // ...
    

Criar com o CMake

Se seu app for criado com o CMake, você poderá criar para ABIs de 64 bits transmitindo arm64-v8a para o parâmetro "-DANDROID_ABI":

:: Command Line
    > cmake -DANDROID_ABI=arm64-v8a … or
    > cmake -DANDROID_ABI=x86_64 …
    

Essa opção não tem efeito quando se usa externalNativeBuild. Veja a seção Criar com o Gradle.

Criar com o ndk-build

Se seu app for criado com o ndk-build, você poderá criar para ABIs de 64 bits modificando o arquivo Application.mk por meio da variável APP_ABI:

APP_ABI := armeabi-v7a arm64-v8a x86 x86_64
    

Essa opção não tem efeito quando se usa externalNativeBuild. Veja a seção Criar com o Gradle.

Portabilidade de código de 32 bits para 64 bits

Se seu código já estiver sendo executado no computador ou no iOS, você não precisará fazer nenhum trabalho extra para o Android. Se esta for a primeira vez que seu código foi criado para um sistema de 64 bits, o principal problema que você precisará resolver é que os ponteiros não se encaixam mais em tipos inteiros de 32 bits, como int. Será necessário atualizar o código que armazena ponteiros em tipos, como int, unsigned, ou uint32_t. Em sistemas Unix, long corresponde ao tamanho do ponteiro, mas isso não é verdade no Windows, então use os tipos de revelação de intenção uintptr_t ou intptr_t. Use o tipo ptrdiff_t para armazenar a diferença entre dois ponteiros.

Prefira sempre os tipos inteiros de largura fixa específicos definidos em <stdint.h> (link em inglês) em vez dos tipos tradicionais, como int ou long, até mesmo para não ponteiros.

Use as seguintes sinalizações do compilador para capturar casos em que seu código está convertendo incorretamente entre ponteiros e números inteiros:

-Werror=pointer-to-int-cast
    -Werror=int-to-pointer-cast
    -Werror=shorten-64-to-32
    

Classes Java com campos int que contêm ponteiros para objetos C/C++ têm o mesmo problema. Procure jint na sua fonte JNI e alterne para long na parte em Java e jlong na parte em C++.

Declarações implícitas de funções são muito mais perigosas para código de 64 bits. C/C++ presume que o tipo de retorno de uma função declarada implicitamente (ou seja, uma função para a qual o compilador não tenha visto uma declaração) é int. Se o tipo de retorno real da sua função for um ponteiro, isso funcionará bem em um sistema de 32 bits em que o ponteiro se encaixa em um int, mas em um sistema de 64 bits o compilador eliminará a metade superior do ponteiro. Por exemplo:

// This function returns a pointer:
    // extern char* foo();

    // If you don't include a header that declares it,
    // when the compiler sees this:
    char* result = foo();

    // Instead of compiling that to:
    result = foo();

    // It compiles to something equivalent to:
    result = foo() & 0xffffffff;

    // Which will then cause a SIGSEGV if you try to dereference `result`.
    

A seguinte sinalização do compilador transforma avisos implícitos de declaração de função em erros para que você possa encontrar e corrigir esse problema mais facilmente:

-Werror=implicit-function-declaration
    

Se você tiver um conversor in-line, precisará reescrevê-lo ou usar uma implementação simples de C/C++.

Se você tiver tamanhos codificados de tipos (8 ou 16 bytes, por exemplo), substitua-os pela expressão sizeof(T) equivalente, como sizeof(void*).

Se você precisa compilar condicionalmente um código para 32 bits diferente do de 64 bits, use o #if defined(__LP64__) para diferenças genéricas entre 32 e 64 bits, ou __arm__, __aarch64__ (arm64), __i386__ (x86) e __x86_64__ para as arquiteturas específicas compatíveis com o Android.

Será necessário ajustar as strings de formato para funções semelhantes a printf ou scanf, já que os especificadores tradicionais de formato não permitem a especificação de tipos de 64 bits de uma forma que seja correta para dispositivos tanto de 32 quanto de 64 bits. As macros PRI e SCN em <inttypes.h> resolvem esse problema: PRIxPTR e SCNxPTR para ponteiros hex de gravação/leitura, PRId64 e SCNd64 para gravação/leitura portátil de valores de 64 bits.

Ao mudar, pode ser necessário usar 1ULL para ter uma constante de 64 bits em vez de usar 1, que é apenas de 32 bits.

Evitar aumento de tamanho com o Android App Bundle

A inclusão da compatibilidade com arquitetura de 64 bits para seu app pode aumentar o tamanho do seu APK. É altamente recomendável que você use o recurso Android App Bundle para minimizar o impacto sobre o tamanho da inclusão de código nativo de 32 e 64 bits no mesmo APK.

Na verdade, o uso do Android App Bundle pode resultar em uma redução no tamanho do seu APK atual.

Desenvolvedores de jogos

Entendemos que a migração de um motor de jogo de terceiros é um processo intenso, com longos tempos de lead. Felizmente, os três motores mais usados são compatíveis com 64 bits:

  • Unreal desde 2015
  • Cocos2d desde 2015
  • Unity desde 2018

Desenvolvedores de Unity

Atualizar para versões compatíveis

O Unity começou a ser compatível com 64 bits nas versões 2018.2 e 2017.4.16 (links em inglês).

Se você acha que está usando uma versão do Unity que não é compatível com 64 bits, determine a versão para a qual quer fazer upgrade. Siga os guias fornecidos pelo Unity para migrar seu ambiente, garantindo que seu app seja atualizado para uma versão que possa criar bibliotecas de 64 bits. A Unity recomenda que você tenha acesso aos recursos e atualizações mais recentes fazendo upgrade para a última versão do LTS do editor.

Veja uma tabela que descreve as várias versões do Unity e o que você precisa fazer:

Versão do Unity Compatível com 64 bits? Ação recomendada

2018.4 (LTS)

✔️

(Versão pendente) Suas configurações de compilação precisam gerar bibliotecas de 64 bits.

2018.3

✔️

Suas configurações de compilação precisam gerar bibliotecas de 64 bits.

2018.2

✔️

Suas configurações de compilação precisam gerar bibliotecas de 64 bits.

2018.1

Tem compatibilidade experimental com 64 bits.

2017.4 (LTS)

✔️

Compatível a partir da versão 2017.4.16. Suas configurações de compilação precisam gerar bibliotecas de 64 bits.

2017.3

✖️

Faça upgrade para a versão compatível com 64 bits.

2017.2

✖️

Faça upgrade para a versão compatível com 64 bits.

2017.1

✖️

Faça upgrade para a versão compatível com 64 bits.

<=5.6

✖️

Faça upgrade para a versão compatível com 64 bits.

Alterar configurações de criação para produzir bibliotecas de 64 bits

Se você estiver usando uma versão do Unity que seja compatível com bibliotecas de 64 bits do Android, poderá gerar uma versão de 64 bits do seu app ajustando as configurações de criação. Você também precisará usar o back-end IL2CPP como back-end de scripts (veja detalhes clicando aqui). Para configurar seu projeto do Unity para compilar uma arquitetura de 64 bits, faça o seguinte:

  1. Acesse Build Settings e confirme que você está compilando para Android verificando se o símbolo do Unity está ao lado da plataforma Android.**
    1. Se o símbolo do Unity não estiver ao lado da plataforma Android, selecione Android e clique em Switch Platform.
  2. Clique em Player settings.

    Configurações do player no Unity

  3. Navegue até Player Settings Panel > Settings for Android > Other settings > Configuration.

  4. Configure o Scripting Backend como IL2CPP.

  5. Marque a caixa de seleção **Target Architecture > ARM64.

    definir arquiteturas de destino no Unity

  6. Continue a criar como de costume.

A criação para ARM64 exigirá que todos os seus recursos sejam criados especificamente para essa plataforma. Siga as orientações do Unity (em inglês) para reduzir o tamanho do APK e use o recurso Android App Bundle para ajudar a evitar esse aumento de tamanho.

Compatibilidade com vários APKs e 64 bits

Se você estiver usando a compatibilidade com vários APKs do Google Play para publicar seu app, observe que a conformidade com o requisito de 64 bits é avaliada no nível da versão. No entanto, o requisito de 64 bits não se aplica a APKs ou pacotes de apps que não sejam distribuídos para dispositivos com o Android 9 Pie ou versões posteriores.

Se um dos seus APKs estiver marcado como não compatível, mas for mais antigo e não for possível deixá-lo em conformidade, adicione um atributo maxSdkVersion="27" ao elemento uses-sdk no manifesto desse APK. O APK não será entregue a dispositivos com Android 9 Pie ou versões posterior e deixará de impedir a conformidade.

Compatibilidade com RenderScript e 64 bits

Se seu app usa o RenderScript e foi criado com uma versão mais antiga das ferramentas do Android, você poderá encontrar problemas de conformidade com 64 bits. Com ferramentas de criação anteriores à 21.0.0, o compilador pode gerar bitcode em um arquivo .bc externo. Esses arquivos .bc legados não são mais compatíveis com arquiteturas de 64 bits, então a presença do arquivo no APK causa o problema de conformidade.

Para resolver o problema, remova todos os arquivos .bc do seu projeto, faça upgrade do seu ambiente para build-tools-21.0.0 ou mais recente e defina a renderscriptTargetApi no Android Studio como 21 ou superior para dizer ao compilador que não emita mais arquivos .bc. Em seguida, recrie seu app, inspecione os arquivos .bc e faça upload para o Play Console.

Testar o app em hardware de 64 bits

A versão de 64 bits do seu app precisa oferecer a mesma qualidade e o mesmo conjunto de recursos da versão de 32 bits. Teste seu app para garantir que os usuários dos dispositivos de 64 bits mais recentes tenham uma ótima experiência.

Para começar a testar seu app, você precisará ter um dispositivo compatível com 64 bits. Há vários dispositivos conhecidos disponíveis compatíveis com 64 bits, como o Pixel do Google e outros dispositivos de sucesso.

A maneira mais fácil de testar seu APK é instalando o app usando adb. Na maioria dos casos, você pode fornecer --abi como um parâmetro para indicar quais bibliotecas serão instaladas no dispositivo. O app será instalado no dispositivo apenas com as bibliotecas de 64 bits.

:: Command Line
    # A successful install:
    > adb install --abi armeabi-v7a YOUR_APK_FILE.apk
    Success

    # If your APK does not have the 64-bit libraries:
    > adb install --abi arm64-v8a YOUR_APK_FILE.apk
    adb: failed to install YOUR_APK_FILE.apk: Failure [INSTALL_FAILED_NO_MATCHING_ABIS: Failed to extract native libraries, res=-113]

    # If your device does not support 64-bit, an emulator, for example:
    > adb install --abi arm64-v8a YOUR_APK_FILE.apk
    ABI arm64-v8a not supported on this device
    

Depois de concluir a instalação, teste o app como normalmente faria para garantir que a qualidade seja igual à da versão de 32 bits.

Publicar

Quando você achar que seu app está pronto, publique-o normalmente. Como sempre, continue seguindo as práticas recomendadas para implantar o app. Recomendamos que você use as faixas de teste fechadas para lançar a um número limitado de usuários para garantir que a qualidade do seu app seja consistente.

Assim como na implementação de uma atualização importante, teste o app completamente em dispositivos compatíveis com 64 bits antes de publicá-lo para um público maior.