Не удается загрузить .so файл, хранящийся в библиотеке (aar) из проекта приложения - PullRequest
0 голосов
/ 29 января 2020

0. Проблема

Я создал библиотеку Android (aar), которая содержит некоторые файлы.

После успешной загрузки файла aar в мой проект приложения Android я пытаюсь загрузить файлы so (из классов aar), но не удается выполнить java.lang.UnsatisfiedLinkError.

. Я думаю, что Приложение Android не ищет внутри aar для загрузки файлов so, но смотрит на папку lib, которая находится внутри приложения Android.

(я знаю, что могу скопировать эти разделяемые библиотеки напрямую в приложении android, но я не хочу этого делать)

1. Создайте библиотеку Android (aar)

build.gradle

    apply plugin: 'com.android.library'

    android {
        compileSdkVersion 29

        defaultConfig {
            minSdkVersion 21
            targetSdkVersion 29
            versionCode 1
            versionName "1.0"

            testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
            consumerProguardFiles 'consumer-rules.pro'

            externalNativeBuild {
                cmake {
                    cppFlags "-std=c++11"
                    abiFilters "armeabi-v7a", "arm64-v8a", "x86", "x86_64"
                }
            }

            packagingOptions {
                pickFirst 'lib/x86_64/libnanolcms.so'
                pickFirst 'lib/x86/libnanolcms.so'
                pickFirst 'lib/armeabi-v7a/libnanolcms.so'
                pickFirst 'lib/arm64-v8a/libnanolcms.so'
                pickFirst 'lib/x86_64/liblcms2.so'
                pickFirst 'lib/x86/liblcms2.so'
                pickFirst 'lib/armeabi-v7a/liblcms2.so'
                pickFirst 'lib/arm64-v8a/liblcms2.so'
            }
        }


        buildTypes {
            release {
                minifyEnabled false
                debuggable false
                proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
                jniDebuggable = true
            }
            debug {
                minifyEnabled false
                debuggable false
                jniDebuggable = true
                proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
            }
        }


        externalNativeBuild {
            cmake {
                version '3.6.0'
                path "src/main/jni/CMakeLists.txt"
            }
        }

        sourceSets {
            main {
                jniLibs.srcDirs = ['src/main/jnilibs']
                jni.srcDirs = [] //disable automatic ndk-build call
            }
        }
    }

    repositories {
        flatDir {
            dirs 'libs'
        }

        // to be able to compile opencv
        maven { url "https://jitpack.io" }
    }

    dependencies {
        implementation fileTree(include: ['*.jar','*.so'], dir: 'libs')
        implementation 'androidx.appcompat:appcompat:1.1.0'
        testImplementation 'junit:junit:4.13'
        androidTestImplementation 'androidx.test.ext:junit:1.1.1'
        androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
        implementation(name: 'openCV-3.3.1', ext: 'aar')

        implementation "com.getkeepsafe.relinker:relinker:1.4.0"
    }

из проекта библиотеки android

   if (useReLinker) {
        ReLinker.recursively().log(logcatLogger).loadLibrary(CXColorcatchManager.getInstance().getWeakContext().get(), libraryName, new ReLinker.LoadListener() {
                @Override
                public void success() {
                    CXLogger.verbose("Library " + libraryName + " successfully loaded");
                    libraryLoaderListener.onLibraryLoaded(true);
                }
                @Override
                public void failure(Throwable t) {
                    CXLogger.verbose("Unable to load " + libraryName + " library \n");
                    libraryLoaderListener.onLibraryLoaded(false);
                }
            });

        } else {
            try {
                System.loadLibrary(libraryName);
                libraryLoaderListener.onLibraryLoaded(true);
            } catch (Exception e) {
                CXLogger.verbose("Unable to load " + libraryName + " library \n " + e);
                libraryLoaderListener.onLibraryLoaded(false);
            }
        }
    }

Как вы можете видеть на На следующем рисунке файл aar содержит файлы so. Они находятся в папке jni, которая является правильной папкой, следующей документации

my-library.aar

enter image description here

2. Android проект приложения

Я создал проект приложения Android, добавил файл aar в качестве зависимости (он работает нормально). Я вызываю класс Singleton, который я создал из файла aar, затем пытаюсь загрузить файл so из класса библиотеки, используя System.loadlibrary() или Relinker .

build.gradle

    apply plugin: 'com.android.application'

    android {
        compileSdkVersion 29
        defaultConfig {
            applicationId "com.colorix.spike.nano"
            minSdkVersion 21

            targetSdkVersion 29
            versionCode 1
            versionName "1.0"
            testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
        }
        buildTypes {
            release {
                minifyEnabled false
                proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
            }
        }
        compileOptions {
            sourceCompatibility JavaVersion.VERSION_1_8
            targetCompatibility JavaVersion.VERSION_1_8
        }

        sourceSets {
            main {
                jniLibs.srcDirs = ['src/main/jnilibs']
            }
        }
    }

    dependencies {
        implementation 'androidx.appcompat:appcompat:1.1.0'
        implementation 'com.google.android.material:material:1.0.0'
        implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
        testImplementation 'junit:junit:4.13'
        androidTestImplementation 'androidx.test:runner:1.3.0-alpha03'
        androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0-alpha03'

        // my library
        implementation files('libs/my_library.aar')
        implementation "com.getkeepsafe.relinker:relinker:1.4.0"
    }

К сожалению, с System.loadlibrary() он не находит библиотеку: java.lang.UnsatisfiedLinkError

Используя Relinker, я использую метод recursive () для проверки каждой папки:

    V/ReLinkerInstance: [LibraryLoadingTask.log()-32]: Loading the library normally failed: java.lang.UnsatisfiedLinkError: dalvik.system.PathClassLoader[DexPathList[[zip file "/data/app/com.colorix.spike.nano-YmXglPRjs_msSVzvsySnZA==/base.apk"],nativeLibraryDirectories=[/data/app/com.colorix.spike.nano-YmXglPRjs_msSVzvsySnZA==/lib/x86, /system/lib]]] couldn't find "libnanolcms.so"
        at java.lang.Runtime.loadLibrary0(Runtime.java:1012)
        at java.lang.System.loadLibrary(System.java:1669)
        at com.getkeepsafe.relinker.SystemLibraryLoader.loadLibrary(SystemLibraryLoader.java:24)
        at com.getkeepsafe.relinker.ReLinkerInstance.loadLibraryInternal(ReLinkerInstance.java:163)
        at com.getkeepsafe.relinker.ReLinkerInstance.access$000(ReLinkerInstance.java:31)
        at com.getkeepsafe.relinker.ReLinkerInstance$1.run(ReLinkerInstance.java:142)
        at java.lang.Thread.run(Thread.java:764)
    V/ReLinkerInstance: [LibraryLoadingTask.log()-32]: nanolcms (null) was not loaded normally, re-linking...
    V/ReLinkerInstance: [LibraryLoadingTask.log()-32]: Looking for lib/x86/libnanolcms.so in APK     /data/app/com.colorix.spike.nano-YmXglPRjs_msSVzvsySnZA==/base.apk...
    V/ReLinkerInstance: [LibraryLoadingTask.log()-32]: Looking for lib/armeabi-v7a/libnanolcms.so in APK /data/app/com.colorix.spike.nano-YmXglPRjs_msSVzvsySnZA==/base.apk...
    [LibraryLoadingTask.log()-32]: Looking for lib/armeabi/libnanolcms.so in APK /data/app    /com.colorix.spike.nano-YmXglPRjs_msSVzvsySnZA==/base.apk...
    [LibraryLoadingTask.log()-32]: Looking for lib/x86/libnanolcms.so in APK /data/app    /com.colorix.spike.nano-YmXglPRjs_msSVzvsySnZA==/base.apk...
    [LibraryLoadingTask.log()-32]: Looking for lib/armeabi-v7a/libnanolcms.so in APK /data/app/com.colorix.spike.nano-YmXglPRjs_msSVzvsySnZA==/base.apk...
    V/ReLinkerInstance: [LibraryLoadingTask.log()-32]: Looking for lib/armeabi/libnanolcms.so in APK /data/app/com.colorix.spike.nano-YmXglPRjs_msSVzvsySnZA==/base.apk...
    [LibraryLoadingTask.log()-32]: Looking for lib/x86/libnanolcms.so in APK /data/app/com.colorix.spike.nano-YmXglPRjs_msSVzvsySnZA==/base.apk...
    [LibraryLoadingTask.log()-32]: Looking for lib/armeabi-v7a/libnanolcms.so in APK /data/app/com.colorix.spike.nano-YmXglPRjs_msSVzvsySnZA==/base.apk...
    V/ReLinkerInstance: [LibraryLoadingTask.log()-32]: Looking for lib/armeabi/libnanolcms.so in APK /data/app/com.colorix.spike.nano-YmXglPRjs_msSVzvsySnZA==/base.apk...
    V/ReLinkerInstance: [LibraryLoadingTask.log()-32]: Looking for lib/x86/libnanolcms.so in APK /data/app/com.colorix.spike.nano-YmXglPRjs_msSVzvsySnZA==/base.apk...
    [LibraryLoadingTask.log()-32]: Looking for lib/armeabi-v7a/libnanolcms.so in APK /data/app/com.colorix.spike.nano-YmXglPRjs_msSVzvsySnZA==/base.apk...
    [LibraryLoadingTask.log()-32]: Looking for lib/armeabi/libnanolcms.so in APK /data/app/com.colorix.spike.nano-YmXglPRjs_msSVzvsySnZA==/base.apk...
    V/ReLinkerInstance: [LibraryLoadingTask.log()-32]: Looking for lib/x86/libnanolcms.so in APK /data/app/com.colorix.spike.nano-YmXglPRjs_msSVzvsySnZA==/base.apk...
    V/ReLinkerInstance: [LibraryLoadingTask.log()-32]: Looking for lib/armeabi-v7a/libnanolcms.so in APK /data/app/com.colorix.spike.nano-YmXglPRjs_msSVzvsySnZA==/base.apk...
    V/ReLinkerInstance: [LibraryLoadingTask.log()-32]: Looking for lib/armeabi/libnanolcms.so in APK /data/app/com.colorix.spike.nano-YmXglPRjs_msSVzvsySnZA==/base.apk...
    W/orix.spike.nan: Accessing hidden method Landroid/view/View;->computeFitSystemWindows(Landroid/graphics/Rect;Landroid/graphics/Rect;)Z (light greylist, reflection)
    W/orix.spike.nan: Accessing hidden method Landroid/view /ViewGroup;->makeOptionalFitsSystemWindows()V (light greylist, reflection)
    V/ReLinkerInstance: [LibraryLoadingTask.failure()-54]: Unable to load nanolcms library 

Как видите, библиотека находится не в lib/<architecture/..., а в aar, которая находится в папке jni.

Если я понимаю документацию android, папка lib является папкой android приложение, а не папка библиотеки android (aar).

Если кто-то знает, как загрузить файл so, находящийся внутри файла aar, пожалуйста, дайте мне знать. Если вам нужна дополнительная информация, дайте мне знать.

Решение (но я этого не хочу)

Я могу скопировать .so файлы в папку jniLibs приложения. Это будет работать правильно. Но это не то, что я хочу.

Ответы [ 2 ]

1 голос
/ 30 января 2020

Я наконец-то понял это сам.

Первая проблема связана с моим cmakelists.txt

Я создаю my-lib-1 из c исходных файлов, затем я создал мой- lib-2, чтобы связать my-lib-1 с некоторыми cpp файлами для jniexport.

Но ссылка на my-lib-1 была правильно установлена ​​на время компиляции, но когда я создал my- В lib-2 из my-lib-1 ссылка на my-lib-1 была прервана.

Использование метода System.loadlibrary() для загрузки my-lib-2 вызвало ошибку: java.lang.UnsatisfiedLinkError, сказав, что my-lib-1 (не my-lib-2) не найден. Так я решаю первую проблему.

Решение:

# mylib1 - source files
file(GLOB SOURCES ${mylib1_source_DIR}/src/*.c)

# mylib1 - include header files
include_directories(${mylib1_source_DIR}/include/)

# compile and add our cpp files - Shared library
add_library(mylib2 SHARED ${SOURCES} mylib2.cpp)

# logger
find_library(log-lib log)

# include our header file
target_include_directories( mylib2 PRIVATE ${mylib1_source_DIR}/include )

# link our library (mylib2) with android and log libraries
target_link_libraries( mylib2 android ${log-lib})

Вторая проблема связана с relinker

Библиотека скомпилирована. Я использую Relinker для загрузки своей библиотеки, но Relinker не может найти my-lib-2. Relinker ищет библиотеку в неправильной папке (папка lib вместо папки jni).

fyi: папка lib - это папка библиотеки для android app jni folder - папка библиотеки для библиотеки aar

Причина, вероятно, в том, что Relinker вызывается из приложения android, что означает, что он будет смотреть на папку собственной библиотеки приложения, а не в папке aar (которая содержит my-lib-2)

Решение: 1. Удалите relinker 2. Загрузите библиотеку из моих классов:

System.loadLibrary(my_lib_2);

Вот и все

Спасибо @ bruno за вашу помощь

0 голосов
/ 29 января 2020

На мой взгляд, вы не можете загрузить файл so в aar lib.

Вам нужно сделать обертку в вашем aar для доступа к функциям .so, потому что ваш .so, я полагаю, загружается при загрузке aar.

...