安卓系统是如何加载本地库(so文件)的?它有什么规则来从armeabi、armeabi-v7a和arm64-v8a中加载呢?

4
假设我们有以下的jni文件夹结构。
armeabi
    a.so
    b.so
armeabi-v7a
    a.so

在基于ARMv7的设备上,我想加载b.so文件,但在"armeabi-v7a"文件夹下没有b.so文件,那么系统会报告找不到库错误还是使用"armeabi"文件夹下的b.so文件?
更进一步地,系统在armeabiarmeabi-v7aarm64-v8ax86x86_64这些文件夹中查找so文件的顺序是什么?例如,在基于x86_64的设备上,系统首先在x86_64文件夹中查找so文件,但如果找不到,系统会按顺序继续在x86arm64-v8aarmeabi-v7aarmeabi文件夹中查找吗?
2个回答

4

你看过了吗:http://developer.android.com/ndk/guides/abis.html#am

我相信它回答了你的问题:

Google Play商店和包管理器都希望在APK文件内找到符合以下模式的文件路径中的NDK生成库:

/lib/<abi>/lib<name>.so

如果系统在预期位置未找到本机共享库,则无法使用它们。在这种情况下,应用程序本身必须复制库,然后执行dlopen()。
页面下方有这个特定的部分:
自动提取安装时的本机代码
安装应用程序时,包管理器服务会扫描APK,并查找以下形式的任何共享库:
lib/<primary-abi>/lib<name>.so

如果找不到任何内容,并且您已经定义了第二个ABI,则服务将扫描以下形式的共享库:
lib/<secondary-abi>/lib<name>.so

当包管理器找到它正在寻找的库时,它会将它们复制到应用程序的数据目录(data/data//lib/)下的 /lib/lib.so 中。如果根本没有共享对象文件,则应用程序将构建和安装,但在运行时崩溃。
因此,在您的情况下,如果您使用的是 armeabi-v7a 架构,则必须复制 lib/armeabi/libb.so 文件,并使用 dlopen(),因为 PackageManager 并不知道需要在您的应用程序中加载什么,但确实在lib/armeabi-v7a 目录中找到了某些内容。

4
除了Morrison Chang的答案外,您可以考虑完全删除armeabi部分(这样您就不需要两份lib,我想是很大的)。实际上,现代设备中支持armeabi但不支持armeabi-v7a的非常少(运行Android 4.0或更高版本),并且自Android 4.4以来就没有了。有关此问题的一些情况,请参见https://dev59.com/4Yzda4cB1Zd3GeqPiSBo#30924571https://dev59.com/914b5IYBdhLWcg3wlilP#28926267。假设您要求Android 4.0,则这将减小文件大小而不会失去目标用户群的任何重要支持。如果您仍然针对旧版本,则更有理由保留armeabi

除此之外,还有许多便宜的设备(尤其是中国制造的手机,价格低于80美元),运行Android 4.0-4.3,仍然使用旧的ARMv6架构。 - dns
这些设备是否也是完全认证的(即带有Google Play商店),还是只是兼容Android的设备? - mstorsjo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接