Wie kann ich die * .so-Bibliothek in Android Studio aufnehmen?

123

Ich habe viele Threads gelesen, wie man eine * .so-Bibliothek zu Android Studio hinzufügt, aber keine davon funktioniert, besonders wenn es um Text geht: Dies funktioniert nicht mit dem neueren xxx (Android Studio, gradle, ...)

Können wir bitte einen Neuanfang machen? Ich habe:

Android Studio 0.6.0

Aus der Projektstruktur sehe ich:

SDK-Speicherort:

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

Projekt:

Gradle version 1.10
Android Plugin Version 0.11.+

Module / App: Eigenschaften:

Kompilieren Sie Sdk Version 19 Build Tools Version 19.1.0

Abhängigkeiten:

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

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

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

Ich habe die * .so-Dateien vorkompiliert und in der Demo-App funktionieren sie. Ich muss den Quellcode der App ändern, daher muss ich mit denselben * .so-Dateien neu erstellen.

Ronald Wiplinger
quelle
Fügen Sie eine .so-Datei aus dem Verzeichnis außerhalb des Android-Projekts hinzu: stackoverflow.com/questions/50713933/…
user1506104
Überprüfen Sie die Antwort hier: stackoverflow.com/a/54977264/8034839
shizhen

Antworten:

108

Aktuelle Lösung

Erstellen Sie den Ordner project/app/src/main/jniLibsund legen Sie Ihre *.soDateien in den abi-Ordnern an diesem Speicherort ab. Z.B,

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

Veraltete Lösung

Fügen Sie beide Codeausschnitte als Abhängigkeit in Ihre Modulklasse gradle.build ein:

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

So erstellen Sie dieses benutzerdefinierte Glas:

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)
}

Die gleiche Antwort finden Sie auch in verwandten Fragen: Fügen Sie .so Bibliothek in apk in Android Studio

Nenick
quelle
6
CompileAufgabe wurde abgelehnt. Verwenden Sie JavaCompilestattdessen (aus verwandten Antworten)
Sergii
Wo soll ich die Aufgaben platzieren?
Masoud Vali
2
Bitte versuchen Sie zuerst die jniLibs-Ordnerlösung. Diese Aufgaben sollten in Ihre app / library gradle.build-Datei eingefügt werden.
Nenick
Referenz für den jniLibsVerzeichnispfad im Gradle Plugin Benutzerhandbuch - Projektstruktur
Eido95
Siehe auch hier (listet die verschiedenen Architektur-Unterordner auf): cumulations.com/blogs/9/…
NorbertM
221

Hinzufügen einer .so-Bibliothek in Android Studio 1.0.2

  1. Erstellen Sie den Ordner "jniLibs" in "src / main /"
  2. Legen Sie alle Ihre .so-Bibliotheken im Ordner "src / main / jniLibs" ab
  3. Die
    Ordnerstruktur sieht wie folgt aus: | --app:
    | - | --src:
    | - | - | --main
    | - | - | - | --jniLibs
    | - | - | - | - | --armeabi
    | - | - | - | - | - | -. also Dateien
    | - | - | - | - | --x86
    | - | - | - | - | - | -. also Dateien
  4. Kein zusätzlicher Code erfordert nur die Synchronisierung Ihres Projekts und die Ausführung Ihrer Anwendung.

    Referenz
    https://github.com/commonsguy/sqlcipher-gradle/tree/master/src/main
Vasanth
quelle
6
Dies funktioniert nicht mit der Beta-Version von Studio vom 16. Juni 2015
Bugfixr
6
Dies ist die richtige Antwort, die in Android Studio 1.2.2 funktioniert. geprüft und verifiziert.
Akhil Jain
3
Arbeiten mit Android Studio 1.3.1.
Jaime Hablutzel
3
Arbeitete für mich danke. auf Android Studio 2.1.2 :)
ShujatAli
3
funktioniert mit Android Studio 3.2.1, großartig! Immer noch nirgendwo dokumentiert! ???
NorbertM
29

Lösung 1: Erstellen eines JniLibs-Ordners

Erstellen Sie einen Ordner mit dem Namen "jniLibs" in Ihrer App und den Ordnern, in denen sich Ihre * .so befindet. Der Ordner "jniLibs" muss im selben Ordner wie Ihre Ordner "Java" oder "Assets" erstellt werden.

Lösung 2: Änderung der Datei build.gradle

Wenn Sie keinen neuen Ordner erstellen und Ihre * .so-Dateien im libs-Ordner behalten möchten, ist dies möglich!

In diesem Fall fügen Sie einfach Ihre * .so-Dateien in den Ordner libs ein (beachten Sie beispielsweise die gleiche Architektur wie in Lösung 1: libs / armeabi / .so) und ändern Sie die Datei build.gradle Ihrer App, um das Quellverzeichnis hinzuzufügen der jniLibs.

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

Sie erhalten weitere Erklärungen mit Screenshots, die Ihnen hier helfen (Schritt 6):

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

BEARBEITEN Es musste jniLibs.srcDirs sein, nicht jni.srcDirs - den Code bearbeitet. Das Verzeichnis kann ein [relativer] Pfad sein, der außerhalb des Projektverzeichnisses verweist.

GuillaumeAgis
quelle
1
Lösung 2 funktioniert bei mir nicht. Ich erhalte einen Build-Fehler: "Die Eigenschaft 'jni' im Quellensatz 'main' konnte nicht gefunden werden."
Greg Brown
Das Geheimnis war 'Der Ordner "jniLibs" muss im selben Ordner wie Ihre Ordner "Java" oder "Assets" erstellt werden.' Vielen Dank!
Seraphim
Methode 1 erlaubte mir, korrekt zu kompilieren, zweite erstellte einen "cpp" -Ordner in AS und gab mir Fehler über fehlenden C ++
fillobotto
Lösung 2 musste jniLibs.srcDirs verwenden, nicht jni.srcDirs, um den Speicherort der nativen Bibliotheken angeben zu können (der Pfad kann relativ oder absolut sein und sogar außerhalb des Projektverzeichnisses zeigen).
Astrajums
Für Lösung 2 müssen Sie den source Sets {Code unter dem android {Abschnitt
yennster
26

* .so Bibliothek in Android Studio

Sie müssen den Ordner jniLibs in main in Android Studio-Projekten generieren und alle .so-Dateien darin ablegen. Sie können diese Zeile auch in build.gradle integrieren

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

Es funktioniert perfekt

| --app:

| - | --src:

| - | - | --main

| - | - | - | --jniLibs

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

| - | - | - | - | - | -. also Dateien

Dies ist die Projektstruktur.

Ramkailash
quelle
4
Das Hinzufügen von .so in compile fileTree (dir: 'libs', include: ['.jar', '. So']) hat mein Problem gelöst. Danke
BST Kaal
Wenn es immer noch nach unter Lösung ist, versuchen Sie Android ndk r10e
Vineet Setia
12

Dies ist meine build.gradle-Datei. Bitte beachten Sie die Zeile

jniLibs.srcDirs = ['libs']

Dies schließt die * .so-Datei von libs an apk ein.

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')
}
NovemberEleven
quelle
5

Offizielles hello-libsCMake-Beispiel für Android NDK

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

Ich habe gerade für Ubuntu 17.10 Host, Android Studio 3, Android SDK 26 gearbeitet. Ich empfehle daher dringend, dass Sie Ihr Projekt darauf aufbauen.

Die gemeinsam genutzte Bibliothek wird aufgerufen libgperf. Die wichtigsten Codeteile sind:

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

    Wenn Sie dann unter /data/appauf das Gerät schauen , libgperf.sowird auch dort sein.

  • Verwenden Sie in C ++ - Code: #include <gperf.h>

  • Header-Position: hello-libs/distribution/gperf/include/gperf.h

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

  • Wenn Sie nur einige Architekturen unterstützen, lesen Sie: Gradle Build NDK-Ziel nur für ARM

Das Beispiel-Git verfolgt die vorgefertigten gemeinsam genutzten Bibliotheken, enthält jedoch auch das Build-System, um sie tatsächlich zu erstellen: https://github.com/googlesamples/android-ndk/tree/840858984e1bb8a7fab37c1b7c571efbe7d6eb75/hello-libs/gen-libs

Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
quelle
2

So verwenden Sie die native Bibliothek (also Dateien) Sie müssen der Datei "build.gradle" einige Codes hinzufügen.

Dieser Code dient zum Löschen des Verzeichnisses "armeabi" und zum Kopieren von "so" -Dateien in "armeabi", während "Projekt bereinigen".

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

Ich wurde von unten verwiesen. https://gist.github.com/pocmo/6461138

hübsche angela
quelle
2

Ich habe ein ähnliches Problem mit externen nativen lib-Abhängigkeiten gelöst, die in JAR-Dateien gepackt sind. Manchmal sind diese architekturabhängigen Bibliotheken zusammen in einem JAR gepackt, manchmal sind sie in mehrere JAR-Dateien aufgeteilt. Also habe ich ein Buildscript geschrieben, um die JAR-Abhängigkeiten nach nativen Bibliotheken zu durchsuchen und sie in die richtigen Android-Lib-Ordner zu sortieren. Darüber hinaus bietet dies auch eine Möglichkeit zum Herunterladen von Abhängigkeiten, die nicht in Maven-Repos gefunden wurden. Dies ist derzeit nützlich, um JNA auf Android zum Laufen zu bringen, da nicht alle nativen Jars in öffentlichen Maven-Repos veröffentlicht werden.

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'])
Jan.
quelle
0

Ich habe die Lösungen in den obigen Antworten ausprobiert, aber keine hat für mich funktioniert. Ich hatte eine Bibliothek mit .so-, .dll- und .jar-Dateien. Am Ende habe ich dies getan, Sie können die Details hier sehen: https://stackoverflow.com/a/54976458/7392868

Ich habe die .so-Dateien in einen Ordner namens jniLibs kopiert und in den Ordner app / src / main / eingefügt. Für andere Abhängigkeiten habe ich die Notenabhängigkeiten verwendet.

Muhammad Ali
quelle