Android Studio에 * .so 라이브러리를 포함하는 방법은 무엇입니까?


123

* .so 라이브러리를 Android Studio에 추가하는 방법을 여러 스레드에서 읽었지만 특히 텍스트의 요점에 관해서는 작동하지 않습니다. 최신 xxx (Android Studio, gradle 등)에서는 작동하지 않습니다.

새로 시작해 주 시겠어요? 나는 얻었다 :

안드로이드 스튜디오 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 파일로 다시 빌드해야합니다.


android 프로젝트 외부 디렉토리에서 .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)
}

관련 질문에서도 동일한 답변을 찾을 수 있습니다 .Android 스튜디오의 apk에 .so 라이브러리 포함


6
Compile작업은 더 이상 사용되지 않습니다. 사용 JavaCompile(관련 답변에서) 대신
Sergii

작업을 어디에 두어야합니까?
masoud vali

2
먼저 jniLibs 폴더 솔루션을 시도하십시오. 이 작업은 앱 / 라이브러리 gradle.build 파일에 넣어야합니다.
nenick

에 대한 참조 jniLibs에서 디렉토리 경로 Gradle을 플러그인 사용자 가이드 - 프로젝트 구조
Eido95

또한 여기 (목록 다른 아키텍처 하위 폴더)를 참조하십시오 : cumulations.com/blogs/9/...
NorbertM

222

Android Studio 1.0.2에 .so 라이브러리 추가

  1. "src / main /"안에 "jniLibs"폴더 생성
  2. 모든 .so 라이브러리를 "src / main / jniLibs"폴더에 넣습니다.
  3. 폴더 구조는 다음과 같습니다.
    | --app :
    |-| --src :
    |-|-| --main
    |-|-|-| --jniLibs
    |-|-|- |-| --armeabi
    |-|-|-|-|-|-. so 파일
    |-|-|-|-| --x86
    |-|- |-|-|-|-. so 파일
  4. 추가 코드는 프로젝트를 동기화하고 애플리케이션을 실행하기 만하면됩니다.

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

6
이것은 Studio의 2015 년 6 월 16 일 베타 버전에서 작동하지 않습니다
bugfixr

6
이것은 Android Studio 1.2.2에서 작동하는 정답입니다. 확인하고 확인했습니다.
Akhil Jain

3
Android Studio 1.3.1로 작업.
Jaime Hablutzel

3
나를 위해 일했다 thnx. : 안드로이드 스튜디오 2.1.2에
ShujatAli

3
Android Studio 3.2.1에서 작동합니다. 아직 어디에도 문서화되지 않았습니다! ???
NorbertM

29

솔루션 1 : JniLibs 폴더 생성

앱에 "jniLibs"라는 폴더를 만들고 내부에 * .so를 포함하는 폴더를 만듭니다. "jniLibs"폴더는 "Java"또는 "Assets"폴더와 동일한 폴더에 생성되어야합니다.

해결 방법 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/

편집 그것은 jni.srcDirs가 아니라 jniLibs.srcDirs이어야했습니다-코드를 편집했습니다. 디렉토리는 프로젝트 디렉토리 외부를 가리키는 [상대적] 경로 일 수 있습니다.


1
솔루션 2가 작동하지 않습니다. 빌드 오류 : "소스 세트 'main'에서 'jni'속성을 찾을 수 없습니다."
Greg Brown

비밀은 ' "Java"또는 "Assets"폴더와 동일한 폴더에 "jniLibs"폴더를 만들어야한다는 것입니다. " 감사!
Seraphim의

방법 1을 사용하면 올바르게 컴파일 할 수 있고, 두 번째 방법은 AS에 "cpp"폴더를 생성하고 C ++ 컴파일러 누락에 대한 오류를 표시했습니다
fillobotto

솔루션 2는 네이티브 라이브러리의 위치를 ​​지정하기 위해 jni.srcDirs가 아닌 jniLibs.srcDirs를 사용해야했습니다 (경로는 상대 또는 절대 경로 일 수 있으며 프로젝트 디렉토리 외부를 가리킬 수도 있음).
astraujums

솔루션 2의 source Sets {경우 android {섹션 아래에 코드 를 배치해야합니다
yennster

26

* Android Studio의 .so 라이브러리

android Studio 프로젝트의 main 안에 jniLibs 폴더를 생성하고 모든 .so 파일을 안에 넣어야합니다. 이 줄을 build.gradle에 통합 할 수도 있습니다.

컴파일 fileTree (dir : 'libs', include : [ ' .jar', ' .so'])

완벽하게 작동합니다

|-앱 :

|-| --src :

|-|-|-메인

|-|-|-| --jniLibs

|-|-|-|-|-아르미 아비

|-|-|-|-|-|-. so 파일

이것이 프로젝트 구조입니다.


4
컴파일 fileTree (dir : 'libs', include : [ '.jar', '. so'])에 .so 를 추가하면 내 prb가 해결되었습니다. thnx
BST Kaal

아직 해결책 다음 아래의 경우, 안드로이드 NDK의 r10e 시도
Vineet SETIA

12

이것은 내 build.gradle 파일입니다.

jniLibs.srcDirs = ['libs']

여기에는 libs의 * .so 파일이 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

Android NDK 공식 hello-libsCMake 예제

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

Ubuntu 17.10 호스트, Android Studio 3, Android SDK 26에서 저를 위해 일 했으므로 프로젝트를 기반으로하는 것이 좋습니다.

공유 라이브러리는라고 libgperf하며 주요 코드 부분은 다음과 같습니다.

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

    그러면 /data/app장치 아래를 보면 libgperf.so거기도있을 것입니다.

  • C ++ 코드에서는 다음을 사용하십시오. #include <gperf.h>

  • 헤더 위치 : hello-libs/distribution/gperf/include/gperf.h

  • lib 위치 ​​: distribution/gperf/lib/arm64-v8a/libgperf.so

  • 일부 아키텍처 만 지원하는 경우 참조 : Gradle Build NDK target only ARM

예제 git은 미리 빌드 된 공유 라이브러리를 추적하지만 실제로 빌드하는 빌드 시스템도 포함합니다. https://github.com/googlesamples/android-ndk/tree/840858984e1bb8a7fab37c1b7c571efbe7d6eb75/hello-libs/gen-libs


2

네이티브 라이브러리 (so 파일)를 사용하려면 "build.gradle"파일에 일부 코드를 추가해야합니다.

이 코드는 "armeabi"디렉토리를 정리하고 'so'파일을 "armeabi"에 복사하는 동안 'clean project'를 수행하기위한 것입니다.

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 파일 내부에 패키지 된 외부 네이티브 lib 종속성을 사용하여 유사한 문제를 해결했습니다. 때로는 이러한 아키텍처 종속 라이브러리가 하나의 jar 안에 모두 함께 패키징되고 때로는 여러 jar 파일로 분할됩니다. 그래서 네이티브 lib에 대한 jar 종속성을 스캔하고 올바른 Android lib 폴더로 정렬하는 빌드 스크립트를 작성했습니다. 또한 모든 네이티브 jar가 공용 maven repos에 게시되지 않기 때문에 현재 Android에서 JNA를 작동시키는 데 유용한 maven repos에서 찾을 수없는 종속성을 다운로드하는 방법도 제공합니다.

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 파일을 복사하여 app / src / main / 폴더에 붙여 넣었습니다. 다른 종속성의 경우 등급 종속성을 사용했습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.