마스터Q&A 안드로이드는 안드로이드 개발자들의 질문과 답변을 위한 지식 커뮤니티 사이트입니다. 안드로이드펍에서 운영하고 있습니다. [사용법, 운영진]

.so파일을 Load하는 부분에 대해 질문드립니다

0 추천

linux(Ubuntu 환경)에서 .so파일을 생성한 뒤 Windows의 Android studio에 추가해주었습니다.

app>src>main>jniLib>{ABI(armeabi, arbeabi-v7a, x86)}>libmain.so

그리고 .so 파일을 .zip파일로 압축한 후 .jar로 형식을 바꿔준 뒤 app>libs>main.jar에 추가하였습니다.

그리고 app/build.gradle에

ndk {
            abiFilters "armeabi", "armeabi-v7a", "x86"
}

packagingOptions {
            exclude '/lib/armeabi/libgnustl_shared.so'
            exclude '/lib/armeabi-v7a/libgnustl_shared.so'
            exclude '/lib/x86/libgnustl_shared.so'
}
sourceSets{
        main{
            jni.srcDirs = []
            jniLibs.srcDirs 'libs'
        }
}
dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
}
task deleteOldJar(type: Delete) {
    delete 'libs/main.jar'
}

//task to export contents as jar
task exportJar(type: Copy) {
    from('build/intermediates/bundles/debug/') // or build/intermediates/bundles/release/
    into('libs/')
    include('classes.jar')
    ///Give whatever name you want to give
    rename('classes.jar', 'main.jar')
}

exportJar.dependsOn(deleteOldJar, build)

추가하고 gradle.properties에

android.useDeprecatedNdk=true

추가한 후 

static {
        System.loadLibrary("main");
}

이 부분에서

java.lang.UnsatisfiedLinkError: dlopen failed: library "libgnustl_shared.so" not found

이런 Error가 나는데 뭐 혹시 빠트린 부분이 있는건가요?

aaaandhelper (900 포인트) 님이 2018년 2월 13일 질문

1개의 답변

0 추천
 
채택된 답변

System.loadLibrary 의 경우 native library를 ABI 에 맞춰 libs/armeabi, libs/armeabi-v7a, libs/x86 등의 폴더에 있는 so를 로그하게 되어 있으며, 이름 또한 앞의 lib 과 뒤의 so를 밴 값을 넣게 되어 있는데, 뒤의 확장자를 jar로 바꾸셨으니, 못 찾을 수 밖에 없습니다.

System.load 를 사용해서 full 경로를 입력하던지 so 경로를 ABI에 맞춘 폴더에 넣어주셔야 합니다.

익명사용자 님이 2018년 2월 13일 답변
aaaandhelper님이 2018년 3월 5일 채택됨
답변 감사합니다. 혹시 .so의 cpp파일 Main function이 int main(int argc, char *argv[])이 이런식이라면 JNI_OnLoad 작업을 해주어야 하나요?
so는 library (window로 치면 dll) 이지 실행 파일(exe)이 아니기 때문에 main을 사용하지 않습니다. jni에 선언된 메소드를 호출하는  java 파일을 직접 호출 해 주셔야 합니다.
예를 들어 java 파일이 com.test.TestLibray.java 이고 void native main();  를 선언한다면, jni 쪽 파일의 void com_test_TestLibrary_main(Env* env, jobject thiz) {}  함수와 매핑되어, TestLibray.main();  호출 시 com_test_TestLibrary_main가 불립니다.
감사합니다. cpp코드의 int main 이 부분을 jni 형식에 맞춰 바꾸고 native를 Load하는 java의 패키지명과 동일한 헤더를 추가하는 방식으로 해결했습니다
...