代码之家  ›  专栏  ›  技术社区  ›  xsveda

Android L Preview不在“armeabi”文件夹中搜索本机库(UnsatisfiedLinkError)

  •  10
  • xsveda  · 技术社区  · 11 年前

    我有一个带有2个本机库的应用程序。1st在ARMv7上运行得更快,所以我有ARMv7和ARMv5的版本。2nd在两个平台上的工作方式相同,因此只提供ARMv5库。

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

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

    该应用程序在所有设备和生产中的Android版本上运行良好。

    当我用L-Preview(锤头-lpv79-Preview-ac1d8a8e.tgz)在Nexus 5上测试它时,我得到了这个错误:

    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”,并因其不存在而崩溃。

    当我将.so文件也复制到“armeabi-v7a”文件夹时,一切都很好,但APK大了3.5 MB,这是我不太喜欢的。

    这只是Android L-Preview的一个bug还是一些“新功能”?

    1 回复  |  直到 11 年前
        1
  •  6
  •   mstorsjo    11 年前

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

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

    在一些较旧版本的android(4.0.3及更早版本)上存在一个已知的问题,即armeabi可能会被意外使用,而不是armeabi-v7a,但不确定这是否使这看起来对您有效。

    参见例如。 https://android.googlesource.com/platform/ndk/+/532389e89c/docs/text/CPU-ARCH-ABIS.text 关于这一点的官方解释(第三节“Android平台上的ABI管理”,特别是第III.3节和第III.1节末尾的注释)。

    编辑:实际上,在kitkat之前的android版本上,包管理器似乎可以从辅助ABI目录安装一些文件,即使主ABI目录已经存在。 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体系结构目录)如下所示:

    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
    

    在kitkat上安装时 亚美尼亚-v7a 设备,这将安装 libhello-jni.so 来自 亚美尼亚-v7a 目录,以及 libhello-uni2.so libgello-jni.so公司 来自 armeabi 目录-但 libtello-jni.so公司 根本没有安装。安装的文件似乎取决于APK中的名称和顺序。因此,根据您的文件名,您可能之前运气不错,而且这已经奏效了——即使文档明确表示它不应该奏效。在android-L预览中,这种不一致性似乎已经得到纠正。