Antes de começar
Este guia presume que você já conheça bem os conceitos inerentes à programação nativa e ao desenvolvimento para Android.
Introdução
Esta seção traz uma explicação de nível avançado sobre como o NDK funciona. O Android NDK é um conjunto de ferramentas que permitem incorporar C ou C++ (“código nativo”) em apps para Android. A capacidade de usar código nativo em apps para Android pode ser muito útil para desenvolvedores que querem:
- portar apps entre plataformas;
- reutilizar bibliotecas existentes ou fornecer as próprias para reutilização;
- melhorar o desempenho em determinados casos, em especial nos de computação intensa, como jogos.
Como funciona
Esta seção apresenta os principais componentes usados na criação de um app nativo para Android e descreve o processo de compilação e empacotamento.
Principais componentes
É necessário compreender os seguintes componentes durante a criação do seu app:
Bibliotecas compartilhadas nativas: o NDK cria essas bibliotecas, ou arquivos
.so
, a partir do código-fonte C/C++.Bibliotecas estáticas nativas: o NDK também pode criar bibliotecas estáticas ou arquivos
.a
que podem ser vinculados a outras bibliotecas.Java Native Interface (JNI): a JNI é a interface de comunicação entre os componentes Java e C++. Este guia requer conhecimentos sobre JNI. Para mais informações sobre esse recurso, consulte a Especificação da Java Native Interface (link em inglês).
Interface Binária de App (ABI): a ABI define exatamente como deverá ser a interação entre o código de máquina do app e o sistema no momento da execução. O NDK compila arquivos
.so
de acordo com essas definições. Diferentes ABIs correspondem a diferentes arquiteturas: o NDK é compatível com ABI para ARM de 32 bits, AArch64, x86 e x86-64. Para mais informações, consulte ABIs do Android.Manifesto: se você estiver criando um app sem componente Java, precisará declarar a classe NativeActivity no manifesto. Consulte Usar a interface native_activity.h para ver mais detalhes sobre como fazer isso.
Fluxo
O fluxo geral para desenvolver um app nativo para Android é o seguinte:
Projete o app e decida quais partes serão implementadas em Java e quais em código nativo.
Crie um projeto de app Android normalmente.
Se você estiver criando um app sem componente Java, precisará declarar a classe NativeActivity no
AndroidManifest.xml
. Para mais informações, consulte Atividades e apps nativos.Crie um arquivo
Android.mk
que descreva a biblioteca nativa, incluindo nome, sinalizações, bibliotecas vinculadas e arquivos de origem a serem compilados no diretório “JNI”.Você também pode criar um arquivo
Application.mk
configurando as ABIs de destino, conjuntos de ferramentas, modo de liberação/depuração e STL. Para qualquer um desses itens que você não especificar, os valores padrão a seguir serão usados, respectivamente:- ABI: todas as ABIs não obsoletas
- Modo: liberação
- STL: system
Coloque o código-fonte nativo no diretório
jni
do projeto.Use o ndk-build para compilar as bibliotecas nativas (
.so
,.a
).Crie o componente Java, produzindo o arquivo executável
.dex
.Agrupe tudo em um arquivo APK, contendo
.so
,.dex
e outros arquivos necessários para a execução do app.
Atividades e aplicativos nativos
O Android SDK fornece uma classe auxiliar, NativeActivity, que permite
programar uma atividade completamente nativa. A NativeActivity lida com a comunicação
entre a estrutura do Android e seu código nativo para que você não precise criar uma
subclassificação nem chamar os métodos. Basta declarar o app como nativo no
arquivo AndroidManifest.xml
e começar a
desenvolvê-lo.
Os apps Android que usam NativeActivity ainda podem ser executados na própria máquina virtual, no sandbox de outros apps. Portanto, você ainda pode acessar as APIs do framework do Android por meio do JNI. Porém, em certos casos, como para sensores, eventos de entrada e recursos, o NDK fornece interfaces nativas que você pode usar em vez de chamar o JNI. Para mais informações sobre essa compatibilidade, consulte APIs nativas.
Independentemente de estar desenvolvendo ou não uma atividade nativa, recomendamos que você crie projetos com as ferramentas de compilação tradicionais do Android. Isso ajuda a garantir a compilação e o empacotamento de apps Android com a estrutura correta.
O Android NDK fornece duas possibilidades para implementar atividades nativas:
- O cabeçalho native_activity.h define a versão nativa da classe NativeActivity. Ele contém a interface de callback e as estruturas de dados necessárias para criar a atividade nativa. Como a linha de execução principal do app lida com os callbacks, suas implementações não podem gerar bloqueios. Se isso acontecer, você poderá receber erros do tipo ANR (O app não está respondendo), porque a linha de execução principal não responderá até o retorno do callback.
- O arquivo
android_native_app_glue.h
define uma biblioteca auxiliar estática compilada sobre a interface native_activity.h. Ele gera outra linha de execução, que gerencia elementos como callbacks ou eventos de entrada em um loop de evento. Mover esses eventos para uma linha de execução separada impede que qualquer callback bloqueie sua linha de execução principal.
A fonte <ndk_root>/sources/android/native_app_glue/android_native_app_glue.c
também está disponível, permitindo que você modifique a implementação.
Para mais informações sobre como usar essa biblioteca estática, veja o exemplo de app de
atividade nativa e a documentação correspondente. Para mais informações,
leia também os comentários
no arquivo
<ndk_root>/sources/android/native_app_glue/android_native_app_glue.h
.
Usar a interface native_activity.h
Para implementar uma atividade nativa com a interface native_activity.h:
Crie um diretório
jni/
no diretório raiz do projeto. Ele vai armazenar todos os códigos nativos.Declare sua atividade nativa no arquivo
AndroidManifest.xml
.Como seu app não tem código em Java, defina
android:hasCode
comofalse
.<application android:label="@string/app_name" android:hasCode="false">
Defina o atributo
android:name
da tag de atividade como NativeActivity.<activity android:name="android.app.NativeActivity" android:label="@string/app_name">
O atributo
android:value
da tagmeta-data
especifica o nome da biblioteca compartilhada que contém o ponto de entrada para o app (comomain
em C/C++), omitindo o prefixolib
e o sufixo.so
do nome da biblioteca.<manifest> <application> <activity> <meta-data android:name="android.app.lib_name" android:value="native-activity" /> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
Crie um arquivo para a atividade nativa e implemente a função nomeada na variável ANativeActivity_onCreate. O app chama essa função quando a atividade nativa é iniciada. Essa função, análoga a
main
em C/C++, recebe um ponteiro para uma estrutura NativeActivity, que contém ponteiros de função para as diferentes implementações de callback que você precisa escrever. Defina os ponteiros aplicáveis da função de callback emANativeActivity->callbacks
para as implementações dos callbacks.Defina o campo
ANativeActivity->instance
como o endereço de qualquer instância de dados específicos que você quer usar.Implemente tudo o que a atividade fará depois de iniciada.
Implemente os demais callbacks definidos em
ANativeActivity->callbacks
. Para saber mais sobre quando os callbacks são chamados, consulte Gerenciamento do ciclo de vida da atividade.Desenvolva o restante do app.
Crie um
Android.mk file
no diretóriojni/
do projeto para descrever seu módulo nativo para o sistema de compilação. Para mais informações, consulte Android.mk.Depois de criar um arquivo Android.mk, compile seu código nativo usando o comando
ndk-build
.cd <path>/<to>/<project> $NDK/ndk-build
Compile e instale seu projeto para Android normalmente. Se o código nativo estiver no diretório
jni/
, o script de compilação empacotará automaticamente os arquivos.so
compilados a partir dele no APK.
Outra amostra de código
Para fazer o download de amostras do NDK, consulte Amostras do NDK (link em inglês).