¿Cómo podemos hacer una aplicación de Android usando el lenguaje C ++?

El Android Native Development Kit (NDK) es parte del conjunto de herramientas oficial de Google y analizaremos cuándo el NDK puede ser útil y cómo usarlo en una aplicación de Android.

¿Qué es el NDK?

El NDK es un conjunto de herramientas que permite el desarrollo de aplicaciones de Android usando C, C ++ y otros lenguajes de código nativo, compilando código en aplicaciones que pueden ejecutarse en dispositivos Android. Por lo general, no se recomienda usar el NDK porque las aplicaciones pueden experimentar un impacto en el rendimiento, sufrir problemas de compatibilidad, ser más difíciles de depurar y reducir la flexibilidad. Lo que garantiza el NDK es un aumento en la complejidad de la aplicación y la conectividad de la interfaz con el código nativo.

Las declaraciones anteriores pueden sonar desalentadoras, pero existen buenos casos de uso para el NDK. Esto incluye aplicaciones computacionalmente intensivas como juegos, motores de juegos, procesamiento de señales y simulaciones físicas. Otro buen caso de uso es reutilizar bibliotecas existentes escritas en C / C ++. Esto significa que puede aprovechar una gran colección de bibliotecas de códigos nativos disponibles en línea.

Asegúrese de equilibrar los pros y los contras de usar el NDK antes de decidir si vale la pena la complejidad adicional. Nunca debe basar su decisión en su idioma preferido, incluso si es un experto en C o C ++.

Usando el NDK

Android Studio

Si aún no lo tiene, descargue Android Studio, el IDE oficial de Google.

Paquete NDK

Android Studio solo incluye las herramientas predeterminadas y el SDK, así que descargue e instale el paquete NDK por separado. Hay dos maneras de hacer esto. La primera y más fácil es la opción de instalación automática en la pestaña Herramientas del SDK . Esta es una descarga grande (~ 1 GB), así que asegúrese de tener una buena conexión a Internet y / o paciencia.

La segunda forma es descargar el NDK manualmente desde la página de descargas de NDK. Esto ahorra algo de tiempo debido al menor tamaño de descarga (<.5 GB) pero necesitará algo de configuración. Descargue el paquete NDK apropiado para su plataforma y siga las instrucciones de instalación. Puede colocar el paquete extraído en cualquier lugar que desee, pero recuerde esta ubicación, ya que la necesitará más adelante.

Hola Mundo

Ejecutemos un proyecto de prueba para ver si la instalación de NDK funciona. La carpeta del paquete NDK contiene ejemplos, pero parece que no funcionan de fábrica en Android Studio sin una configuración adicional. En su lugar, importaremos muestras que funcionen desde la pantalla de bienvenida . Estas muestras de NDK de GitHub también se pueden descargar o clonar directamente. Esta colección de muestras tiene una mejor compatibilidad con la última versión de Android Studio.

Seleccione Importar un ejemplo de código de Android y escriba hola en el cuadro de búsqueda para filtrar la lista. Elija Hola JNI de la lista filtrada en la categoría Ndk . Haga clic en Siguiente para editar el nombre de la aplicación y la ubicación del proyecto, luego haga clic en Finalizar .

El JNI

Después de que el código se haya cargado y Gradle se haya sincronizado, echemos un vistazo a la estructura del proyecto resultante. Es posible que haya notado lo que parece ser una discrepancia en el nombre del proyecto. ¿Por qué se llama HelloJNI y no HelloNDK ? ¿Qué es ‘JNI’ y en qué se diferencia del ‘NDK’? La ‘Interfaz nativa de Java’ es un marco que permite que las aplicaciones Java interactúen con el código nativo. El JNI y el NDK trabajan juntos para brindar soporte nativo a las aplicaciones de Android. El NDK es parte del marco de Android, mientras que el JNI está disponible para cualquier aplicación Java, no solo para las aplicaciones de Android.

Dentro del proyecto hay una carpeta llamada jni que contendrá todo el código fuente nativo C o C ++ de la aplicación. El JNI proporciona una interfaz bidireccional. El código C / C ++ puede llamar al código Java, incluidas las bibliotecas estándar de Android, y el código Java puede llamar a las funciones nativas definidas en el código C / C ++. El código nativo se rige por las mismas reglas de seguridad y sandbox que el código Java, por lo que la aplicación no tendrá acceso completo sin restricciones al hardware. Para una discusión más detallada sobre el JNI, lea los artículos de JNI del sitio web para desarrolladores de Android.

ABI

Construyamos y ejecutemos el proyecto en un emulador o exportemos un APK para probarlo en un dispositivo. Aquí está hello-jni ejecutándose en mi Asus Zenfone que utiliza una interfaz binaria de aplicaciones Intel o x86 (ABI). Cuando la aplicación interactúa con código nativo, debe admitir diferentes arquitecturas de CPU. Esto significa que debe compilarse para cada plataforma en la que desea que se ejecute.

Cada ABI corresponde a una arquitectura de destino, que define cómo el código nativo de una aplicación debe comportarse o interactuar con el sistema durante el tiempo de ejecución. Actualmente, el NDK admite las arquitecturas ARMEABI (predeterminado), MIPS y x86. Normalmente, el proyecto debe configurarse manualmente y el código nativo creado para cada plataforma. Esto ya se ha solucionado en el proyecto de muestra, así que simplemente reutilice la muestra y configúrelo como punto de partida para un proyecto. Tiene todos los requisitos básicos ya establecidos para permitir que una aplicación interactúe con el NDK.

Reutilizando Bibliotecas

Como se mencionó anteriormente, la fortaleza del NDK radica en su capacidad para reutilizar bibliotecas C / C ++ existentes, probadas y potentes. Esta característica se encuentra en la etapa experimental en Android Studio y generalmente se recomienda para desarrolladores avanzados. Sin embargo, esto es algo interesante y que vale la pena explorar.

SDL

Simple DirectMedia Layer es una biblioteca de abstracción de hardware de código abierto lanzada hace 18 años. Se usa principalmente para juegos, pero se puede usar para cualquier cosa que involucre gráficos de alto rendimiento. En esta sección, configuraremos un proyecto básico que usa el SDL y puede usarse como plantilla para proyectos más sofisticados en el futuro.

Configuración del proyecto

El primer paso es descargar la fuente SDL desde la página de descarga del código fuente o clonar el repositorio Mercurial con:

hg clone http://hg.libsdl.org/SDL

Una vez finalizada la descarga o el clon, importe el proyecto de Android de muestra (denominado proyecto android ) desde la carpeta SDL en Android Studio, aceptando los valores predeterminados en las pantallas de importación. Una vez creado el proyecto, puede haber un problema de sincronización que implique una versión faltante del SDK. Para resolver esto, abra el Administrador de SDK y descargue la versión de SDK adecuada para el proyecto. En este caso, Android 3.1 (API Nivel 12). Marque la casilla Mostrar detalles del paquete para revelar esta versión porque está marcada como obsoleta. Se puede usar una versión más reciente, pero por ahora sigamos con Android-12 para simplificar las cosas.

Después de instalar el SDK, el proyecto debe sincronizarse sin errores, mostrando un

CONSTRUIR CON ÉXITO

mensaje en la consola. Si encuentra algún otro error, hágamelo saber en los comentarios.

Gradle

Android Studio utiliza Gradle, un sistema de automatización de compilación de código abierto para administrar proyectos y sus resultados. La mayoría de la configuración del proyecto ocurre dentro de los archivos gradle. Agreguemos una configuración manual al proyecto. Abra build.gradle (módulo de aplicación) y agregue el siguiente código debajo de la propiedad buildToolsVersion :

sourceSets {
principal {
jni.srcDirs = []
}
}

Esto ocultará el código nativo en el explorador de proyectos que ayuda a construir manualmente SDL y el código nativo usando ndk-build , que está dentro de la carpeta ndk-bundle . La creación manual de código nativo es el método más confiable sobre las compilaciones automatizadas que utilizan Android Studio y Gradle. El soporte de Gradle para NDK todavía es experimental y no se manejan todos los casos de uso.

Enlace simbólico

Creemos un enlace simbólico dentro de la carpeta app / src / main / jni / del proyecto. Póngale el nombre SDL y apúntelo a la carpeta SDL descargada o clonada anteriormente. La carpeta SDL se puede copiar directamente, pero este método es menos eficiente y propenso a errores. Los archivos de origen están ocultos en Android Studio, por lo que deben abrirse manualmente en un editor externo para realizar las siguientes modificaciones.

http://Android.mk

Android.mk es un archivo de creación simple que describe el código fuente del proyecto y las bibliotecas compartidas para el sistema de compilación. El proyecto ya importado tiene estos archivos de creación por defecto pero con una configuración mínima requerida. Hagamos los cambios en el archivo http://Android.mk de la aplicación principal. Este archivo se encuentra dentro de la carpeta app / src / main / jni / src . Busque la línea que dice YourSourceHere.c y reemplácela por main.c

http://Application.mk

El archivo make http://Application.mk contiene una configuración común a todos los módulos y afecta la forma en que se construye todo el proyecto. Agregue la siguiente línea a http://Application.mk dentro de la carpeta app / src / main / jni / :

APP_PLATFORM: = android-12

Esta configuración de propiedad le dice a ndk-build que la versión de destino mínima es Android 3.1 y apuntará el proyecto a los archivos de encabezado apropiados. Otra configuración para cambiar en http://Application.mk son plataformas de destino adicionales que utilizan la propiedad APP_ABI . Seleccione plataformas de las siguientes o agréguelas todas:

  • arm64-v8a
  • Armeabi
  • armeabi-v7a
  • mips
  • mips64
  • x86
  • x86_64

Agregar soporte para todas estas plataformas le da a la aplicación un mejor alcance, pero dará como resultado un APK más grande.

C Principal

El último paso es agregar un código personalizado que inicializa el SDL y llama a sus funciones para ver si el proyecto funciona. Por conveniencia, reutilicemos este archivo main.c, descargándolo en la carpeta app / src / main / jni / src .

Al abrir main.c , notará que intenta cargar y mostrar una imagen llamada image.bmp . Para admitir esto, cree una carpeta llamada activo dentro de app / src / main y agregue un mapa de bits llamado image.bmp . Utilicé el logotipo de SitePoint.com para esta prueba.

Construyendo y corriendo

Usando la terminal, abra la aplicación / src / main / jni / y ejecute ndk-build NDK_LIBS_OUT=../jniLibs . Este comando crea el código nativo y guarda los archivos de objetos compartidos ( .so ) resultantes en la carpeta jniLibs . Si no se puede encontrar ndk-build , ejecútelo con una ruta completa o agréguelo a la variable de entorno PATH. Una vez finalizada la compilación, cambie a Android Studio e invoque manualmente la sincronización utilizando el elemento de menú Herramientas -> Android -> Proyecto de sincronización con archivos Gradle . Ahora se puede crear un APK utilizando el elemento de menú Compilar -> Compilar APK para probar la aplicación en un dispositivo o emulador. Aquí está mi compilación que se ejecuta en la arquitectura x86:

Conclusión

Como hemos visto, usar NDK con código nativo en una aplicación de Android requiere algo de trabajo, pero trae un mundo de nuevo potencial. Espero haberte mostrado lo suficiente para que aprecies si es apropiado para tu proyecto o no