Come includere la libreria * .so in Android Studio?


123

Ho letto molti thread su come aggiungere una libreria * .so ad Android Studio, ma nessuno di loro funziona, soprattutto quando si tratta di testo: questo non funziona con il nuovo xxx (Android Studio, gradle, ...)

Possiamo ricominciare da capo, per favore. Ho ottenuto:

Android Studio 0.6.0

Dalla struttura del progetto vedo:

Posizione SDK:

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

Progetto:

Gradle version 1.10
Android Plugin Version 0.11.+

Moduli / app: Proprietà:

Compilare Sdk versione 19 Build Tools versione 19.1.0

dipendenze:

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

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

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

Ho i file * .so precompilati e nell'app demo funzionano. Devo cambiare il codice sorgente dell'app, quindi devo ricostruire con gli stessi file * .so.


aggiungere un file .so dalla directory al di fuori del progetto Android: stackoverflow.com/questions/50713933/...
user1506104

Controllare risposta qui: stackoverflow.com/a/54977264/8034839
Shizhen

Risposte:


108

Soluzione attuale

Crea la cartella project/app/src/main/jniLibse poi metti i tuoi *.sofile nelle loro cartelle abi in quella posizione. Per esempio,

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

Soluzione obsoleta

Aggiungi entrambi i frammenti di codice nel file gradle.build del modulo come dipendenza:

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

Come creare questo vaso personalizzato:

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 stessa risposta può essere trovata anche nella domanda correlata: Includi la libreria .so in apk in Android Studio


6
Compilel'attività è stata deprecata. Usa JavaCompileinvece (da risposte correlate)
Sergii

dove devo mettere i compiti?
masoud vali

2
Per favore prova prima la soluzione della cartella jniLibs. Queste attività dovrebbero essere inserite nel file gradle.build della tua app / libreria.
nenick

Riferimento per il jniLibspercorso della directory in Gradle Plugin User Guide - Project Structure
Eido95

vedi anche qui (elenca le diverse sottocartelle dell'architettura): cumulations.com/blogs/9/…
NorbertM

222

Aggiunta della libreria .so in Android Studio 1.0.2

  1. Crea cartella "jniLibs" all'interno di "src / main /"
  2. Metti tutte le tue librerie .so nella cartella "src / main / jniLibs"
  3. La struttura della cartella è simile a,
    | --app:
    | - | --src:
    | - | - | --main
    | - | - | - | --jniLibs
    | - | - | - | - | --armeabi
    | - | - | - | - | - | -. so File
    | - | - | - | - | --x86
    | - | - | - | - | - | -. so Files
  4. Nessun codice aggiuntivo richiede solo la sincronizzazione del progetto e l'esecuzione dell'applicazione.

    Riferimento
    https://github.com/commonsguy/sqlcipher-gradle/tree/master/src/main

6
Questo non funziona con la versione beta del 16 giugno 2015 di Studio
bugfixr

6
questa è la risposta corretta, lavorando in Android Studio 1.2.2. controllato e verificato.
Akhil Jain,

3
Lavorare con Android Studio 1.3.1.
Jaime Hablutzel

3
Ha funzionato per me grazie. su Android Studio 2.1.2 :)
ShujatAli

3
funziona con Android Studio 3.2.1, fantastico! Ancora non documentato da nessuna parte! ???
NorbertM

29

Soluzione 1: creazione di una cartella JniLibs

Crea una cartella chiamata "jniLibs" nella tua app e le cartelle che contengono il tuo * .so all'interno. La cartella "jniLibs" deve essere creata nella stessa cartella delle cartelle "Java" o "Assets".

Soluzione 2: modifica del file build.gradle

Se non vuoi creare una nuova cartella e mantenere i tuoi file * .so nella cartella libs, è possibile!

In tal caso, aggiungi semplicemente i tuoi file * .so nella cartella libs (rispetta la stessa architettura della soluzione 1: libs / armeabi / .so per esempio) e modifica il file build.gradle della tua app per aggiungere la directory di origine delle jniLibs.

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

Avrai più spiegazioni, con screenshot per aiutarti qui (Passaggio 6):

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

EDIT Doveva essere jniLibs.srcDirs, non jni.srcDirs - ha modificato il codice. La directory può essere un percorso [relativo] che punta all'esterno della directory del progetto.


1
La soluzione 2 non funziona per me. Ricevo un errore di compilazione: "Impossibile trovare la proprietà 'jni' sul set di sorgenti 'main'."
Greg Brown

Il segreto era "La cartella" jniLibs "deve essere creata nella stessa cartella delle cartelle" Java "o" Assets ".". Grazie!
Seraphim's

Il metodo 1 mi ha permesso di compilare correttamente, il secondo ha creato una cartella "cpp" in AS e mi ha dato un errore sul compilatore C ++ mancante
fillobotto

La soluzione 2 doveva utilizzare jniLibs.srcDirs, non jni.srcDirs per consentire di specificare la posizione delle librerie native (il percorso può essere relativo o assoluto e può puntare anche all'esterno della directory del progetto).
astraujums

Per la soluzione 2 è necessario inserire il source Sets {codice nella android {sezione
yennster

26

* .so libreria in Android Studio

Devi generare la cartella jniLibs all'interno di main nei progetti di Android Studio e inserire tutti i tuoi file .so all'interno. Puoi anche integrare questa riga in build.gradle

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

Funziona perfettamente

| --App:

| - | --src:

| - | - | --main

| - | - | - | --jniLibs

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

| - | - | - | - | - | -. so Files

Questa è la struttura del progetto.


4
L'aggiunta di .so in compile fileTree (dir: 'libs', include: ['.jar', '. So ']) ha risolto il mio prb. grazie
BST Kaal

Se è ancora dopo la soluzione sotto, prova Android ndk r10e
Vineet Setia

12

Questo è il mio file build.gradle, si prega di notare la riga

jniLibs.srcDirs = ['libs']

Questo includerà il file * .so di libs in 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')
}

5

hello-libsEsempio di CMake ufficiale di Android NDK

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

Ha funzionato per me su host Ubuntu 17.10, Android Studio 3, Android SDK 26, quindi consiglio vivamente di basare il tuo progetto su di esso.

Viene chiamata la libreria condivisa libgperf, le parti del codice chiave sono:

  • ciao-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']

    Quindi, se guardi sotto /data/appsul dispositivo, libgperf.soci sarà anche lui.

  • su codice C ++, usa: #include <gperf.h>

  • posizione dell'intestazione: hello-libs/distribution/gperf/include/gperf.h

  • posizione lib: distribution/gperf/lib/arm64-v8a/libgperf.so

  • Se si supportano solo alcune architetture, vedere: Gradle Build NDK target only ARM

L'esempio git tiene traccia delle librerie condivise predefinite, ma contiene anche il sistema di compilazione per crearle effettivamente: https://github.com/googlesamples/android-ndk/tree/840858984e1bb8a7fab37c1b7c571efbe7d6eb75/hello-libs/gen-libs


2

Per utilizzare la libreria nativa (file so) È necessario aggiungere alcuni codici nel file "build.gradle".

Questo codice serve per pulire la directory "armeabi" e copiare i file 'so' in "armeabi" mentre 'clean project'.

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

Sono stato segnalato dal basso. https://gist.github.com/pocmo/6461138


2

Ho risolto un problema simile utilizzando dipendenze lib native esterne che sono impacchettate all'interno di file jar. A volte queste librerie dipendenti dall'architettura sono impacchettate tutte insieme all'interno di un jar, a volte sono suddivise in diversi file jar. quindi ho scritto un buildscript per scansionare le dipendenze jar per le librerie native e ordinarle nelle cartelle lib di Android corrette. Inoltre, questo fornisce anche un modo per scaricare le dipendenze che non si trovano nei repository Maven, che è attualmente utile per far funzionare JNA su Android perché non tutti i jar nativi sono pubblicati in repository Maven pubblici.

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'])

0

Ho provato le soluzioni nelle risposte precedenti ma nessuna ha funzionato per me. Avevo una libreria con file .so, .dll e .jar. Alla fine l'ho fatto, puoi vedere i dettagli qui: https://stackoverflow.com/a/54976458/7392868

Ho copiato incollato i file .so in una cartella denominata jniLibs e incollato all'interno della cartella app / src / main /. Per altre dipendenze ho usato le dipendenze di grado.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.