Bagaimana cara memasukkan pustaka * .so di Android Studio?

123

Saya membaca banyak utas cara menambahkan pustaka * .so ke Android Studio, tetapi tidak ada yang berfungsi, terutama jika menyangkut poin teks: Ini tidak berfungsi dengan xxx yang lebih baru (Android Studio, gradle, ...)

Bisakah kita membuat awal yang baru. Saya mendapatkan:

Android Studio 0.6.0

Dari Struktur Proyek saya melihat:

Lokasi SDK:

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

Proyek:

Gradle version 1.10
Android Plugin Version 0.11.+

Modul / aplikasi: Properti:

Kompilasi Sdk Versi 19 Build Tools Versi 19.1.0

Dependensi:

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

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

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

Saya mendapatkan file * .so yang telah dikompilasi sebelumnya dan di aplikasi demo mereka berfungsi. Saya harus mengubah kode sumber aplikasi, jadi saya perlu membangun kembali dengan file * .so yang sama.

Ronald Wiplinger
sumber
menambahkan file .so dari direktori di luar proyek android: stackoverflow.com/questions/50713933/…
user1506104
Periksa jawabannya di sini: stackoverflow.com/a/54977264/8034839
shizhen

Jawaban:

108

Solusi Saat Ini

Buat folder project/app/src/main/jniLibs, lalu letakkan *.sofile Anda di dalam folder abi mereka di lokasi itu. Misalnya,

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

Solusi yang tidak berlaku lagi

Tambahkan kedua cuplikan kode dalam file gradle.build modul Anda sebagai dependensi:

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

Cara membuat toples khusus ini:

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

Jawaban yang sama juga dapat ditemukan pada pertanyaan terkait: Include .so library in apk in android studio

nenick
sumber
6
Compiletugas sudah tidak digunakan lagi. Gunakan JavaCompilesebagai gantinya (dari jawaban terkait)
Sergii
di mana saya harus meletakkan tugas?
masoud vali
2
Silakan coba dulu solusi folder jniLibs. Tugas ini harus dimasukkan ke dalam file gradle.build app / library Anda.
nenick
Referensi untuk jniLibsjalur direktori di Panduan Pengguna Plugin Gradle - Struktur Proyek
Eido95
lihat juga di sini (daftar sub-folder arsitektur yang berbeda): cumulations.com/blogs/9/…
NorbertM
222

Menambahkan Library .so di Android Studio 1.0.2

  1. Buat Folder "jniLibs" di dalam "src / main /"
  2. Letakkan semua pustaka .so Anda di dalam folder "src / main / jniLibs"
  3. Struktur folder terlihat seperti,
    | --app:
    | - | --src:
    | - | - | --main
    | - | - | - | --jniLibs
    | - | - | - | - | --armeabi
    | - | - | - | - | - | -. jadi Berkas
    | - | - | - | - | --x86
    | - | - | - | - | - | -. Jadi File
  4. Tidak ada kode tambahan yang hanya membutuhkan sinkronisasi proyek Anda dan menjalankan aplikasi Anda.

    Referensi
    https://github.com/commonsguy/sqlcipher-gradle/tree/master/src/main
Vasanth
sumber
6
Ini tidak berfungsi dengan Studio versi beta 16 Juni 2015
perbaikan bug
6
ini adalah jawaban yang benar, bekerja di Android Studio 1.2.2. diperiksa dan diverifikasi.
Akhil Jain
3
Bekerja dengan Android Studio 1.3.1.
Jaime Hablutzel
3
Bekerja untuk saya thnx. di studio android 2.1.2 :)
ShujatAli
3
berfungsi dengan Android Studio 3.2.1, hebat! Masih belum terdokumentasi dimanapun! ???
NorbertM
29

Solusi 1: Pembuatan folder JniLibs

Buat folder bernama "jniLibs" ke dalam aplikasi Anda dan folder yang berisi * .so Anda di dalamnya. Folder "jniLibs" harus dibuat di folder yang sama dengan folder "Java" atau "Assets".

Solusi 2: Modifikasi file build.gradle

Jika Anda tidak ingin membuat folder baru dan menyimpan file * .so Anda ke dalam folder libs, itu mungkin!

Jika demikian, cukup tambahkan file * .so Anda ke dalam folder libs (harap hormati arsitektur yang sama dengan solusi 1: libs / armeabi / .so misalnya) dan ubah file build.gradle aplikasi Anda untuk menambahkan direktori sumber dari jniLibs.

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

Anda akan memiliki lebih banyak penjelasan, dengan tangkapan layar untuk membantu Anda di sini (Langkah 6):

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

EDIT Itu harus jniLibs.srcDirs, bukan jni.srcDirs - yang mengedit kodenya. Direktori dapat berupa jalur [relatif] yang mengarah ke luar direktori proyek.

GuillaumeAgis
sumber
1
Solusi 2 tidak berhasil untuk saya. Saya mendapatkan kesalahan versi: "Tidak dapat menemukan properti 'jni' di kumpulan sumber 'utama'."
Greg Brown
Rahasianya adalah 'Folder "jniLibs" harus dibuat dalam folder yang sama dengan folder "Java" atau "Assets".'. Terima kasih!
Seraphim's
Metode 1 memungkinkan saya untuk mengkompilasi dengan benar, yang kedua membuat folder "cpp" di AS dan memberi saya kesalahan tentang compiler C ++ yang hilang
fillobotto
Solusi 2 harus menggunakan jniLibs.srcDirs, bukan jni.srcDirs untuk memungkinkan penentuan lokasi pustaka asli (jalur dapat bersifat relatif atau absolut dan dapat menunjuk bahkan di luar direktori proyek).
astraujums
Untuk Solusi 2, Anda perlu menempatkan source Sets {kode di bawah android {bagian
yennster
26

* .so library di Android Studio

Anda harus membuat folder jniLibs di dalam main di proyek Android Studio dan meletakkan semua file .so Anda di dalamnya. Anda juga dapat mengintegrasikan baris ini di build.gradle

kompilasi fileTree (dir: 'libs', sertakan: [' .jar', ' .so'])

Ini bekerja dengan sempurna

| --app:

| - | --src:

| - | - | --main

| - | - | - | --jniLibs

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

| - | - | - | - | - | -. Jadi File

Ini adalah struktur proyek.

Ramkailash
sumber
4
Menambahkan .so di fileTree kompilasi (dir: 'libs', include: ['.jar', '. So']) menyelesaikan prb saya. thnx
BST Kaal
Jika masih setelah solusi di bawah ini, coba android ndk r10e
Vineet Setia
12

Ini adalah file build.gradle saya, Harap perhatikan barisnya

jniLibs.srcDirs = ['libs']

Ini akan menyertakan file * .so libs ke 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')
}
Sebelas November
sumber
5

hello-libsContoh CMake resmi Android NDK

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

Baru saja bekerja untuk saya di host Ubuntu 17.10, Android Studio 3, Android SDK 26, jadi saya sangat menyarankan agar Anda mendasarkan proyek Anda padanya.

Perpustakaan bersama disebut libgperf, bagian kode kuncinya adalah:

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

    Kemudian, jika Anda melihat /data/appperangkat di bawah , libgperf.soakan ada juga.

  • pada kode C ++, gunakan: #include <gperf.h>

  • lokasi tajuk: hello-libs/distribution/gperf/include/gperf.h

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

  • Jika Anda hanya mendukung beberapa arsitektur, lihat: Gradle Build NDK hanya menargetkan ARM

Contoh git melacak pustaka bersama prebuilt, tetapi juga berisi sistem build untuk benar-benar membangunnya juga: https://github.com/googlesamples/android-ndk/tree/840858984e1bb8a7fab37c1b7c571efbe7d6eb75/hello-libs/gen-libs

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

Untuk menggunakan native-library (file jadi) Anda perlu menambahkan beberapa kode di file "build.gradle".

Kode ini untuk membersihkan direktori "armeabi" dan menyalin file 'so' ke dalam "armeabi" saat 'membersihkan proyek'.

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

Saya telah dirujuk dari bawah. https://gist.github.com/pocmo/6461138

angela cantik
sumber
2

Saya telah memecahkan masalah serupa menggunakan dependensi lib asli eksternal yang dikemas di dalam file jar. Terkadang pustaka dependend arsitektur ini dikemas semuanya di dalam satu jar, terkadang mereka dipecah menjadi beberapa file jar. jadi saya menulis beberapa buildscript untuk memindai dependensi jar untuk lib asli dan mengurutkannya ke dalam folder lib android yang benar. Selain itu, ini juga menyediakan cara untuk mendownload dependensi yang tidak ditemukan di repo maven yang saat ini berguna untuk membuat JNA berfungsi di android karena tidak semua native jar dipublikasikan di repo maven publik.

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
sumber
0

Saya mencoba solusi dalam jawaban di atas tetapi tidak ada yang berhasil untuk saya. Saya memiliki perpustakaan dengan file .so, .dll, dan .jar. Pada akhirnya saya melakukan ini, Anda dapat melihat detailnya di sini: https://stackoverflow.com/a/54976458/7392868

Saya menyalin menempelkan file .so di folder bernama jniLibs dan menempelkannya di dalam folder app / src / main /. Untuk dependensi lain saya menggunakan dependensi kelas.

Muhammad Ali
sumber