developer tip

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

optionbox 2020. 8. 6. 08:15
반응형

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


Android 스레드에 * .so 라이브러리를 추가하는 방법에 대한 많은 스레드를 읽었지만 특히 텍스트와 관련하여 아무것도 작동하지 않습니다. 새로운 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 파일로 다시 빌드해야합니다.


현재 솔루션

폴더 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')

이 사용자 정의 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 Studio의 APK에 .so 라이브러리 포함


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

* .so Android Studio의 라이브러리

android Studio 프로젝트에서 main 내부에 jniLibs 폴더를 생성하고 모든 .so 파일을 내부에 저장해야합니다. 이 라인을 build.gradle에 통합 할 수도 있습니다.

fileTree (dir : 'libs', 다음을 포함하십시오 : [ ' .jar', ' .so'])

완벽하게 작동합니다

|-앱 :

|-| --src :

|-|-|-주요

|-|-|-| --jniLibs

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

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

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


해결 방법 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 여야했습니다. 코드를 편집했습니다. 디렉토리는 프로젝트 디렉토리 외부를 가리키는 [상대] 경로 일 수 있습니다.


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

jniLibs.srcDirs = ['libs']

여기에는 apk to 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')
}

Android NDK 공식 hello-libsCMake 예

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

Just worked for me on Ubuntu 17.10 host, Android Studio 3, Android SDK 26, so I strongly recommend that you base your project on it.

The shared library is called libgperf, the key code parts are:

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

    Then, if you look under /data/app on the device, libgperf.so will be there as well.

  • on C++ code, use: #include <gperf.h>

  • header location: hello-libs/distribution/gperf/include/gperf.h

  • lib location: distribution/gperf/lib/arm64-v8a/libgperf.so

  • If you only support some architectures, see: Gradle Build NDK target only ARM

The example git tracks the prebuilt shared libraries, but it also contains the build system to actually build them as well: https://github.com/googlesamples/android-ndk/tree/840858984e1bb8a7fab37c1b7c571efbe7d6eb75/hello-libs/gen-libs


To use native-library (so files) You need to add some codes in the "build.gradle" file.

This code is for cleaing "armeabi" directory and copying 'so' files into "armeabi" while 'clean project'.

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

I've been referred from the below. https://gist.github.com/pocmo/6461138


I have solved a similar problem using external native lib dependencies that are packaged inside of jar files. Sometimes these architecture dependend libraries are packaged alltogether inside one jar, sometimes they are split up into several jar files. so i wrote some buildscript to scan the jar dependencies for native libs and sort them into the correct android lib folders. Additionally this also provides a way to download dependencies that not found in maven repos which is currently usefull to get JNA working on android because not all native jars are published in public 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'])

I tried the solutions in the above answers but none worked for me. I had a library with .so,.dll and .jar files. At the end I did this, you can see the details here: https://stackoverflow.com/a/54976458/7392868

I copy pasted the .so files in a folder named jniLibs and pasted it inside app/src/main/ folder. For other dependencies I used the grade dependencies.

참고URL : https://stackoverflow.com/questions/24357687/how-to-include-so-library-in-android-studio

반응형