* .So kitaplığını Android Studio'ya nasıl dahil edebilirim?


123

Android Studio'ya * .so kitaplığını nasıl ekleyeceğimi pek çok iş parçacığı okudum, ancak hiçbiri çalışmıyor, özellikle metin açısından: Bu, daha yeni xxx ile çalışmıyor (Android Studio, gradle, ...)

Yeni bir başlangıç ​​yapabilir miyiz lütfen? Bende var:

Android Studio 0.6.0

Proje Yapısından şunu görüyorum:

SDK Konumu:

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

Proje:

Gradle version 1.10
Android Plugin Version 0.11.+

Modüller / uygulama: Özellikler:

Sdk Sürüm 19 Derleme Araçları Sürüm 19.1.0

Bağımlılıklar:

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

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

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

* .So dosyalarını önceden derledim ve demo uygulamasında çalışıyorlar. Uygulamanın kaynak kodunu değiştirmem gerekiyor, bu yüzden aynı * .so dosyalarıyla yeniden oluşturmam gerekiyor.


android projesi dışındaki
dizinden

Yanıtı burada kontrol edin: stackoverflow.com/a/54977264/8034839
shizhen

Yanıtlar:


108

Mevcut Çözüm

Klasörü oluşturun project/app/src/main/jniLibsve ardından *.sodosyalarınızı bu konumdaki abi klasörlerine koyun . Örneğin,

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

Kullanımdan kaldırılan çözüm

Bağımlılık olarak modül gradle.build dosyanıza her iki kod parçacığını da ekleyin:

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

Bu özel kavanoz nasıl oluşturulur:

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

Aynı yanıt, ilgili soruda da bulunabilir: Android stüdyosunda .so kitaplığını apk'ye dahil et


6
Compilegörev kullanımdan kaldırıldı. JavaCompileBunun yerine kullanın (ilgili cevaplardan)
Sergii

görevleri nereye koymalıyım?
masoud vali

2
Lütfen önce jniLibs klasör çözümünü deneyin. Bu görevler, uygulama / kitaplık gradle.build dosyanıza eklenmelidir.
nenick


ayrıca buraya bakın (farklı mimari alt klasörlerini listeler): cumulations.com/blogs/9/…
NorbertM

222

Android Studio 1.0.2'de .so Kitaplığı ekleme

  1. "Src / main /" içinde "jniLibs" Klasörü oluşturun
  2. Tüm .so kitaplıklarınızı "src / main / jniLibs" klasörüne koyun
  3. Klasör yapısı,
    | --app:
    | - | --src:
    | - | - | --main
    | - | - | - | --jniLibs
    | - | - | - | - | --armeabi
    | - | - | - | - | - | -. so Dosyaları
    | - | - | - | - | --x86
    | - | - | - | - | - | -. so Dosyaları
  4. Ekstra kod gerekmez, sadece projenizi senkronize edin ve uygulamanızı çalıştırın.

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

6
Bu, Studio'nun 16 Haziran 2015 beta sürümünde
çalışmıyor

6
Android Studio 1.2.2'de çalışan bu doğru cevaptır. kontrol edildi ve doğrulandı.
Akhil Jain

3
Android Studio 1.3.1 ile çalışma.
Jaime Hablutzel

3
Benim için çalıştı thnx. android studio 2.1.2 :)
ShujatAli

3
Android Studio 3.2.1 ile çalışır, harika! Hala hiçbir yerde belgelenmedi! ???
NorbertM

29

1.Çözüm: Bir JniLibs klasörünün oluşturulması

Uygulamanızda "jniLibs" adlı bir klasör oluşturun ve içinde * .so'nuzu içeren klasörler oluşturun. "JniLibs" klasörünün "Java" veya "Assets" klasörlerinizle aynı klasörde oluşturulması gerekir.

2.Çözüm: build.gradle dosyasının değiştirilmesi

Yeni bir klasör oluşturmak ve * .so dosyalarınızı libs klasöründe tutmak istemiyorsanız, bu mümkündür!

Bu durumda, * .so dosyalarınızı libs klasörüne ekleyin (lütfen çözüm 1: libs / armeabi / .so ile aynı mimariye uyun) ve kaynak dizini eklemek için uygulamanızın build.gradle dosyasını değiştirin jniLibs.

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

Burada size yardımcı olacak ekran görüntüleriyle birlikte daha fazla açıklamaya sahip olacaksınız (Adım 6):

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

DÜZENLE Kodun düzenlenmiş jni.srcDirs değil jniLibs.srcDirs olması gerekiyordu. Dizin, proje dizininin dışına işaret eden [göreceli] bir yol olabilir.


1
Çözüm 2 benim için çalışmıyor. Bir yapı hatası alıyorum: "'main' kaynak kümesinde 'jni' özelliği bulunamadı."
Greg Brown

İşin sırrı "jniLibs" klasörünün "Java" veya "Varlıklar" klasörlerinizle aynı klasörde oluşturulması gerekiyordu. " Teşekkürler!
Seraphim'in

Yöntem 1 doğru bir şekilde
derlememe

Çözüm 2, yerel kitaplıkların konumunun belirlenmesine izin vermek için jni.srcDirs'i değil jniLibs.srcDirs'i kullanmak zorundaydı (yol göreceli veya mutlak olabilir ve proje dizininin dışına bile işaret edebilir).
astraujums

source Sets {android {
2.Çözüm

26

* Android Studio'da .so kitaplığı

Android Studio projelerinde main içinde jniLibs klasörü oluşturmalı ve tüm .so dosyalarınızı içine koymalısınız. Bu satırı build.gradle'a da entegre edebilirsiniz.

fileTree derleyin (dir: 'libs', şunları içerir: [' .jar', ' .so'])

Mükemmel çalışıyor

| --App:

| - | --src:

| - | - | --main

| - | - | - | --jniLibs

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

| - | - | - | - | - | -. so Dosyaları

Proje yapısı budur.


4
Ekleme .bu içinde derleme FileTree (dir: 'kütüphaneleri', şunları içerir: [ ', böylece', 'Jar']) benim PRB çözüldü. thnx
BST Kaal

Hala aşağıdaki çözümün peşindeyse, android ndk r10e'yi deneyin
Vineet Setia

12

Bu benim build.gradle dosyam, lütfen satıra dikkat edin

jniLibs.srcDirs = ['libs']

Bu, libs'in * .so dosyasını apk'ye dahil edecektir.

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

Android NDK resmi hello-libsCMake örneği

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

Benim için Ubuntu 17.10 host, Android Studio 3, Android SDK 26 üzerinde çalıştım, bu yüzden projenizi buna dayandırmanızı şiddetle tavsiye ederim.

Paylaşılan kitaplık denir libgperf, anahtar kod parçaları şunlardır:

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

    Ardından, /data/appcihazın altına bakarsanız , libgperf.soorada da olacaktır.

  • C ++ kodunda şunu kullanın: #include <gperf.h>

  • başlık konumu: hello-libs/distribution/gperf/include/gperf.h

  • kitaplık konumu: distribution/gperf/lib/arm64-v8a/libgperf.so

  • Yalnızca bazı mimarileri destekliyorsanız, bkz: Gradle Build NDK yalnızca hedef ARM

Örnek git, önceden oluşturulmuş paylaşılan kitaplıkları izler, ancak aynı zamanda onları gerçekten oluşturmak için derleme sistemini de içerir: https://github.com/googlesamples/android-ndk/tree/840858984e1bb8a7fab37c1b7c571efbe7d6eb75/hello-libs/gen-libs


2

Yerel kitaplığı (yani dosyaları) kullanmak için "build.gradle" dosyasına bazı kodlar eklemeniz gerekir.

Bu kod "armeabi" dizinini temizlemek ve "so" dosyalarını "armeabi" ye kopyalamak ve "temiz proje" yapmak içindir.

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

Aşağıdan yönlendirildim. https://gist.github.com/pocmo/6461138


2

Jar dosyalarının içinde paketlenmiş harici yerel kitaplık bağımlılıklarını kullanarak benzer bir sorunu çözdüm. Bazen bu mimari bağımlı kitaplıklar tek bir kavanoz içinde paketlenir, bazen birkaç jar dosyasına bölünürler. bu yüzden yerel kitaplıklar için jar bağımlılıklarını taramak ve bunları doğru android kitaplık klasörlerinde sıralamak için bazı buildscript yazdım. Buna ek olarak, bu aynı zamanda maven depolarında bulunmayan bağımlılıkları indirmenin bir yolunu sağlar; bu, şu anda JNA'nın android üzerinde çalışmasını sağlamak için yararlıdır çünkü tüm yerel kavanozlar genel maven depolarında yayınlanmamaktadır.

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

Yukarıdaki cevaplardaki çözümleri denedim ama hiçbiri benim için işe yaramadı. .So, .dll ve .jar dosyalarını içeren bir kütüphanem vardı. Sonunda bunu yaptım, ayrıntıları burada görebilirsiniz: https://stackoverflow.com/a/54976458/7392868

.So dosyalarını jniLibs adlı bir klasöre kopyalayıp app / src / main / klasörüne yapıştırdım. Diğer bağımlılıklar için not bağımlılıklarını kullandım.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.