首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >无法从应用程序项目加载存储在库中的.so文件

无法从应用程序项目加载存储在库中的.so文件
EN

Stack Overflow用户
提问于 2020-01-29 13:18:34
回答 3查看 4K关注 0票数 3

0。问题

我创建了一个Android库(aar),其中包含一些so文件。

在成功地在我的Android应用程序项目中加载了aar文件之后,我尝试加载so文件(来自aar类),但是java.lang.UnsatisfiedLinkError失败了。

我认为Android应用程序不是为了加载so文件而查看aar内部,而是查看Android应用程序中的lib文件夹。

(我知道我可以在android应用程序中直接复制那些共享库,但我不想这样做)

1.创建Android库(aar)

build.gradle

代码语言:javascript
复制
    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库项目中的代码

代码语言:javascript
复制
   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

2. Android应用程序项目

我创建了一个Android应用程序项目,添加了aar文件作为依赖项(它工作得很好)。我调用我从aar文件创建的Singleton类,然后尝试使用System.loadlibrary()Relinker从库类加载so文件。

build.gradle

代码语言:javascript
复制
    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,我使用递归()方法来检查每个文件夹:

代码语言:javascript
复制
    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)的文件夹。

如果有人知道如何加载在aar文件内的so文件没有,请告诉我。如果你需要更多的信息,请告诉我。

解决方案(但我不想那样)

我可以在应用程序的.so文件夹中复制jniLibs文件。它会正常工作的。但这不是我想要的。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2020-01-30 18:08:15

我终于自己想出来了。

第一个问题来自我的cmakelists.txt

我从c源文件创建我的-lib-1,然后创建我的-lib-2,以便将我的-lib-1与一些用于jniexport的cpp文件链接起来。

但是指向my 1的链接是为编译时间正确设置的,但是当我从我的-lib-1创建-lib-2时,对my 1的引用被破坏了。

使用System.loadlibrary()方法加载my 2会引发一个错误:java.lang.UnsatisfiedLinkError表示没有找到my 1(而不是my 2)。我就是这样解决第一个问题的。

解决办法:

代码语言:javascript
复制
# 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无法找到我的-lib-2。Relinker正在寻找错误文件夹中的库(lib文件夹而不是jni文件夹)。

fyi : lib文件夹是android应用程序的库文件夹,jni文件夹是aar库的库文件夹

原因可能是因为Relinker是从android应用程序中调用的,这意味着它将查看应用程序本机库文件夹,而不是aar文件夹(其中包含my-lib-2)。

解决方案: 1.从我的aar类中删除relinker 2. load库:

代码语言:javascript
复制
System.loadLibrary(my_lib_2);

就这样

谢谢@bruno的帮助

票数 3
EN

Stack Overflow用户

发布于 2020-01-29 13:22:15

在我看来,您不能在aar库中加载so文件。

您需要做的是在您的aar中使用一个包装器来访问.so特性,因为我想,在加载.so时,您的.so是加载的。

票数 1
EN

Stack Overflow用户

发布于 2020-05-22 09:36:12

对我来说,问题是我没有使用@aar后缀。所以我不得不用:

代码语言:javascript
复制
implementation('lib:2.0.3@aar') {
    transitive = true
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59967984

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档