Android的大号preVIEW不会在搜索本地库" armeabi"文件夹(的UnsatisfiedLinkError)会在、大号、文件夹、preVIEW

2023-09-05 06:56:08 作者:败给现实

我有2本机库的应用程序。第一个适用于ARMv7的要快得多,所以我有两个版本,对ARMv7和ARMv5中。第二个工程被设置成只有库的ARMv5两个平台是相同的。

I have an app with 2 native libraries. 1st works much faster on ARMv7 so I have version both for ARMv7 and ARMv5. 2nd works the same on both platforms so only ARMv5 library is provided.

我的本地库文件夹,如下所示:

My native library folder looks like this:

/jniLibs/
    |
    +---armeabi/
    |     |
    |     +---libFirstLibrary.so
    |     +---libSecondLibrary.so
    |
    +---armeabi-v7a/
          |
          +---libFirstLibrary.so

该应用程序的工作原理以及在生产的所有设备和Android版本。

The app works well on all devices and Android versions in production.

当我测试它在我的Nexus 5用1- preVIEW(锤头lpv79- preVIEW-ac1d8a8e.tgz),我得到这个错误:

When I tested it on my Nexus 5 with L-Preview (hammerhead-lpv79-preview-ac1d8a8e.tgz), I get this error:

java.lang.UnsatisfiedLinkError: Couldn't load SecondLibrary from loader dalvik.system.PathClassLoader[DexPathList[[zip file "/data/app/com.package-1.apk"],nativeLibraryDirectories=[/data/app-lib/com.package-1, /vendor/lib, /system/lib]]]: findLibrary returned null
   at java.lang.Runtime.loadLibrary(Runtime.java:358)
   at java.lang.System.loadLibrary(System.java:610)

现在的问题是,尽管事实上的Nexus 5已 CPU_ABI 设置为 armeabi-V7A CPU_ABI2 设置为 armeabi ,L preVIEW仅使用 CPU_ABI 价值只有在armeabi-V7A的文件夹和崩溃查找SecondLibrary,因为它是不存在。

The problem is that despite the fact Nexus 5 has CPU_ABI set to armeabi-v7a and CPU_ABI2 set to armeabi, L-Preview uses just CPU_ABI value and looks for "SecondLibrary" only in "armeabi-v7a" folder and crashes as it is not there.

当我复制.so文件也以armeabi-V7A的文件夹,一切都很好,但APK为3.5 MB更大,我真的不喜欢。

When I copy the .so file also to "armeabi-v7a" folder, everything is fine but the APK is 3.5 MB bigger which I don't really like.

这是Android的L- preVIEW只是一个错误或一些新功能?

Is it just a bug of Android L-Preview or some "new feature"?

推荐答案

据我所知,这一直是预期的行为,我很不解,为什么这个之前已经为你工作。

As far as I know, this has always been the intended behaviour, and I'm puzzled why this has worked for you before.

链接器无法浏览每个LoadLibrary调用完整的APK文件 - 相反,正确的本地库在安装APK时提取。只有一个单一架构目录使用,因此,如果它发现的lib / armeabi-V7A它甚至不会找LIB / armeabi。

The linker doesn't browse the full APK file on each loadLibrary call - instead, the right native libraries are extracted when the APK is installed. Only one single architecture directory is used, thus if it found lib/armeabi-v7a it won't even look for lib/armeabi.

有一些较旧的Andr​​oid版本的一个已知的问题(4.0.3及更早版本),其中armeabi可以被意外代替armeabi-V7A不过,不知道这是什么使得这似乎为你工作。

There is a known issue on some older versions of android (4.0.3 and earlier) where the armeabi can be accidentally used instead of armeabi-v7a though, not sure if that's what makes this seem to work for you.

请参阅例如的https://android.googlesource.com/platform/ndk/+/532389e89c/docs/text/CPU-ARCH-ABIS.text这个正式的解释(一节三,ABI管理在Android平台上,尤其是第III.3和注,第III.1年底)。

See e.g. https://android.googlesource.com/platform/ndk/+/532389e89c/docs/text/CPU-ARCH-ABIS.text for an official explanation of this (section "III. ABI Management on the Android platform", in particular subsection III.3 and the note at the end of subsection III.1).

编辑:它实际上看来,包管理器可以从二级ABI目录即使主ABI目录中存在,在Android版本多达奇巧安装一些文件。 http://albin.abo.fi/~mstorsjo/hellojni-test-abis .ZIP 的源动力,我的测试为例, HTTP:/ /albin.abo.fi/~mstorsjo/hellojni-test-abis.apk 是它的二进制文件。这个例子创建四个机库, libgello-jni.so libhello-jni.so libhello-jni2.so libtello-jni.so 。这些文件是专门为所有的ABI,但在 armeabi-V7A ,我已经删除了所有的文件,除了 libhello-jni.so - 文件列表(针对ARM架构的目录),因此看起来是这样的:

It actually seems that the package manager could install some files from the secondary ABI directory even though the primary ABI directory existed, on android versions up to kitkat. http://albin.abo.fi/~mstorsjo/hellojni-test-abis.zip is the source for my test example, and http://albin.abo.fi/~mstorsjo/hellojni-test-abis.apk is a binary of it. This example creates four native libraries, libgello-jni.so, libhello-jni.so, libhello-jni2.so and libtello-jni.so. These files are built for all ABIs, but in armeabi-v7a, I've removed all files except libhello-jni.so - the file listing (for the ARM architecture directories) thus looks like this:

lib/armeabi/libgello-jni.so
lib/armeabi/libhello-jni.so
lib/armeabi/libhello-jni2.so
lib/armeabi/libtello-jni.so
lib/armeabi-v7a/libhello-jni.so

在上一个奇巧 armeabi-V7A 装置,这种安装 libhello-jni.so 从 armeabi-V7A 目录, libhello-jni2.so libgello-jni.so armeabi 目录 - 但 libtello-jni.so 未安装在所有。什么是安装文件似乎取决于APK中的名称和顺序。所以,这取决于你的文件名,则可能是以前有运气,这工作过 - 即使文件明确地说,这是不应该的工作。在Android-L preVIEW这个矛盾似乎已经得到纠正。

On installation on a kitkat armeabi-v7a device, this installs libhello-jni.so from the armeabi-v7a directory, and libhello-jni2.so and libgello-jni.so from the armeabi directory - but libtello-jni.so is not installed at all. What files are installed seem to depend on the names and order within the APK. So depending on your file names, you might have had luck before and this have worked - even if the documentation explicitly says it isn't supposed to work. In the android-L preview this inconsistency seems to have been corrected.