Як включити * .so library в Android Studio?


123

Я читав багато тем, як додати бібліотеку * .so до Android Studio, але жодна з них не працює, особливо якщо мова йде про текст: Це не працює з новими xxx (Android Studio, gradle, ...)

Чи можемо ми почати новий початок. Я отримав:

Android Studio 0.6.0

Зі структури проекту я бачу:

Розташування SDK:

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

Проект:

Gradle version 1.10
Android Plugin Version 0.11.+

Модулі / додаток: Властивості:

Скомпілюйте Sdk Версія 19 Інструменти збирання Версія 19.1.0

Залежності:

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

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

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

Я отримав * .so файли заздалегідь складені і в демонстраційному додатку вони працюють. Мені потрібно змінити вихідний код програми, тому мені потрібно відновити ті самі * .so файли.


додати файл .so з каталогу поза андроїда проекту: stackoverflow.com/questions/50713933 / ...
user1506104

Перевірте відповідь тут: stackoverflow.com/a/54977264/8034839
Shizhen

Відповіді:


108

Поточне рішення

Створіть папку project/app/src/main/jniLibs, а потім помістіть свої *.soфайли в свої папки Abi в цьому місці. Наприклад,

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

Застаріле рішення

Додайте обидва фрагменти коду у файл модуля gradle.build як залежність:

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

Як створити цю власну баночку:

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

Таку ж відповідь можна знайти і в пов'язаному питанні: Включити .so library в apk в android studio


6
Compileзавдання застаріле. Використовуйте JavaCompileнатомість (із пов’язаних відповідей)
Сергій

куди мені поставити завдання?
masoud vali

2
Спробуйте спочатку рішення папки jniLibs. Ці завдання слід помістити у ваш додаток / бібліотеку gradle.build файл.
nenick

Довідка про jniLibsшлях до каталогу у посібнику користувача для
додатків

дивіться також тут (перераховує різні підпапки архітектури): cumulations.com/blogs/9/…
NorbertM

222

Додавання .so Library у Android Studio 1.0.2

  1. Створіть папку "jniLibs" всередині "src / main /"
  2. Помістіть усі ваші бібліотеки .so у папку "src / main / jniLibs"
  3. Папка структура виглядає,
    | --app:
    | - | --src:
    | - | - | --main
    | - | - | - | --jniLibs
    | - | - | - | - | --armeabi
    | - | - | - | - | - | -. Файли
    | - | - | - | - | --x86
    | - | - | - | - | - | -. так Файли
  4. Без зайвого коду не потрібно просто синхронізувати ваш проект та запустити свою програму.

    Довідка
    https://github.com/commonsguy/sqlcipher-gradle/tree/master/src/main

6
Це не працює з бета-версією Studio
bugfixr

6
це правильна відповідь, працюючи в Android Studio 1.2.2. перевірено і перевірено.
Ахіл Джайн

3
Робота з Android Studio 1.3.1.
Хайме Хаблуцель

3
Працював для мене thnx. на андроїд-студії 2.1.2 :)
ShujatAli

3
працює з Android Studio 3.2.1, чудово! Досі ніде не задокументовано! ???
NorbertM

29

Рішення 1: Створення папки JniLibs

Створіть у вашій програмі папку під назвою "jniLibs" та папки, що містять ваш * .so. Папку "jniLibs" потрібно створити в тій самій папці, що і ваші папки "Java" або "Активи".

Рішення 2: Модифікація файла build.gradle

Якщо ви не хочете створювати нову папку і зберігати свої * .so файли у папці libs, можливо!

У цьому випадку просто додайте свої * .so файли у папку libs (будь ласка, поважайте таку ж архітектуру, що і рішення 1: libs / armeabi / .so, наприклад) та змініть файл build.gradle вашого додатка, щоб додати вихідний каталог jniLibs.

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

У вас буде більше пояснень із скріншотами, які допоможуть вам тут (Крок 6):

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

EDIT Це повинен бути jniLibs.srcDirs, а не jni.srcDirs - редагував код. До каталогу може бути [відносний] шлях, який вказує поза каталогу проекту.


1
Рішення 2 не працює для мене. Я отримую помилку збирання: "Не вдалося знайти властивість 'jni' у наборі джерела" main "."
Грег Браун

Секрет полягав у тому, що "Папку" jniLibs "потрібно створити у тій самій папці, що і папки" Java "або" Активи "." Дякую!
Серафима

Метод 1 дозволив мені правильно скласти, другий створив папку "cpp" в AS і дав мені помилку щодо відсутнього компілятора C ++
fillobotto

Рішення 2 повинно було використовувати jniLibs.srcDirs, а не jni.srcDirs, щоб дозволити вказати місце розташування нативних бібліотек (шлях може бути відносним або абсолютним і може вказувати навіть поза каталогом проекту).
astraujums

Для вирішення 2 необхідно помістити source Sets {код під android {розділ
yennster

26

* .so library в Android Studio

Вам потрібно створити папку jniLibs всередині основної в проектах Android and Studio і помістити всі .so файли всередину. Ви також можете інтегрувати цей рядок у build.gradle

компілювати fileTree (dir: 'libs', include: [' .jar', ' .so'])

Це працює ідеально

| --app:

| - | --src:

| - | - | --основна

| - | - | - | --jniLibs

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

| - | - | - | - | - | -. Файли

Це структура проекту.


4
Додавання .so до компіляції fileTree (dir: 'libs', include: ['.jar', '. So']) вирішив мій prb. thnx
BST Kaal

Якщо це все ще залишається після рішення нижче, спробуйте android ndk r10e
Vineet Setia

12

Це мій файл build.gradle. Зверніть увагу на рядок

jniLibs.srcDirs = ['libs']

Сюди ввійде файл * .so libs для 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-libsприклад CMake для Android NDK

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

Просто працював для мене на хості Ubuntu 17.10, Android Studio 3, Android SDK 26, тому настійно рекомендую ви базувати на ньому свій проект.

Викликається спільна бібліотека libgperf, ключовими частинами коду є:

  • привіт-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']

    Тоді, якщо заглянути /data/appв пристрій, libgperf.soбуде і там.

  • у коді C ++ використовуйте: #include <gperf.h>

  • розташування заголовка: hello-libs/distribution/gperf/include/gperf.h

  • місце розташування: distribution/gperf/lib/arm64-v8a/libgperf.so

  • Якщо ви підтримуєте лише деякі архітектури, див.: Gradle Build NDK орієнтується лише на ARM

Приклад git відстежує попередньо вбудовані бібліотеки спільного використання, але він також містить систему збірки, щоб фактично їх створити: https://github.com/googlesamples/android-ndk/tree/840858984e1bb8a7fab37c1b7c571efbe7d6eb75/hello-libs/gen-libs


2

Щоб використовувати нативну бібліотеку (так файли) Вам потрібно додати кілька кодів у файл "build.gradle".

Цей код призначений для очищення каталогів "Armeabi" та копіювання файлів "so" у "Armeabi" під час "чистого проекту".

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

Мене посилали знизу. https://gist.github.com/pocmo/6461138


2

Я вирішив аналогічну проблему за допомогою зовнішніх залежних ліб, які запаковані всередині файлів jar. Іноді ці архітектури залежать від бібліотек, які повністю упаковані всередині однієї банку, іноді вони розділені на кілька файлів jar. тож я написав деякий buildscript, щоб просканувати залежність jar для власних libs та сортувати їх у правильні папки liroid android. Крім того, це також забезпечує спосіб завантаження залежностей, яких не знайдено в maven repos, який наразі корисний для того, щоб JNA працювала на андроїд, оскільки не всі рідні банки публікуються у публічних репортажах Maven.

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

Я спробував рішення у наведених вище відповідях, але жоден не працював на мене. У мене була бібліотека з файлами .so, .dll та .jar. Наприкінці я зробив це, ви можете ознайомитися з деталями тут: https://stackoverflow.com/a/54976458/7392868

Я копіюю вставлені .so файли у папку з іменем jniLibs та вставляв її всередину папки app / src / main /. Для інших залежностей я використав оціночні залежності.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.