JNI y Gradle en Android Studio

Estoy tratando de agregar código nativo a mi aplicación. Tengo todo en ../main/jni como estaba en mi proyecto de Eclipse. He agregado ndk.dir=... a mis local.properties . Todavía no he hecho nada más (no estoy seguro de qué más se necesita realmente, así que si me he perdido algo, házmelo saber). Cuando bash y construyo obtengo 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+ – Lo más cerca que al NDK se lo ha llamado ‘magia’

Al tratar de evitar experimental y francamente harto del NDK y de todos sus hackers, me complace que salió 2.2.x de Gradle Build Tools y ahora simplemente funciona. La clave es el argumento ndkBuild ruta ndkBuild en un Android.mk o cambiar ndkBuild por cmake y apuntar el argumento de ruta en un CMakeLists.txt construcció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 obtener más detalles, consulte la página de Google sobre cómo agregar código nativo .

Después de configurar esto correctamente, puede ./gradlew installDebug y listo. También deberás ser consciente de que el NDK se está moviendo a clang ya que gcc ahora está obsoleto en el NDK de Android.

Android Studio Clean and Build Integration: DEPRECATED

Las otras respuestas señalan la forma correcta de evitar la creación automática de archivos Android.mk , pero no logran el paso adicional de integrarse mejor con Android Studio. He agregado la capacidad de limpiar y comstackr desde la fuente 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 supone una disposición estándar del proyecto. Debe ser el pariente de esta ubicación del archivo build.gradle en el directorio jni .

Gradle – para aquellos que tienen problemas

También verifique esta respuesta de desbordamiento de stack .

Es realmente importante que la 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. Además, usa gradlew . Esto protege al desarrollador de una discrepancia en la versión de Gradle. Finalmente, el plugin de gradle debe estar configurado correctamente.

¿Y preguntas cuál es la última versión del plugin Gradle? Verifique 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 archivo gradle/wrapper subdirectorio gradle/wrapper . Este es un gran problema.

ndkDirectory

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

gradle admite la comstackción de ndk generando otro archivo Android.mk con rutas absolutas a sus fonts. NDK admite 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 NDK de gradle es preliminar. Si es así, puede desactivar la comstackción ndk de gradle estableciendo:

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

para poder llamar a ndk-build usted mismo e integrar libs desde libs /.

Por cierto, ¿tiene algún problema comstackndo para x86? Veo que no lo ha incluido en su APP_ABI.

En mi caso, estoy en Windows y seguir la respuesta de Cameron de arriba solo funciona si usa el nombre completo de ndk-build que es ndk-build.cmd . Debo limpiar y reconstruir el proyecto , luego reiniciar el emulador antes de hacer funcionar la aplicación (de hecho, importé la muestra HelloJni de NDK a 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 en OSX fue la versión gradle. Gradle estaba ignorando mi Android.mk. Entonces, para anular esta opción, y usar mi marca, he ingresado a esta línea:

sourceSets.main.jni.srcDirs = []

dentro de la etiqueta de 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 intenté, funciona … sin embargo, mis variables no aparecen en el depurador. Todavía puedo consultarlos a través de la línea de comandos.

Debes hacer algo como esto:

 externalNativeBuild{ ndkBuild{ path "Android.mk" } } defaultConfig { externalNativeBuild{ 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" } } } 

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

NB: la anidación adicional de externalNativeBuild dentro de defaultConfig fue un cambio radical introducido con Android Studio 2.2 Preview 5 (8 de julio de 2016). Vea las notas de la versión en el enlace de arriba.

En el módulo build.gradle, en el campo de la tarea, aparece un error a menos que use:

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

Veo 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 en realidad estaba importando.