Antes de comenzar
En esta guía, se asume que ya conoces los conceptos inherentes a la programación nativa y al desarrollo de Android.
Introducción
En esta sección, se proporciona una explicación detallada del funcionamiento del NDK. Android NDK es un conjunto de herramientas que te permiten incorporar código C o C++ ("código nativo") a tus apps de Android. La capacidad para usar código nativo en apps de Android puede ser particularmente útil para los desarrolladores que deseen realizar una o varias de las siguientes acciones:
- Conectar sus apps entre plataformas.
- Reutilizar bibliotecas existentes o proporcionar sus propias bibliotecas para reutilizarlas.
- Aumentar el rendimiento en ciertos casos, en especial los de mayor exigencia computacional, como el de los juegos.
Cómo funciona
En esta sección, se presentan los componentes principales que se usan en la compilación de una app nativa para Android, y se describen los procesos de compilación y empaquetado.
Componentes principales
Debes comprender los siguientes componentes a medida que compilas tu app:
- Bibliotecas compartidas nativas: El NDK compila estas bibliotecas, o archivos
.so
, a partir de tu código fuente C/C++. - Bibliotecas estáticas nativas: El NDK también puede compilar bibliotecas estáticas, o archivos
.a
, que puedes vincular con otras bibliotecas. - Interfaz nativa de Java (JNI): Es la interfaz mediante la cual los componentes Java y C++ se comunican entre sí. En esta guía, se asume que ya conoces la JNI. Para obtener información sobre ella, consulta la Especificación de la interfaz nativa Java.
- Interfaz binaria de aplicaciones (ABI): La ABI define exactamente cómo se espera que el código máquina de tu app interactúe con el sistema en el tiempo de ejecución. El NDK compila archivos
.so
con estas definiciones. Las diferentes ABI corresponden a las distintas arquitecturas: El NDK incluye compatibilidad con ABI para ARM de 32 bits, AArch64, x86 y x86-64. Para obtener más información, consulta Administración de ABI. - Manifiesto: Si escribes una app sin componente Java, debes declarar la clase
NativeActivity
en el manifiesto. En la sección "Cómo usar la interfaznative_activity.h
" de Apps y actividades nativas se proporciona información detallada sobre cómo hacerlo.
Fluir
El flujo general para desarrollar una app nativa para Android es el siguiente:
- Diseña tu app y decide las partes que implementarás en Java, así como las que implementarás como código nativo.
Nota: Si bien es posible evitar el uso de Java completamente, quizá te resulte útil el marco de trabajo de Java para Android para tareas que incluyen el control de la pantalla y la interfaz de usuario.
- Crea un proyecto de aplicación para Android como lo harías en cualquier otro proyecto de Android.
- Si escribes una app sólo con código nativo, declara la clase
NativeActivity
enAndroidManifest.xml
. Para obtener más información, consulta Apps y actividades nativas. - Crea un archivo
Android.mk
que describa la biblioteca nativa y, también, incluya el nombre, los indicadores, las bibliotecas vinculadas y los archivos de origen que se compilarán en el directorio "JNI". - De manera opcional, puedes crear un archivo
Application.mk
si configuras las ABI de destino, la cadena de herramientas, el modo de lanzamiento y depuración, y la STL.- ABI: todas las ABI que no están obsoletas
- Cadena de herramientas: Clang
- Modo: Lanzamiento
- STL: system
- Coloca tu archivo de origen nativo en el directorio
jni
del proyecto. - Usa ndk-build para compilar las bibliotecas (
.so
,.a
) nativas. - Compila el componente de Java, que produce el archivo
.dex
ejecutable. - Integra todo en un archivo APK que contenga
.so
,.dex
y otros archivos necesarios para que tu app funcione.
Aplicaciones y actividades nativas
El SDK de Android proporciona una clase de ayuda, NativeActivity
, que te permite escribir una actividad completamente nativa. NativeActivity
maneja la comunicación entre el marco de trabajo de Android y tu código nativo, de manera que no tengas que crear una subclase ni llamar a sus métodos Lo único que debes hacer es declarar que tu app sea nativa en el archivo AndroidManifest.xml
y comenzar a crearla.
Una app de Android que usa NativeActivity
aún se ejecuta en su propia máquina virtual, en una zona de pruebas separada de las demás apps. Por lo tanto, aún puedes acceder a las API del marco de trabajo de Android por medio de JNI. Sin embargo, en algunos casos (como sucede con sensores, eventos de entrada y elementos), el NDK proporciona interfaces nativas que puedes usar en lugar de tener que realizar llamadas en toda la JNI. Para obtener más información, consulta API nativas del NDK de Android.
Independientemente de que desarrolles una actividad nativa o no, te recomendamos crear tus proyectos con las herramientas de compilación de Android tradicionales. De esta manera, podrás garantizar que las apps de Android se compilen y empaqueten con la estructura correcta.
Android NDK te ofrece dos opciones para implementar tu actividad nativa:
- El encabezado
native_activity.h
define la versión nativa de la claseNativeActivity
. Contiene la interfaz de devolución de llamada y las estructuras de datos que necesitas para crear tu actividad nativa. Debido a que el subproceso principal de tu app controla las devoluciones de llamada, las implementaciones de estas no deben generar bloqueos. Si lo hacen, podrías recibir errores ANR (la aplicación no responde), ya que el subproceso principal no responderá hasta que se muestre la devolución de llamada. - El archivo
android_native_app_glue.h
define una biblioteca auxiliar estática compilada encima de la interfaz denative_activity.h
. Genera otro subproceso que controla, por ejemplo, las devoluciones de llamadas o los eventos de entrada en un bucle de eventos. Si mueves estos eventos a un subproceso independiente evitarás que las devoluciones de llamadas bloqueen tu subproceso principal.
El origen <ndk_root>/sources/android/native_app_glue/android_native_app_glue.c
también está disponible, lo que te permite modificar la implementación.
Para obtener más información sobre cómo usar esta biblioteca estática, explora la app de muestra native-activity y su documentación. Podrás acceder a más contenido en los comentarios del archivo <ndk_root>/sources/android/native_app_glue/android_native_app_glue.h
.
Uso de la interfaz native_activity.h
Para implementar una actividad nativa con la interfaz native_activity.h
, haz lo siguiente:
- Crea un directorio
jni/
en el directorio raíz de tu proyecto. Este directorio almacena todo tu código nativo. - Declara tu actividad nativa en el archivo
AndroidManifest.xml
. - Crea un archivo para tu actividad nativa y, luego, implementa esta función nombrada en la variable
ANativeActivity_onCreate
. La aplicación llama esta función cuando se inicia la actividad nativa. Esta función, que es análoga amain
en C/C++, recibe un puntero a una estructuraANativeActivity
, que contiene punteros de función a distintas implementaciones de devoluciones de llamadas que debes escribir. Configura los punteros de la función de devolución de llamada correspondientes enANativeActivity->callbacks
para las implementaciones de las devoluciones de llamadas. - Establece el campo
ANativeActivity->instance
con la dirección de cualquier instancia de datos específicos que quieras usar. - Implementa todas las demás acciones que desees que tu actividad realice al iniciarse.
- Implementa el resto de las devoluciones de llamada que estableciste en
ANativeActivity->callbacks
. Para obtener más información sobre cuándo se debe llamar a las devoluciones de llamada, consulta Cómo administrar el ciclo de vida de la actividad. - Desarrolla el resto de tu aplicación.
- Crea un
Android.mk file
en el directoriojni/
de tu proyecto para describir tu módulo nativo al sistema de compilación. Para obtener más información, consulta Android.mk. - Una vez que tengas un archivo
Android.mk
, compila tu código nativo con el comandondk-build
. - Compila e instala tu proyecto para Android como lo haces habitualmente. Si tu código nativo se encuentra en el directorio
jni/
, la secuencia de comandos de compilación empaqueta automáticamente los archivos.so
compilados a partir de ella en el APK.
Como tu app no tiene código Java, establece android:hasCode
a false
.
<application android:label="@string/app_name" android:hasCode="false">
Debes establecer el atributo android:name
de la etiqueta de actividad a NativeActivity
.
<activity android:name="android.app.NativeActivity" android:label="@string/app_name">
Nota: Puedes generar la subclase NativeActivity
. Si lo haces, usa el nombre de la subclase en lugar de NativeActivity
.
El atributo android:value
de la etiqueta meta-data
especifica el nombre de la biblioteca compartida que contiene el punto de entrada para la app (como C/C++ main
), y omite el prefijo lib
y el sufijo .so
del nombre de la biblioteca.
<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>
$ cd <path>/<to>/<project> $ <ndk>/ndk-build
Código de ejemplo adicional
Para descargar muestras del NDK, consulta Muestras de NDK.