android-studio agregar - ¿Cómo incluir la biblioteca * .so en Android Studio?





aar last (8)


He resuelto un problema similar utilizando dependencias de lib nativas externas que se empaquetan dentro de archivos jar. A veces, estas bibliotecas dependen de la arquitectura y se empaquetan juntas en un solo contenedor, a veces se dividen en varios archivos jar. así que escribí algunos buildscript para escanear las dependencias de jar para libs nativas y ordenarlas en las carpetas de lib de Android correctas. Además, esto también proporciona una forma de descargar dependencias que no se encuentran en los repos de maven, que actualmente es útil para hacer que JNA trabaje en Android porque no todos los archivos jar nativos están publicados en repositorios maven públicos.

android {
    compileSdkVersion 23
    buildToolsVersion '24.0.0'

    lintOptions {
        abortOnError false
    }


    defaultConfig {
        applicationId "myappid"
        minSdkVersion 17
        targetSdkVersion 23
        versionCode 1
        versionName "1.0.0"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }

    sourceSets {
        main {
            jniLibs.srcDirs = ["src/main/jniLibs", "$buildDir/native-libs"]
        }
    }
}

def urlFile = { url, name ->
    File file = new File("$buildDir/download/${name}.jar")
    file.parentFile.mkdirs()
    if (!file.exists()) {
        new URL(url).withInputStream { downloadStream ->
            file.withOutputStream { fileOut ->
                fileOut << downloadStream
            }
        }
    }
    files(file.absolutePath)
}
dependencies {
    testCompile 'junit:junit:4.12'
    compile 'com.android.support:appcompat-v7:23.3.0'
    compile 'com.android.support:design:23.3.0'
    compile 'net.java.dev.jna:jna:4.2.0'
    compile urlFile('https://github.com/java-native-access/jna/blob/4.2.2/lib/native/android-arm.jar?raw=true', 'jna-android-arm')
    compile urlFile('https://github.com/java-native-access/jna/blob/4.2.2/lib/native/android-armv7.jar?raw=true', 'jna-android-armv7')
    compile urlFile('https://github.com/java-native-access/jna/blob/4.2.2/lib/native/android-aarch64.jar?raw=true', 'jna-android-aarch64')
    compile urlFile('https://github.com/java-native-access/jna/blob/4.2.2/lib/native/android-x86.jar?raw=true', 'jna-android-x86')
    compile urlFile('https://github.com/java-native-access/jna/blob/4.2.2/lib/native/android-x86-64.jar?raw=true', 'jna-android-x86_64')
    compile urlFile('https://github.com/java-native-access/jna/blob/4.2.2/lib/native/android-mips.jar?raw=true', 'jna-android-mips')
    compile urlFile('https://github.com/java-native-access/jna/blob/4.2.2/lib/native/android-mips64.jar?raw=true', 'jna-android-mips64')
}
def safeCopy = { src, dst ->
    File fdst = new File(dst)
    fdst.parentFile.mkdirs()
    fdst.bytes = new File(src).bytes

}

def archFromName = { name ->
    switch (name) {
        case ~/.*android-(x86-64|x86_64|amd64).*/:
            return "x86_64"
        case ~/.*android-(i386|i686|x86).*/:
            return "x86"
        case ~/.*android-(arm64|aarch64).*/:
            return "arm64-v8a"
        case ~/.*android-(armhf|armv7|arm-v7|armeabi-v7).*/:
            return "armeabi-v7a"
        case ~/.*android-(arm).*/:
            return "armeabi"
        case ~/.*android-(mips).*/:
            return "mips"
        case ~/.*android-(mips64).*/:
            return "mips64"
        default:
            return null
    }
}

task extractNatives << {
    project.configurations.compile.each { dep ->
        println "Scanning ${dep.name} for native libs"
        if (!dep.name.endsWith(".jar"))
            return
        zipTree(dep).visit { zDetail ->
            if (!zDetail.name.endsWith(".so"))
                return
            print "\tFound ${zDetail.name}"
            String arch = archFromName(zDetail.toString())
            if(arch != null){
                println " -> $arch"
                safeCopy(zDetail.file.absolutePath,
                        "$buildDir/native-libs/$arch/${zDetail.file.name}")
            } else {
                println " -> No valid arch"
            }
        }
    }
}

preBuild.dependsOn(['extractNatives'])

Leí muchos hilos de cómo agregar una biblioteca * .so a Android Studio, pero ninguno de ellos funciona, especialmente cuando se trata del punto de texto: Esto no funciona con el xxx más nuevo (Android Studio, gradle, ...)

¿Podemos hacer un nuevo comienzo por favor? Tengo:

Android Studio 0.6.0

Desde la estructura del proyecto veo:

Ubicación del SDK:

/usr/share/android-studio/data/sdk
/usr/lib/jvm/default-java

Proyecto:

Gradle version 1.10
Android Plugin Version 0.11.+

Módulos / aplicación: Propiedades:

Compile Sdk Versión 19 Build Tools Versión 19.1.0

Dependencias:

{dir=libs, include=[*.jar]} Compile

{dir=libs, include=[*.so]}  Provided

m com.android.support: appcompat -v7:19.+   Compile

Obtuve los archivos * .so precompilados y en la aplicación de demostración que están trabajando. Tengo que cambiar el código fuente de la aplicación, así que necesito reconstruir con los mismos archivos * .so.




Este es mi archivo build.gradle, tenga en cuenta la línea

jniLibs.srcDirs = ['libs']

Esto incluirá el archivo * .so de libs para apk.

sourceSets {
    main {
        manifest.srcFile 'AndroidManifest.xml'
        java.srcDirs = ['src']
        resources.srcDirs = ['src']
        aidl.srcDirs = ['src']
        renderscript.srcDirs = ['src']
        res.srcDirs = ['res']
        assets.srcDirs = ['assets']
        jniLibs.srcDirs = ['libs']
    }

    // Move the tests to tests/java, tests/res, etc...
    instrumentTest.setRoot('tests')

    // Move the build types to build-types/<type>
    // For instance, build-types/debug/java, build-types/debug/AndroidManifest.xml, ...
    // This moves them out of them default location under src/<type>/... which would
    // conflict with src/ being used by the main source set.
    // Adding new build types or product flavors should be accompanied
    // by a similar customization.
    debug.setRoot('build-types/debug')
    release.setRoot('build-types/release')
}



Para usar la biblioteca nativa (archivos so) Necesita agregar algunos códigos en el archivo "build.gradle".

Este código es para limpiar el directorio "armeabi" y copiar archivos 'so' en "armeabi" mientras que 'limpiar proyecto'.

task copyJniLibs(type: Copy) {
    from 'libs/armeabi'
    into 'src/main/jniLibs/armeabi'
}
tasks.withType(JavaCompile) {
    compileTask -> compileTask.dependsOn(copyJniLibs)
}
clean.dependsOn 'cleanCopyJniLibs'

Me han recomendado desde abajo. https://gist.github.com/pocmo/6461138




Android NDK oficial hello-libs CMake ejemplo

https://github.com/googlesamples/android-ndk/tree/840858984e1bb8a7fab37c1b7c571efbe7d6eb75/hello-libs

Acabo de trabajar para mí en el host Ubuntu 17.10, Android Studio 3, SDK 26 de Android, por lo que le recomiendo que base su proyecto en él.

La biblioteca compartida se llama libgperf , las partes del código clave son:

  • hello-libs/app/src/main/cpp/CMakeLists.txt :

    // -L
    add_library(lib_gperf SHARED IMPORTED)
    set_target_properties(lib_gperf PROPERTIES IMPORTED_LOCATION
              ${distribution_DIR}/gperf/lib/${ANDROID_ABI}/libgperf.so)
    
    // -I
    target_include_directories(hello-libs PRIVATE
                               ${distribution_DIR}/gperf/include)
    // -lgperf
    target_link_libraries(hello-libs
                          lib_gperf)
    
  • app/build.gradle :

    android {
        sourceSets {
            main {
                // let gradle pack the shared library into apk
                jniLibs.srcDirs = ['../distribution/gperf/lib']
    

    Luego, si miras en /data/app en el dispositivo, libgperf.so estará allí también.

  • en código C ++, use: #include <gperf.h>

  • Ubicación del encabezado: hello-libs/distribution/gperf/include/gperf.h

  • ubicación lib: distribution/gperf/lib/arm64-v8a/libgperf.so

  • Si solo admite algunas arquitecturas, consulte: Gradle Build NDK target only ARM

El git de ejemplo rastrea las bibliotecas compartidas previamente compiladas, pero también contiene el sistema de compilación para construirlas también: https://github.com/googlesamples/android-ndk/tree/840858984e1bb8a7fab37c1b7c571efbe7d6eb75/hello-libs/gen-libs




* .so biblioteca en Android Studio

Tienes que generar la carpeta jniLibs dentro de main en los proyectos de Android Studio y poner todos tus archivos .so dentro. También puede integrar esta línea en build.gradle

compilar fileTree (dir: 'libs', include: [' .jar', ' .so'])

Funciona perfectamente

| --app:

| - | --src:

| - | - | --main

| - | - | - | --jniLibs

| - | - | - | - | --armeabi

| - | - | - | - | - | -. so archivos

Esta es la estructura del proyecto.




Solución 1: creación de una carpeta JniLibs

Crea una carpeta llamada "jniLibs" en tu aplicación y las carpetas que contienen tu * .so adentro. La carpeta "jniLibs" debe crearse en la misma carpeta que las carpetas "Java" o "Assets".

Solución 2: modificación del archivo build.gradle

Si no desea crear una nueva carpeta y mantener sus archivos * .so en la carpeta libs, ¡es posible!

En ese caso, solo agregue sus archivos * .so en la carpeta libs (respete la misma arquitectura que la solución 1: libs / armeabi / .so por ejemplo) y modifique el archivo build.gradle de su aplicación para agregar el directorio fuente de los jniLibs.

sourceSets {
    main {
        jniLibs.srcDirs = ["libs"]
    }
}

Tendrás más explicaciones, con capturas de pantalla para ayudarte aquí (Paso 6):

http://blog.guillaumeagis.eu/setup-andengine-with-android-studio/

EDITAR Tenía que ser jniLibs.srcDirs, no jni.srcDirs - editado el código. El directorio puede ser una ruta [relativa] que señala fuera del directorio del proyecto.




Solución actual

Cree la carpeta project/app/src/main/jniLibs , y luego ponga sus archivos *.so dentro de sus carpetas abi en esa ubicación. P.ej,

project/
├──libs/
|  └── *.jar       <-- if your library has jar files, they go here
├──src/
   └── main/
       ├── AndroidManifest.xml
       ├── java/
       └── jniLibs/ 
           ├── arm64-v8a/                       <-- ARM 64bit
           │   └── yourlib.so
           ├── armeabi-v7a/                     <-- ARM 32bit
           │   └── yourlib.so
           └── x86/                             <-- Intel 32bit
               └── yourlib.so

Solución obsoleta

Agregue ambos fragmentos de código en su archivo gradle.build de módulo como una dependencia:

compile fileTree(dir: "$buildDir/native-libs", include: 'native-libs.jar')

Cómo crear este jar personalizado

task nativeLibsToJar(type: Jar, description: 'create a jar archive of the native libs') {
    destinationDir file("$buildDir/native-libs")
    baseName 'native-libs'
    from fileTree(dir: 'libs', include: '**/*.so')
    into 'lib/'
}

tasks.withType(JavaCompile) {
    compileTask -> compileTask.dependsOn(nativeLibsToJar)
}

La misma respuesta también se puede encontrar en una pregunta relacionada: Incluir la biblioteca .so en apk en android studio




Como ya ha visto todas las respuestas y comentarios anteriores, pero esta respuesta es para aclarar algo que un nuevo desarrollador podría no obtener fácilmente.

./gradlew -q dependencias app: dependencias --configuración compilar

La línea anterior salvará su vida sin duda, pero cómo obtener el punto exacto del resultado de la línea anterior.

Cuando obtiene la lista o el gráfico de todas las dependencias con el comando anterior, debe buscar el número de versión en conflicto que está ingresando en su código. Por favor vea la imagen de abajo.

En la imagen de arriba puede ver que 23.4.0 está creando el problema, pero no lo encontramos en nuestro archivo de gradle. Así que ahora este número de versión (23.4.0) nos salvará. Cuando tengamos este número, encontraremos este número en el resultado del resultado del comando anterior e importaremos directamente esa dependencia directamente en nuestro archivo de gradle. Por favor, vea la imagen de abajo para obtener una vista clara.

puede ver claramente que com.android.support:cardview-v7:23.4.0 y com.android.support:customtabs:23.4.0 están usando la versión que está creando el problema. Ahora simplemente copie esa línea de la lista de dependencias y úsela explícitamente en nuestro archivo de gradle pero con el enlace de la versión actualizada

implementación "com.android.support:cardview-v7:26.1.0" implementación "com.android.support:customtabs:26.1.0"







android android-studio