Gradle Android Build System Problemas de NDK

Voy a ser el primero en admitir que no soy muy experto en Gradle y el nuevo sistema de compilación de Android, pero, por desgracia, tuve que pasar a él (de ant) ​​debido a la edición 21479 ( https://code.google .com / p / android / issues / detail? Id = 21479 ) y el comentario "Esto no se arreglará.Nos estamos centrando en terminar el sistema de compilación basado en Gradle que reemplazará a Ant." Por desgracia, no pude conseguir las cosas para construir de nuevo después de agregar la biblioteca de publicidad Millenium Media. Esto era además de la biblioteca OpenCV de Android, la biblioteca de cifrado de Chilkat y la biblioteca de soporte v4, pero la biblioteca de MMedia era la que rompía todo.

Por lo tanto, pensé, una buena razón para migrar a la nueva Gradle basado en sistema de construcción. Desafortunadamente, a pesar de dejar un sistema de construcción de hormigón roto, el nuevo sistema no parece estar terminado todavía; Particularmente el soporte ndk.

La aplicación en la que estoy trabajando utiliza OpenCV para el procesamiento de imágenes y un par de operaciones funcionan demasiado lentamente a menos que estén compiladas en nativo (MUCHOS movimientos de memoria y comparaciones que son demasiado lentas en el límite de JNI). Por lo tanto, en lugar de tratar de pasar los datos hacia atrás y hacia adelante entre la VM y el código nativo, dejo todas estas cosas en el lado nativo y sólo tiene una llamada de la máquina virtual para obtener los resultados.

El primer problema fue obtener las cosas ndk para compilar. No pude conseguir los ajustes en el cierre del ndk para trabajar así que tuve que recurrir a usar el comando ndk-build y ejecutarlo como una tarea:

task ndkBuild(type: Exec) { String MainDirectory = System.getProperty("user.dir") + '/app/src/main' println "Main app directory for NDK build " + MainDirectory if (Os.isFamily(Os.FAMILY_WINDOWS)) { commandLine 'gradle-ndk-build.cmd', MainDirectory, '-j' } else { commandLine 'gradle-ndk-build', MainDirectory, '-j' } } tasks.withType(JavaCompile) { compileTask -> compileTask.dependsOn ndkBuild } 

Esto funciona perfectamente; Compila el código ndk y genera la biblioteca .so sin error. Desafortunadamente, no pondrá el archivo resultante .so en el paquete final. Pone todas las otras bibliotecas nativas en bien, pero no esta – no idea de por qué sin embargo.

He encontrado un montón de presuntos arreglos para este problema, tales como:

 tasks.withType(com.android.build.gradle.tasks.PackageApplication) { pkgTask -> pkgTask.jniFolders = new HashSet<File>() pkgTask.jniFolders.add(new File(buildDir, 'native-libs')) } 

Pero agregar esto sólo resulta en un archivo apk con NO librerías nativas en absoluto. He visto que otras personas tienen el mismo problema (como https://groups.google.com/forum/#!msg/adt-dev/QbDHM41QT2E/J4jHCC_RuIEJ ), pero he probado todas las soluciones propuestas y ninguna de ellas trabaja para mi.

Como no cambio el código nativo muy a menudo, acabo de hacer un hack para copiar la librería nativa generada (libndklib.so) desde app / src / main / libs a / app / src / main / jni después de haber sido Compilado; Entonces termina en el paquete apk. Obviamente, esto es un poco desagradable como, si alguien toma este código, se preguntarán por qué sus cambios en el código nativo nunca aparecen en la aplicación.

Por lo tanto, mis preguntas son: ¿Hay algo que puedo ejecutar en el script gradle que se ejecutará después de ejecutar el comando ndk (gradle-ndk-build) que copiará los archivos generados desde app / src / main / Libs / armeabi / libndklib.so a /app/src/main/jni/armeabi/libndklib.so (para cada una de las arquitecturas – armeabi, armeabi-v7, x86, mips) para que termine en el paquete apk?

O

¿Hay alguna manera de hacer el cierre de Ndk Gradle manejar el siguiente ndk hacer archivos correctamente: Application.mk

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

Android.mk

 LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) # OpenCV OPENCV_CAMERA_MODULES:=on OPENCV_INSTALL_MODULES:=on OPENCV_LIB_TYPE:=SHARED include /home/myname/tools/OpenCV-2.4.8-android-sdk/sdk/native/jni/OpenCV.mk LOCAL_MODULE := ndklib LOCAL_SRC_FILES := ndklib.cpp motion.cpp LOCAL_LDLIBS += -lm -llog include $(BUILD_SHARED_LIBRARY) # Add prebuilt chilkat library include $(CLEAR_VARS) LOCAL_MODULE := lib-chilkat LOCAL_SRC_FILES := $(TARGET_ARCH_ABI)/libchilkatemail.so include $(PREBUILT_SHARED_LIBRARY) 

Miré la fuente de Gradle para el plug-in pero no pude ver muchas de estas directivas soportadas.

O

¿Puedo añadir algún tipo de hack que se ejecuta al final del script Gradle que sólo fuerza la copia apropiada de libndklib.so (para la arquitectura correcta) en el apk generado? Puedo vivir con este último hasta que el material ndk esté terminado para el complemento de Android para la compilación gradle.

========================================

Editar – Después de la respuesta de ph0b Este es el archivo build.gradle final con el mod propuesto en él. Crea el .apk perfectamente build.gradle (en el directorio de la aplicación)

 buildscript { repositories { mavenCentral() } dependencies { classpath 'com.android.tools.build:gradle:0.9.+' } } apply plugin: 'android' import org.apache.tools.ant.taskdefs.condition.Os android { compileSdkVersion 19 buildToolsVersion "19.0.3" signingConfigs { debug { storeFile file("dbgkeystore") storePassword "nopass" keyAlias "mainkeyname" keyPassword "nopass" } release { storeFile file("keystore") storePassword "xxxxxxxx" keyAlias "mainkeyname" keyPassword "yyyyyyyy" } } // Autoincrement the version properties file // ****************************************** def versionPropsFile = file('version.properties') def code = 1 def majorversion = 1 def minorversion = 1 defaultConfig { versionCode code versionName "${majorversion}.${minorversion}.${code}" minSdkVersion 10 targetSdkVersion 19 } buildTypes { release { runProguard true proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt' signingConfig signingConfigs.release } debug { runProguard false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt' packageNameSuffix ".debug" versionNameSuffix "-debug" signingConfig signingConfigs.debug } } sourceSets { main { jni.srcDirs = [] // jniLibs.srcDir 'src/main/jni' // - Doesn't work, leaves out the .so files generated by ndk-build jniLibs.srcDir 'src/main/libs' } } flavorDimensions "version", "abi" productFlavors { pro { flavorDimension "version" packageName "org.somedomainname.myAppPro1" } lite { flavorDimension "version" packageName "org.somedomainname.myAppLite1" } arm { flavorDimension "abi" ndk { abiFilter "armeabi" } if (versionPropsFile.canRead()){ def Properties versionProps = new Properties() versionProps.load(new FileInputStream(versionPropsFile)) code = versionProps['VERSION_CODE'].toInteger() + 1 versionProps['VERSION_CODE']=code.toString() versionProps.store(versionPropsFile.newWriter(), null) versionCode code versionName "${majorversion}.${minorversion}.${code}" } else { throw new GradleException("Could not read version.properties!") } } armv7 { flavorDimension "abi" ndk { abiFilter "armeabi-v7a" } if (versionPropsFile.canRead()){ def Properties versionProps = new Properties() versionProps.load(new FileInputStream(versionPropsFile)) code = versionProps['VERSION_CODE'].toInteger() + 1 versionProps['VERSION_CODE']=code.toString() versionProps.store(versionPropsFile.newWriter(), null) versionCode code versionName "${majorversion}.${minorversion}.${code}" } else { throw new GradleException("Could not read version.properties!") } } x86 { flavorDimension "abi" ndk { abiFilter "x86" } if (versionPropsFile.canRead()){ def Properties versionProps = new Properties() versionProps.load(new FileInputStream(versionPropsFile)) code = versionProps['VERSION_CODE'].toInteger() + 1 versionProps['VERSION_CODE']=code.toString() versionProps.store(versionPropsFile.newWriter(), null) versionCode code versionName "${majorversion}.${minorversion}.${code}" } else { throw new GradleException("Could not read version.properties!") } } } lintOptions { checkReleaseBuilds false // Or, if you prefer, you can continue to check for errors in release builds, // but continue the build even when errors are found: abortOnError false } repositories { mavenCentral() flatDir { dirs '/home/myname/maindrive/work/dynamic/android/UtilLib/aarlib' } } dependencies { compile 'com.android.support:appcompat-v7:+' compile fileTree(dir: 'libs', include: ['*.jar']) // Note: org.somedomainname.UtilLib on the depency below is ignored when usng flatdir compile 'org.somedomainname.UtilLib:library:1.0.0@aar' } task ndkBuild(type: Exec) { String MainDirectory = System.getProperty("user.dir") + '/app/src/main' println '************************************************************************' println "Main app directory for NDK build " + MainDirectory println '************************************************************************' if (Os.isFamily(Os.FAMILY_WINDOWS)) { commandLine 'gradle-ndk-build.cmd', MainDirectory, '-j' } else { commandLine 'gradle-ndk-build', MainDirectory, '-j' } } tasks.withType(JavaCompile) { compileTask -> compileTask.dependsOn ndkBuild } android.applicationVariants.all { variant -> variant.assemble.doLast { rename_and_moveout_apk(variant) } } // allprojects { // tasks.withType(Compile) { // options.compilerArgs << "-Xlint:deprecation" // } // } def rename_and_moveout_apk(targetVariant) { // replace output apk name to <product>-<version>-<buildtype>-<githash>.apk def versionSuffix = targetVariant.buildType.versionNameSuffix ? targetVariant.buildType.versionNameSuffix : "" def versionName = targetVariant.mergedFlavor.versionName + versionSuffix; if (targetVariant.zipAlign) { def apkFinal = targetVariant.outputFile; def apkFinalNewName = "myApp-" + apkFinal.name.replace(targetVariant.buildType.name, versionName); copy { from "$apkFinal" into "$rootProject.projectDir/apk_release" rename ("$apkFinal.name", "$apkFinalNewName") println "*************** Renaming zipalign apk file from: ${apkFinal.name} to ${apkFinalNewName}" } } } 

Gradle-ndk-build (versión modificada de ndk-build usada para depurar los parámetros)

 #!/bin/bash export NDK_PROJECT_PATH=$1 export NDK_PROJECT_DIRECTORY=$1 bash -c "ndk-build" 

Estructura del Directorio

 ------ apk_release ------ app -- -- ---- src -- ------ lite -- -- -- ---- java -- -- -- ---- org -- -- -- ---- somedomainname -- -- -- ---- myApp -- ------ main -- -- ------ assets -- -- ------ java -- -- -- -- ---- org -- -- -- ------ chilkatsoft -- -- -- -- ---- somedomainname -- -- -- -- ---- myApp -- -- ------ jni -- -- -- ------ armeabi -- -- -- ------ armeabi-v7a -- -- -- ------ mips -- -- -- -- ---- x86 -- -- ------ libs -- -- -- ------ armeabi -- -- -- ------ armeabi-v7a -- -- -- ------ mips -- -- -- -- ---- x86 -- -- ------ obj -- -- -- -- ---- local -- -- -- ------ armeabi -- -- -- -- -- ---- objs -- -- -- -- -- ---- ndklib -- -- -- ------ armeabi-v7a -- -- -- -- -- ---- objs -- -- -- -- -- ---- ndklib -- -- -- ------ mips -- -- -- -- -- ---- objs -- -- -- -- -- ---- ndklib -- -- -- -- ---- x86 -- -- -- -- ---- objs -- -- -- -- ---- ndklib -- -- -- ---- res -- -- ------ drawable -- -- ------ drawable-hdpi -- -- ------ drawable-ldpi -- -- ------ drawable-mdpi -- -- ------ drawable-xhdpi -- -- ------ drawable-xxhdpi -- -- ------ layout -- -- ------ raw -- -- ------ values -- -- -- ---- xml -- -- ---- pro -- -- ---- java -- -- ---- somedomainname -- -- ---- myApp 

Gradle buscará automáticamente los archivos jniLibs/ABI/ dentro de jniLibs/ABI/ .

Puede cambiar este comportamiento para que use su directorio normal de libs estableciéndolo dentro del archivo build.gradle :

 android { sourceSets.main { jniLibs.srcDir 'src/main/libs' } } 
  • Detección de objetos Android OpenCV
  • Cómo encontrar las esquinas de un objeto Rect en openCV?
  • Android - Detección de funciones de cara
  • Android OpenCV Buscar contornos
  • Rotar la imagen desde los datos del sensor de orientación
  • Detecta el movimiento de una persona e identifica sus partes del cuerpo moviéndose hacia la cámara en Android
  • SIGNAL 11 SIGSEGV código = 2 crash Android
  • ¿Cómo obtener el nivel de Compensación de exposición de la cámara del teléfono Android, a través de Java, cuando se toma la foto?
  • Ejemplo de OpenCV Template Matching en Android
  • Eclipse da error al usar GaussianBlur con OpenCV para Android
  • Android "No hay tal archivo o directorio" error?
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.