Android L Preview不搜索"armeabi"文件夹中的本机库(UnsatisfiedLinkError)

xsv*_*eda 10 android android-ndk android-5.0-lollipop

我有一个带有2个本地库的应用程序.第一个在ARMv7上工作得更快,所以我有ARMv7和ARMv5的版本.第二个在两个平台上的工作方式相同,因此只提供了ARMv5库.

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

/jniLibs/
    |
    +---armeabi/
    |     |
    |     +---libFirstLibrary.so
    |     +---libSecondLibrary.so
    |
    +---armeabi-v7a/
          |
          +---libFirstLibrary.so
Run Code Online (Sandbox Code Playgroud)

该应用程序适用于生产中的所有设备和Android版本.

当我在Nexus 5上用L-Preview(hammerhead-lpv79-preview-ac1d8a8e.tgz)测试它时,我收到此错误:

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)
Run Code Online (Sandbox Code Playgroud)

问题在于,尽管Nexus 5已CPU_ABI设置armeabi-v7aCPU_ABI2设置为armeabi,但L-Preview仅使用CPU_ABI值并仅在"armeabi-v7a"文件夹中查找"SecondLibrary"并且因为它不存在而崩溃.

当我将.so文件复制到"armeabi-v7a"文件夹时,一切都很好,但APK大3.5 MB,我真的不喜欢.

这只是Android L-Preview或某些"新功能"的错误吗?

mst*_*sjo 5

据我所知,这一直是预期的行为,我很困惑为什么这对你有用.

链接器不会在每个loadLibrary调用上浏览完整的APK文件 - 而是在安装APK时提取正确的本机库.只使用一个体系结构目录,因此如果找到lib/armeabi-v7a,它甚至不会查找lib/armeabi.

有一些较旧的Android版本的已知问题(4.0.3及更早版本),其中armeabi可能会被意外用来代替armeabi-V7A不过,不知道这是什么使得这似乎为你工作.

例如参见https://android.googlesource.com/platform/ndk/+/532389e89c/docs/text/CPU-ARCH-ABIS.text本(节"三,ABI管理在Android平台上"的官方解释,特别是第III.3小节和第III.1小节末尾的注释.

编辑:它实际上似乎包管理器可以从辅助ABI目录安装一些文件,即使主要的ABI目录存在,在Android版本到kitkat.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.solibtello-jni.so.这些文件是为所有ABI构建的,但在armeabi-v7a,我删除了所有文件,除了libhello-jni.so- 文件列表(对于ARM体系结构目录),因此看起来像这样:

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
Run Code Online (Sandbox Code Playgroud)

在安装奇巧的armeabi-v7a设备,这将安装libhello-jni.soarmeabi-v7a目录,libhello-jni2.solibgello-jni.soarmeabi目录-但libtello-jni.so没有安装在所有.安装的文件似乎取决于APK中的名称和顺序.因此,根据您的文件名,您可能之前有过运气并且这已经奏效 - 即使文档明确表示它不应该起作用.在android-L预览中,这种不一致似乎已得到纠正.