Làm cách nào để đưa thư viện * .so vào Android Studio?


123

Tôi đã đọc nhiều chủ đề về cách thêm thư viện * .so vào Android Studio, nhưng không có chủ đề nào hoạt động, đặc biệt là khi nói đến văn bản: Điều này không hoạt động với xxx mới hơn (Android Studio, gradle, ...)

Chúng ta có thể bắt đầu lại mới được không? Tôi đã nhận:

Android Studio 0.6.0

Từ cấu trúc dự án, tôi thấy:

Vị trí SDK:

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

Dự án:

Gradle version 1.10
Android Plugin Version 0.11.+

Mô-đun / ứng dụng: Thuộc tính:

Biên dịch Sdk Phiên bản 19 Công cụ xây dựng Phiên bản 19.1.0

Sự phụ thuộc:

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

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

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

Tôi đã biên dịch trước các tệp * .so và tại ứng dụng demo chúng đang hoạt động. Tôi phải thay đổi mã nguồn của ứng dụng, vì vậy tôi cần xây dựng lại bằng các tệp * .so giống nhau.


thêm một file .so từ thư mục bên ngoài dự án android: stackoverflow.com/questions/50713933/...
user1506104

Kiểm tra câu trả lời tại đây: stackoverflow.com/a/54977264/8034839
shizhen

Câu trả lời:


108

Giải pháp tạm thời

Tạo thư mục project/app/src/main/jniLibs, sau đó đặt các *.sotệp của bạn trong các thư mục abi của chúng ở vị trí đó. Ví dụ,

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

Giải pháp không được chấp nhận

Thêm cả hai đoạn mã vào tệp gradle.build mô-đun của bạn dưới dạng phụ thuộc:

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

Cách tạo lọ tùy chỉnh này:

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

Câu trả lời tương tự cũng có thể được tìm thấy trong câu hỏi liên quan: Bao gồm thư viện .so trong apk trong android studio


6
Compilenhiệm vụ đã không được dùng nữa. Sử dụng JavaCompilethay thế (từ các câu trả lời liên quan)
Sergii

tôi nên đặt nhiệm vụ ở đâu?
masoud dũng cảm

2
Trước tiên hãy thử giải pháp thư mục jniLibs. Tác vụ này nên được đưa vào tệp gradle.build ứng dụng / thư viện của bạn.
nenick

Tài liệu tham khảo cho các jniLibsđường dẫn thư mục tại Hướng dẫn sử dụng Gradle Plugin - Cấu trúc dự án
Eido95

xem thêm tại đây (liệt kê các kiến trúc các thư mục con khác nhau): cumulations.com/blogs/9/...
NorbertM

222

Thêm thư viện .so trong Android Studio 1.0.2

  1. Tạo Thư mục "jniLibs" bên trong "src / main /"
  2. Đặt tất cả các thư viện .so của bạn bên trong thư mục "src / main / jniLibs"
  3. Cấu trúc thư mục trông giống như,
    | --app:
    | - | --src:
    | - | - | --main
    | - | - | - | --jniLibs
    | - | - | - | - | --armeabi
    | - | - | - | - | - | -. nên Tập tin
    | - | - | - | - | --x86
    | - | - | - | - | - | -. nên Tập tin
  4. Không có mã bổ sung yêu cầu chỉ cần đồng bộ hóa dự án của bạn và chạy ứng dụng của bạn.

    Tham khảo
    https://github.com/commonsguy/sqlcipher-gradle/tree/master/src/main

6
Đây không phải là làm việc với các ngày 16 Tháng 6 năm 2015 phiên bản beta của Studio
bugfixr

6
đây là câu trả lời chính xác, hoạt động trong Android Studio 1.2.2. đã kiểm tra và xác minh.
Akhil Jain

3
Làm việc với Android Studio 1.3.1.
Jaime Hablutzel

3
Làm việc cho tôi thnx. trên Android Studio 2.1.2 :)
ShujatAli

3
hoạt động với Android Studio 3.2.1, tuyệt vời! Vẫn không có tài liệu ở đâu! ???
NorbertM

29

Giải pháp 1: Tạo thư mục JniLibs

Tạo một thư mục có tên “jniLibs” trong ứng dụng của bạn và các thư mục chứa * .so bên trong của bạn. Thư mục "jniLibs" cần được tạo trong cùng thư mục với thư mục "Java" hoặc "Tài sản" của bạn.

Giải pháp 2: Sửa đổi tệp build.gradle

Nếu bạn không muốn tạo một thư mục mới và giữ các tệp * .so của mình trong thư mục libs, bạn hoàn toàn có thể làm được!

Trong trường hợp đó, chỉ cần thêm tệp * .so của bạn vào thư mục libs (vui lòng tôn trọng kiến ​​trúc tương tự như giải pháp 1: ví dụ: libs / armeabi / .so) và sửa đổi tệp build.gradle của ứng dụng để thêm thư mục nguồn của jniLibs.

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

Bạn sẽ có nhiều giải thích hơn, với ảnh chụp màn hình để giúp bạn ở đây (Bước 6):

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

CHỈNH SỬA Nó phải là jniLibs.srcDirs, không phải jni.srcDirs - đã chỉnh sửa mã. Thư mục có thể là một đường dẫn [tương đối] trỏ ra ngoài thư mục dự án.


1
Giải pháp 2 không hiệu quả với tôi. Tôi gặp lỗi bản dựng: "Không thể tìm thấy thuộc tính 'jni' trên bộ nguồn 'chính'."
Greg Brown

Bí mật là 'Thư mục "jniLibs" cần được tạo trong cùng một thư mục với thư mục "Java" hoặc "Tài sản" của bạn.'. Cảm ơn!
Seraphim's

Phương pháp 1 cho phép tôi để biên dịch một cách chính xác, một giây tạo ra một "cpp" thư mục trong AS và đã cho tôi lỗi về việc thiếu C ++
fillobotto

Giải pháp 2 phải sử dụng jniLibs.srcDirs, không phải jni.srcDirs để cho phép chỉ định vị trí của các thư viện gốc (đường dẫn có thể tương đối hoặc tuyệt đối và có thể trỏ ngay cả bên ngoài thư mục dự án).
astraujums

Đối với Giải pháp 2, bạn cần đặt source Sets {mã dưới android {phần
yennster

26

* Thư viện .so trong Android Studio

Bạn phải tạo thư mục jniLibs bên trong main trong các dự án android Studio và đặt tất cả các tệp .so của bạn vào bên trong. Bạn cũng có thể tích hợp dòng này trong build.gradle

biên dịch fileTree (dir: 'libs', bao gồm: [' .jar', ' .so'])

Nó hoạt động hoàn hảo

| --app:

| - | --src:

| - | - | - chính

| - | - | - | --jniLibs

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

| - | - | - | - | - | -. nên Tập tin

Đây là cấu trúc dự án.


4
Thêm .so trong biên dịch fileTree (dir: 'libs', include: ['.jar', '. So']) đã giải quyết được prb của tôi. thnx
BST Kaal

Nếu nó vẫn còn sau giải pháp dưới đây, hãy thử android ndk r10e
Vineet Setia

12

Đây là tệp build.gradle của tôi, Xin lưu ý dòng

jniLibs.srcDirs = ['libs']

Điều này sẽ bao gồm tệp * .so của libs vào 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-libsVí dụ về CMake chính thức của Android NDK

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

Vừa làm việc cho tôi trên máy chủ Ubuntu 17.10, Android Studio 3, Android SDK 26, vì vậy tôi thực sự khuyên bạn nên căn cứ vào dự án của mình.

Thư viện được chia sẻ được gọi libgperf, các phần mã chính là:

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

    Sau đó, nếu bạn nhìn /data/appvào thiết bị, libgperf.socũng sẽ ở đó.

  • trên mã C ++, sử dụng: #include <gperf.h>

  • vị trí tiêu đề: hello-libs/distribution/gperf/include/gperf.h

  • vị trí lib: distribution/gperf/lib/arm64-v8a/libgperf.so

  • Nếu bạn chỉ hỗ trợ một số kiến ​​trúc, hãy xem: Gradle Build NDK chỉ nhắm mục tiêu ARM

Ví dụ git theo dõi các thư viện được chia sẻ dựng sẵn, nhưng nó cũng chứa hệ thống xây dựng để thực sự xây dựng chúng: https://github.com/googlesamples/android-ndk/tree/840858984e1bb8a7fab37c1b7c571efbe7d6eb75/hello-libs/gen-libs


2

Để sử dụng thư viện gốc (so với các tệp) Bạn cần thêm một số mã vào tệp "build.gradle".

Mã này dùng để tách thư mục "armeabi" và sao chép các tệp "so" vào "armeabi" trong khi "dự án sạch".

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

Tôi đã được giới thiệu từ bên dưới. https://gist.github.com/pocmo/6461138


2

Tôi đã giải quyết một vấn đề tương tự bằng cách sử dụng các phụ thuộc lib gốc bên ngoài được đóng gói bên trong các tệp jar. Đôi khi các thư viện phụ thuộc kiến ​​trúc này được đóng gói tất cả bên trong một jar, đôi khi chúng được chia thành nhiều tệp jar. vì vậy tôi đã viết một số bản xây dựng để quét các phụ thuộc jar cho các lib gốc và sắp xếp chúng vào các thư mục lib android chính xác. Ngoài ra, điều này cũng cung cấp một cách để tải xuống các phụ thuộc không có trong maven repo hiện đang hữu ích để JNA hoạt động trên android vì không phải tất cả các lọ gốc đều được xuất bản trong repos maven công khai.

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

Tôi đã thử các giải pháp trong các câu trả lời ở trên nhưng không có giải pháp nào phù hợp với tôi. Tôi đã có một thư viện với các tệp .so, .dll và .jar. Ở phần cuối, tôi đã làm điều này, bạn có thể xem chi tiết tại đây: https://stackoverflow.com/a/54976458/7392868

Tôi sao chép đã dán các tệp .so vào một thư mục có tên jniLibs và dán nó vào bên trong thư mục app / src / main /. Đối với các phụ thuộc khác, tôi đã sử dụng các phụ thuộc cấp.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.