JNI y Gradle en Android Studio

Estoy intentando agregar código nativo a mi aplicación. Tengo todo en ../main/jni como estaba en mi proyecto de Eclipse. He añadido ndk.dir=... a mi local.properties . No he hecho nada más (no estoy seguro de qué más es realmente necesario, así que si he perdido algo, házmelo saber). Cuando intento y construyo consigo este error:

 Execution failed for task ':app:compileDebugNdk'. > com.android.ide.common.internal.LoggedErrorException: Failed to run command: /Users/me/android-ndk-r8e/ndk-build NDK_PROJECT_PATH=null APP_BUILD_SCRIPT=/Users/me/Project/app/build/ndk/debug/Android.mk APP_PLATFORM=android-19 NDK_OUT=/Users/me/Project/app/build/ndk/debug/obj NDK_LIBS_OUT=/Users/me/Project/app/build/ndk/debug/lib APP_ABI=all Error Code: 2 Output: make: *** No rule to make target `/Users/me/Project/webapp/build/ndk/debug//Users/me/Project/app/src/main/jni/jni_part.cpp', needed by `/Users/me/Project/app/build/ndk/debug/obj/local/armeabi-v7a/objs/webapp//Users/me/Project/app/src/main/jni/jni_part.o'. Stop. 

¿Que necesito hacer?

Android.mk:

 LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) # OpenCV OPENCV_CAMERA_MODULES:=on OPENCV_INSTALL_MODULES:=on include .../OpenCV-2.4.5-android-sdk/sdk/native/jni/OpenCV.mk LOCAL_MODULE := native_part LOCAL_SRC_FILES := jni_part.cpp LOCAL_LDLIBS += -llog -ldl include $(BUILD_SHARED_LIBRARY) 

Application.mk:

 APP_STL := gnustl_static APP_CPPFLAGS := -frtti -fexceptions APP_ABI := armeabi armeabi-v7a APP_PLATFORM := android-8 

Gradle Build Tools 2.2.0+ – El más cercano el NDK ha llegado a ser llamado "magia"

Al tratar de evitar experimental y francamente harto de la NDK y todo su hackery estoy feliz de que 2.2.x de las herramientas de compilación de Gradle salió y ahora sólo funciona. La clave es el argumento externalNativeBuild y apuntando a ndkBuild path en un Android.mk o cambia ndkBuild a cmake y señala el argumento path en un CMakeLists.txt compilación CMakeLists.txt .

 android { compileSdkVersion 19 buildToolsVersion "25.0.2" defaultConfig { minSdkVersion 19 targetSdkVersion 19 ndk { abiFilters 'armeabi', 'armeabi-v7a', 'x86' } externalNativeBuild { cmake { cppFlags '-std=c++11' arguments '-DANDROID_TOOLCHAIN=clang', '-DANDROID_PLATFORM=android-19', '-DANDROID_STL=gnustl_static', '-DANDROID_ARM_NEON=TRUE', '-DANDROID_CPP_FEATURES=exceptions rtti' } } } externalNativeBuild { cmake { path 'src/main/jni/CMakeLists.txt' } //ndkBuild { // path 'src/main/jni/Android.mk' //} } } 

Para ver más detalles, visite la página de Google al agregar código nativo .

Después de esto se configura correctamente, puede ./gradlew installDebug y apagado. También tendrá que ser consciente de que el NDK se está moviendo a clang desde gcc está ahora en desuso en el Android NDK.

Android Studio Limpieza y integración de la compilación – DEPRECATED

Las otras respuestas señalan la forma correcta de evitar la creación automática de archivos de Android.mk , pero no logran el paso extra de integrarse mejor con Android Studio. He añadido la capacidad de realmente limpiar y construir desde el origen sin necesidad de ir a la línea de comandos. Su archivo local.properties necesitará tener ndk.dir=/path/to/ndk

 apply plugin: 'com.android.application' android { compileSdkVersion 14 buildToolsVersion "20.0.0" defaultConfig { applicationId "com.example.application" minSdkVersion 14 targetSdkVersion 14 ndk { moduleName "YourModuleName" } } sourceSets.main { jni.srcDirs = [] // This prevents the auto generation of Android.mk jniLibs.srcDir 'src/main/libs' // This is not necessary unless you have precompiled libraries in your project. } task buildNative(type: Exec, description: 'Compile JNI source via NDK') { def ndkDir = android.ndkDirectory commandLine "$ndkDir/ndk-build", '-C', file('src/main/jni').absolutePath, // Change src/main/jni the relative path to your jni source '-j', Runtime.runtime.availableProcessors(), 'all', 'NDK_DEBUG=1' } task cleanNative(type: Exec, description: 'Clean JNI object files') { def ndkDir = android.ndkDirectory commandLine "$ndkDir/ndk-build", '-C', file('src/main/jni').absolutePath, // Change src/main/jni the relative path to your jni source 'clean' } clean.dependsOn 'cleanNative' tasks.withType(JavaCompile) { compileTask -> compileTask.dependsOn buildNative } } dependencies { compile 'com.android.support:support-v4:20.0.0' } 

El directorio src/main/jni asume un diseño estándar del proyecto. Debe ser el relativo desde esta ubicación de archivo jni directorio jni .

Gradle – para aquellos que tienen problemas

También compruebe esta respuesta de desbordamiento de pila .

Es muy importante que su versión gradle y la configuración general sean correctas. Si tienes un proyecto anterior, recomiendo crear uno nuevo con el último Android Studio y ver lo que Google considera el proyecto estándar. También, use gradlew . Esto protege al desarrollador de un desajuste de versión de gradle. Finalmente, el plugin gradle debe estar configurado correctamente.

¿Y usted pregunta cuál es la última versión del plugin gradle? Revise la página de herramientas y edite la versión en consecuencia.

Producto final – / build.gradle

 // Top-level build file where you can add configuration options common to all sub-projects/modules. // Running 'gradle wrapper' will generate gradlew - Getting gradle wrapper working and using it will save you a lot of pain. task wrapper(type: Wrapper) { gradleVersion = '2.2' } // Look Google doesn't use Maven Central, they use jcenter now. buildscript { repositories { jcenter() } dependencies { classpath 'com.android.tools.build:gradle:1.2.0' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files } } allprojects { repositories { jcenter() } } 

Asegúrese de que gradle wrapper genera el gradlew file y gradle/wrapper . Este es un gran gotcha.

NdkDirectorio

Esto ha surgido varias veces, pero android.ndkDirectory es la forma correcta de obtener la carpeta después de 1.1. Migrar proyectos de Gradle a la versión 1.0.0 . Si está utilizando una versión experimental o antigua del complemento, su kilometraje puede variar.

Gradle soporta la compilación ndk generando otro archivo Android.mk con rutas absolutas a sus fuentes. NDK soporta rutas absolutas desde r9 en OSX, r9c en Windows, por lo que necesita actualizar su NDK a r9 +.

Puede encontrarse con otros problemas, ya que el soporte de NDK por gradle es preliminar. Si es así, puede desactivar la compilación ndk de gradle mediante la configuración:

 sourceSets.main { jni.srcDirs = [] jniLibs.srcDir 'src/main/libs' } 

Para poder llamar a ndk-build e integrar libs desde libs /.

BTW, ¿tiene algún problema de compilación para x86? Veo que no lo ha incluido en su APP_ABI.

En mi caso, estoy en Windows y siguiendo la respuesta de Cameron anterior sólo funciona si utiliza el nombre completo de la ndk-build que es ndk-build.cmd . Tengo que limpiar y reconstruir el proyecto , luego reiniciar el emulador antes de conseguir que la aplicación funcione (de hecho, importé la muestra HelloJni de NDK, en Android Studio). Sin embargo, asegúrese de que la ruta a NDK no contenga espacio .

Finalmente, mi build.gradle está completo como se muestra a continuación:

 apply plugin: 'com.android.application' android { compileSdkVersion 21 buildToolsVersion "21.1.2" defaultConfig { applicationId "com.example.hellojni" minSdkVersion 4 targetSdkVersion 4 ndk { moduleName "hello-jni" } testApplicationId "com.example.hellojni.tests" testInstrumentationRunner "android.test.InstrumentationTestRunner" } sourceSets.main { jni.srcDirs = [] // This prevents the auto generation of Android.mk // sourceSets.main.jni.srcDirs = [] jniLibs.srcDir 'src/main/libs' // This is not necessary unless you have precompiled libraries in your project. } task buildNative(type: Exec, description: 'Compile JNI source via NDK') { def ndkDir = android.plugin.ndkFolder commandLine "$ndkDir/ndk-build.cmd", '-C', file('src/main/jni').absolutePath, // Change src/main/jni the relative path to your jni source '-j', Runtime.runtime.availableProcessors(), 'all', 'NDK_DEBUG=1' } task cleanNative(type: Exec, description: 'Clean JNI object files') { def ndkDir = android.plugin.ndkFolder commandLine "$ndkDir/ndk-build.cmd", '-C', file('src/main/jni').absolutePath, // Change src/main/jni the relative path to your jni source 'clean' } clean.dependsOn 'cleanNative' tasks.withType(JavaCompile) { compileTask -> compileTask.dependsOn buildNative } } dependencies { compile 'com.android.support:support-v4:21.0.3' } 

Mi problema con OSX fue la versión gradle. Gradle estaba ignorando mi Android.mk. Por lo tanto, con el fin de anular esta opción, y utilizar mi marca en su lugar, he entrado en esta línea:

SourceSets.main.jni.srcDirs = []

Dentro de la etiqueta android en build.gradle .

He perdido mucho tiempo en esto!

Android Studio 2.2 salió con la capacidad de usar ndk-build y cMake. Sin embargo, tuvimos que esperar hasta 2.2.3 para el soporte de Application.mk. Lo he probado, funciona … sin embargo, mis variables no aparecen en el depurador. Todavía puedo consultar a través de línea de comandos sin embargo.

Necesitas hacer algo como esto:

 externalNativeBuild{ ndkBuild{ path "Android.mk" } } defaultConfig { ndkBuild { arguments "NDK_APPLICATION_MK:=Application.mk" cFlags "-DTEST_C_FLAG1" "-DTEST_C_FLAG2" cppFlags "-DTEST_CPP_FLAG2" "-DTEST_CPP_FLAG2" abiFilters "armeabi-v7a", "armeabi" } } 

Consulte http://tools.android.com/tech-docs/external-c-builds

En el módulo build.gradle, en el campo de tarea, obtengo un error a menos que utilice:

 def ndkDir = plugins.getPlugin('com.android.application').sdkHandler.getNdkFolder() 

Veo a la gente usando

 def ndkDir = android.plugin.ndkFolder 

y

 def ndkDir = plugins.getPlugin('com.android.library').sdkHandler.getNdkFolder() 

Pero ninguno de esos funcionó hasta que lo cambié al plugin que estaba importando realmente.

  • Temporizadores Android NDK
  • Cómo vincular cualquier biblioteca en la aplicación ndk
  • java.lang.UnsatisfiedLinkError: No se ha encontrado ninguna implementación debido a que la biblioteca no está cargando
  • Integración o compilación de instrucciones para libjpeg-turbo en Android
  • JNI: Del código C a Java y JNI
  • Androide ndk multitouch
  • JNI se bloquea al llamar a CallVoidMethod
  • JNI proguard obfuscation
  • Redireccionamiento de STDIN y STDOUT del programa C en Android
  • Uso de bibliotecas pre-construidas y jni en Android Studio
  • Pasar una cadena al código C en Android NDK
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.