एंड्रॉइड स्टूडियो में * .so पुस्तकालय कैसे शामिल करें?


123

मैंने कई थ्रेड्स पढ़े कि एंड्रॉइड स्टूडियो में एक .so पुस्तकालय कैसे जोड़ा जाए, लेकिन उनमें से कोई भी काम नहीं करता है, खासकर जब यह पाठ के बिंदु पर आता है: यह नए xxx (एंड्रॉइड स्टूडियो, ग्रेडेल, ...) के साथ काम नहीं करता है

क्या हम एक नई शुरुआत कर सकते हैं। मुझे मिला:

एंड्रॉइड स्टूडियो 0.6.0

परियोजना संरचना से मैं देख रहा हूँ:

एसडीके स्थान:

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

संबंधित प्रश्न में भी एक ही उत्तर पाया जा सकता है: एंड्रॉइड स्टूडियो में apk में .so पुस्तकालय शामिल करें


6
Compileकार्य को हटा दिया गया है। JavaCompileइसके बजाय (संबंधित उत्तरों से) का उपयोग करें
सर्गई

मुझे कहां काम करना चाहिए?
मसूद वली

2
कृपया पहले jniLibs फ़ोल्डर समाधान का प्रयास करें। यह कार्य आपके एप्लिकेशन / लाइब्रेरी gradle.build फ़ाइल में डाला जाना चाहिए।
nenick


यहाँ भी देखें (विभिन्न आर्किटेक्चर सब-फ़ोल्डर्स को सूचीबद्ध करता है): cumulations.com/blogs/9/…
नॉर्बर्टम

222

एंड्रॉइड स्टूडियो में .so पुस्तकालय जोड़ना 1.0.2

  1. "Src / main /" के अंदर "jniLibs" फ़ोल्डर बनाएँ
  2. अपने सभी .so पुस्तकालयों को "src / main / jniLibs" फ़ोल्डर के अंदर रखें
  3. फ़ोल्डर संरचना जैसा दिखता है;
    - --app:
    | - | --src:
    | - | - | --main
    | - | - | - | --jniLibs
    | - | - | - | - | --armeabi
    | - | - | - | - | - | - | - इसलिए फ़ाइलें
    | - | - | - | - | - | - x86
    | - | - | | - | - | - | - | - तो फ़ाइलें
  4. किसी अतिरिक्त कोड के लिए केवल आपकी परियोजना को सिंक करने और आपके एप्लिकेशन को चलाने की आवश्यकता नहीं है।

    संदर्भ
    https://github.com/commonsguy/sqlcipher-gradle/tree/master/src/main

6
यह 16 जून, 2015 के स्टूडियो संस्करण के साथ काम नहीं कर रहा है
Bugfixr

6
यह सही उत्तर है, एंड्रॉइड स्टूडियो 1.2.2 में काम कर रहा है। जाँच की और सत्यापित किया।
अखिल जैन

3
एंड्रॉइड स्टूडियो 1.3.1 के साथ काम करना।
Jaime Hablutzel

3
मेरे लिए काम किया thnx। एंड्रॉइड स्टूडियो पर 2.1.2 :)
शूजतअली

3
एंड्रॉइड स्टूडियो 3.2.1 के साथ काम करता है, बढ़िया! अभी भी कहीं दस्तावेज नहीं है ???
नोर्बर्टएम

29

समाधान 1: JniLibs फ़ोल्डर का निर्माण

अपने ऐप में “jniLibs” नामक फोल्डर बनाएं और आपके अंदर .so वाले फोल्डर। "JniLibs" फ़ोल्डर को आपके "Java" या "Assets" फ़ोल्डर के समान फ़ोल्डर में बनाने की आवश्यकता है।

समाधान 2: build.gradle फ़ाइल का संशोधन

यदि आप एक नया फ़ोल्डर नहीं बनाना चाहते हैं और अपनी * .so फाइलों को लिबास फोल्डर में रखना चाहते हैं, तो यह संभव है!

उस स्थिति में, बस अपनी * .so फ़ाइलों को लिबास फ़ोल्डर में जोड़ें (कृपया समाधान 1: libs / armeabi / .so उदाहरण के लिए समान आर्किटेक्चर का सम्मान करें) और स्रोत निर्देशिका को जोड़ने के लिए अपने ऐप की बिल्ड.gradle फ़ाइल को संशोधित करें। jniLibs की।

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

आपके पास यहां (चरण 6) में मदद करने के लिए स्क्रीनशॉट के साथ अधिक स्पष्टीकरण होंगे:

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

EDIT यह jniLibs.srcDirs होना था, jni.srcDirs नहीं - कोड को संपादित किया। निर्देशिका एक [रिश्तेदार] पथ हो सकता है जो परियोजना निर्देशिका के बाहर इंगित करता है।


1
समाधान 2 मेरे लिए काम नहीं करता है। मुझे एक बिल्ड त्रुटि मिलती है: "स्रोत सेट 'मुख्य' पर संपत्ति 'जेनी' नहीं मिली।"
ग्रेग ब्राउन

रहस्य यह था कि "jniLibs" फ़ोल्डर को आपके "Java" या "हैंडसेट" फ़ोल्डर के समान फ़ोल्डर में बनाने की आवश्यकता है। ' धन्यवाद!
सेराफिम का

विधि 1 ने मुझे सही ढंग से संकलित करने की अनुमति दी, दूसरे ने एएस में एक "सीपीपी" फ़ोल्डर बनाया और मुझे सी ++ संकलक के गायब होने के बारे में त्रुटि दी
fillobotto

समाधान 2 में jniLibs.srcDirs का उपयोग करना था, न कि jni.srcDirs को देशी पुस्तकालयों के स्थान को निर्दिष्ट करने की अनुमति देने के लिए (पथ सापेक्ष या निरपेक्ष हो सकता है और परियोजना निर्देशिका के बाहर भी इंगित कर सकता है)।
अस्त्राजुम्स

समाधान 2 के लिए आपको source Sets {कोड को android {अनुभाग के नीचे
रखना होगा

26

एंड्रॉयड स्टूडियो में .so पुस्तकालय

आपको एंड्रॉइड स्टूडियो परियोजनाओं में मुख्य रूप से अंदर jniLibs फ़ोल्डर उत्पन्न करना है और अपनी सभी .so फाइलें अंदर डालनी हैं। आप इस लाइन को build.gradle में भी एकीकृत कर सकते हैं

संकलन फ़ाइलट्री (dir: 'libs', शामिल हैं: [' .jar', ' .so'])।

यह पूरी तरह से काम है

| --App:

| - | --src:

| - | - | --main

| - | - | - | --jniLibs

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

| - | - | - | - | - | - | - | तो फ़ाइलें

यह प्रोजेक्ट स्ट्रक्चर है।


4
संकलित फ़ाइल में .so जोड़ना (dir: 'libs', शामिल हैं: ['.jar', ''। '' इसलिए) ने मेरे prb को हल किया। thnx
बीएसटी काल

यदि यह समाधान के बाद भी नीचे है, तो एंड्रॉइड ndk r10e
विनीत सेतिया

12

यह मेरी बिल्ड.ग्रेडल फ़ाइल है, कृपया लाइन पर ध्यान दें

jniLibs.srcDirs = ['libs']

इसमें लिबास की * .so फ़ाइल को एपीके में शामिल किया जाएगा।

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 आधिकारिक hello-libsCMake उदाहरण

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

बस उबंटू 17.10 होस्ट, एंड्रॉइड स्टूडियो 3, एंड्रॉइड एसडीके 26 पर मेरे लिए काम किया, इसलिए मैं दृढ़ता से अनुशंसा करता हूं कि आप इस पर अपनी परियोजना को आधार बनाते हैं।

साझा पुस्तकालय कहा जाता है libgperf, कुंजी कोड भागों हैं:

  • हैलो-लिबास / ऐप / 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)
  • एप्लिकेशन / 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

  • यदि आप केवल कुछ आर्किटेक्चर का समर्थन करते हैं, तो देखें: ग्रैड बिल्ड एनडीके लक्ष्य केवल एआरएम

उदाहरण git पूर्वनिर्मित साझा पुस्तकालयों को ट्रैक करता है, लेकिन इसमें वास्तव में उन्हें बनाने के लिए बिल्ड सिस्टम भी शामिल है: https://github.com/googlesamples/android-ndk/tree/840858984e1bbb7a7fab37c1b7c571efbe7d6eb75/hello-libs/


2

देशी-पुस्तकालय (इतनी फाइलें) का उपयोग करने के लिए आपको "build.gradle" फ़ाइल में कुछ कोड जोड़ने होंगे।

यह कोड "आर्मेबी" निर्देशिका को क्लीइंग करने और 'क्लीन प्रोजेक्ट' के दौरान 'आर्मएबी' में 'फाइल' को कॉपी करने के लिए है।

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

मैंने बाहरी देशी वाणिज्यिक निर्भरता का उपयोग करके एक समान समस्या हल की है जो जार फ़ाइलों के अंदर पैक की गई है। कभी-कभी इन आर्किटेक्चर पर निर्भर पुस्तकालयों को एक जार के अंदर पूरी तरह से पैक किया जाता है, कभी-कभी उन्हें कई जार फ़ाइलों में विभाजित किया जाता है। इसलिए मैंने देशी कामों के लिए जार निर्भरता को स्कैन करने और उन्हें सही एंड्रॉइड लिबर फ़ोल्डर में सॉर्ट करने के लिए कुछ बिल्डडस्क्रिप्ट लिखी हैं। इसके अतिरिक्त यह मावेन रेपो में न मिलने वाली निर्भरता को डाउनलोड करने का एक तरीका भी प्रदान करता है जो वर्तमान में JNA को एंड्रॉइड पर काम करने के लिए उपयोगी है क्योंकि सभी देशी जार सार्वजनिक मावेन रेपो में प्रकाशित नहीं होते हैं।

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

मैंने jniLibs नामक फ़ोल्डर में .so फ़ाइलों को कॉपी किया और इसे ऐप / src / main / फ़ोल्डर के अंदर चिपकाया। अन्य निर्भरता के लिए मैंने ग्रेड निर्भरता का उपयोग किया।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.