Android本机库(.so)-不满意的链接错误 [英] Android native library (.so) - unsatisfied link error

查看:164
本文介绍了Android本机库(.so)-不满意的链接错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我最近创建并发布了一个Android App捆绑包,其中包含针对所有处理器架构的已编译本机库.在大多数设备上,一切运行正常.但是在某些设备上,我可以在Crashlytics控制台中看到此错误 致命异常:java.lang.UnsatisfiedLinkError dalvik.system.PathClassLoader [DexPathList [[zip文件"/system/framework/org.apache.http.legacy.boot.jar",zip文件"/data/app/com.someapp-wAu5DoLmLvM_RVnbU1qsCg==/base.apk"],nativeLibraryDirectories = [/data/app/com.someapp-wAu5DoLmLvm_RVnbU1qsCg ==/lib/arm64,/system/lib64]]]找不到"somemylib.so"

I have recently created and published an Android App bundle with compiled native libraries for all processors architectures. On most of devices everything is running ok. But on some of devices I can see this error in Crashlytics console Fatal Exception: java.lang.UnsatisfiedLinkError dalvik.system.PathClassLoader[DexPathList[[zip file "/system/framework/org.apache.http.legacy.boot.jar", zip file "/data/app/com.someapp-wAu5DoLmLvM_RVnbU1qsCg==/base.apk"],nativeLibraryDirectories=[/data/app/com.someapp-wAu5DoLmLvM_RVnbU1qsCg==/lib/arm64, /system/lib64]]] couldn't find "somemylib.so"

我想知道-为什么会发生这种情况.我有用于x64处理器的库.这仅在某些设备上发生-但是此崩溃在Crashlytics中最常见. 我所有的库都存储在jniLibs目录中 这些是我的build.gradle中的一些片段

I am wondering - why this may happen. I have libs for x64 processors. This is happening only on some devices - but this crash is the most often in Crashlytics. All my libs are stored inside jniLibs directory THese are some pieces from my build.gradle

bundle {
    density {
        // Different APKs are generated for devices with different screen densities; true by default.
        enableSplit false
    }
    abi {
        // Different APKs are generated for devices with different CPU architectures; true by default.
        enableSplit true
    }
    language {
        // This is disabled so that the App Bundle does NOT split the APK for each language.
        // We're gonna use the same APK for all languages.
        enableSplit false
    }
}
splits {
    abi {
        enable true
        reset()
        include 'armeabi', 'mips', 'x86', 'armeabi-v7a', 'arm64-v8a', 
 'mips64', 'x86_64'
    }
}
sourceSets {

    main {
        jniLibs.srcDirs = ['jniLibs']
    }
}

我的应用程序中有一个服务类,当有人启动它时,它试图加载本机库.我有时在操作系统可以检测到我的应用程序中的本机库之前就执行了对服务的开始"调用吗?但是我不这么认为. 你能帮我吗

I have a service class inside my app which is trying to load native library when someone is starting it. My be sometimes this "start" call to service is executing before the OS can detect the native libs in my app? But I don't think that this is so. Can you help me please

推荐答案

您的问题不是库代码,而是.so文件本身. Android设备具有主要的ABI,即处理器支持的指令集. 例如,某些具有64位处理器的设备使用ABI arm64-v8a.

Your problem is not with the library code, but with the .so files themselves. Android devices have a primary ABI, the instruction set supported by the processor. For example, some devices with 64-bit processors use the ABI arm64-v8a.

但是,许多库和应用程序尚不支持64位处理器.因此,通常情况下,较新的处理器还支持辅助ABI,这是较常见的辅助ABI.例如,arm64-v8a处理器通常也支持armeabi-v7a.

However, a lot of libraries and apps don't support 64-bit processors yet. So usually, the newer processors also support a secondary ABI, which is a more common one. arm64-v8a processors usually support armeabi-v7a too, for example.

应用程序启动时,它将开始在目录中查找本机库.首先,它检入主ABI目录,在此示例中为arm64-v8a.如果.so文件不存在,它将检入辅助ABI目录(armeabi-v7a).如果仍然找不到,您将得到您所描述的错误.

When the app starts, it starts looking for the native libraries in the directories. First it checks in the primary ABI directory, arm64-v8a in this example. If the .so files are not there, it checks in the secondary ABI directory (armeabi-v7a). If still not found, you will get the error you described.

就您而言,如您所说,您拥有文件,所以这不是问题.

In your case, you have the files, as you said, so that's not the problem.

此选择的一个大问题是,如果目录存在,它始终坚持主ABI.如果并非所有库都为所有ABI提供所有.so文件,则可能导致崩溃. 此处进行了描述.

One big problem with this selection is, that it always sticks to the primary ABI, if the directory exists. This can lead to crashes if not all libraries supply all .so files for all ABIs. This is described here.

这里是一个示例:您的应用程序中包含2个库: 1. VideoPlayerLibrary,其中包含所有ABI的.so文件 2. GifLibrary,仅具有armeabiarmeabi-v7a的.so文件.

Here's an example: you include 2 libraries in your app: 1. VideoPlayerLibrary, which has .so files for all ABIs 2. GifLibrary, which has .so files only for armeabi and armeabi-v7a.

现在,如果您在arm64-v8a设备上启动该应用程序,它将继续使用其主要ABI,因为它已在其中找到文件(VideoPlayerLibrary的.so文件).但是目前,您想播放gif文件,它将尝试从arm64-v8a目录中加载.so文件,但在该目录中找不到它们,并且会像在您的帖子中一样崩溃,并出现链接错误.

Now if you start the app on an arm64-v8a device, it will stick to it's primary ABI, because it has found files there (the .so files of VideoPlayerLibrary). But at the moment you want to play gifs, it will try to load the .so files from the arm64-v8a directory, but it will not find them there and it will crash as in your post with a link error.

那你该怎么办?

您有2个选择:

  1. 如果它是您自己的库,其中缺少.so文件,请针对所有ABI对其进行编译. 如果不是您自己的,请检查是否存在解决此问题的较新版本.
  2. 从应用程序中排除不完整的ABI.这样,较新的处理器将使用辅助ABI来运行该应用程序.当然,这将导致性能下降,但不会崩溃. 根据我的经验,最重要的ABI是armeabi-v7a,这可能会在所有Android设备上得到支持.
  1. If it is your own library which has the missing .so files, compile it for all ABIs. If it is not your own, check if there's a newer version which has fixed this issue.
  2. Exclude the incomplete ABIs from the app. This way the newer processors will use the secondary ABI for running the app. This will result in worse performance of course, but it will not crash. From my experience, the most important ABI is armeabi-v7a, this should be supported by probably all Android devices.

这篇关于Android本机库(.so)-不满意的链接错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆