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?
- No se encontró JNI_OnLoad en ... saltando init
- JNI ERROR (bug de la aplicación): desbordamiento de la tabla de referencia local (máx = 512)
- El proceso de alojamiento del servicio de cámara ha muerto inesperadamente
- ¿Cuál es la mejor manera de guardar JNIEnv *
- Enviar int s entre Java y C
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
- Uso de pjsip con android
- Problema para crear NDK con C ++ en Android
- Java.lang.UnsatisfiedLinkError: Método nativo no encontrado: Error en jni ()
- El mejor enfoque para cargar múltiples bibliotecas nativas en la aplicación para Android
- ¿Cómo utilizo JNI con la biblioteca AAR?
- Pruebas unitarias Llamadas JNI
- Android ICS: intento de error JNI para usar referencia local obsoleta 0x1
- No se pueden cargar archivos de biblioteca .so al hacer una aplicación de sistema
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.