Android ndk.abiFilters armeabi

您所在的位置:网站首页 安卓ndk下载 Android ndk.abiFilters armeabi

Android ndk.abiFilters armeabi

2023-08-01 22:40| 来源: 网络整理| 查看: 265

故事背景

今天公司项目打完包,突然发现apk的size从原来的50多M激增到85M,作为敏感的我,肯定是要查清楚原因的。 如何排查呢,肯定是结果出发,我们解压了最新的apk,对比上个版本的apk,看一下具体增大的文件是哪部分? 在这里插入图片描述 可以清晰地看到,lib文件夹下增加了很多文件。 看了一下这个周期的开发需求,我发现是有一个同学在处理接入一个第三方库的时候,增加了ndk的abiFilter种类,具体代码为:

android { ...... defaultConfig { ...... ndk { abiFilters 'armeabi', 'x86', 'armeabi-v7a', 'x86_64', 'arm64-v8a' } }

那么在此之前我确实对这部分内容没有很透彻的研究,借着此机会好好研究了一下。

so库

NDK编译出来的动态链接库。 一些重要的加密算法或者核心协议一般都用c写然后给java调用。这样可以避免反编译后查看到应用的源码。

放置so文件的正确方式: • 为了减小 apk 体积,只保留 armeabi 和 armeabi-v7a 两个文件夹,并保证这两个文件夹中 .so 数量一致 • 对只提供 armeabi 版本的第三方 .so,原样复制一份到 armeabi-v7a 文件夹 原则:你应该尽可能的提供专为每个ABI优化过的.so文件,但要么全部支持,要么都不支持:你不应该混合着使用。你应该为每个ABI目录提供对应的.so文件。

ABI是啥

ABI是英文Application Binary Interface的缩写,也就是应用二进制接口。

不同Android设备,使用的CPU架构可能不同,因此支持不同的指令集。 CPU 与指令集的每种组合都有其自己的应用二进制界面(或 ABI),ABI非常精确地定义了应用程序的机器代码应如何在运行时与系统交互。您必须为要与您的应用程序一起使用的每种CPU架构指定一个ABI(Application Binary Interface)。

ABI 包含以下信息:

可使用的 CPU 指令集(和扩展指令集)。运行时内存存储和加载的字节顺序。Android 始终是 little-endian。在应用和系统之间传递数据的规范(包括对齐限制),以及系统调用函数时如何使用堆栈和寄存器。可执行二进制文件(例如程序和共享库)的格式,以及它们支持的内容类型。Android 始终使用 ELF。如何重整 C++ 名称。

总而言之,abi就是帮助适配不同的CPU架构的。

ABI现状及原理分析

Android 目前共支持7种CPU架构: mips, mips64, X86, X86–64, arm64-v8a, armeabi, armeabi-v7a 市场占有率上,x86 / x86_64/armeabi/mips / mips6 的架构,基本可以不不考虑了,它们的占有量应很少很少了,arm64-v8a作为最新一代架构,应该是目前的主流,armeabi-v7a只存在少部分老旧手机。

难道我要全部写上?if so,我们的apk size岂不是无比巨大。

根据参考资料:微信适配的是arm64-v8a(部分渠道下载的apk可能适配的是armeabi-v7a,不做过多纠结,有可能采用的是动态下发的方案,具体不详,以前是armeabi),支付宝和手Q适配的是armeabi,淘宝适配的是armeabi-v7a。各个APP适配的平台不太一样,但是他们有一个共同点,那就是它们只指定了一个平台。

看到这里,有的同学就开始问了,上面这些APP只适配了一中CPU架构,比如只适配了armeabi-v7a,那如果APP装在其他架构的手机上,如arm64-v8a上,会crash吗?

实际上,一个Android设备可以支持多种ABI,设备主ABI和辅助ABI,以arm64-v8a为主ABI的设备,辅助ABI为armeabi-v7a和armeabi;以armeabi-v7a为主ABI的设备,辅助ABI为armeabi。 另外,x86 架构的手机都会包含由 Intel 提供的称为 Houdini 的指令集动态转码工具,实现对 arm .so 的兼容,也就是说有适配armeabi平台的APP是可以跑在x86手机上的。

下面以arm64-v8a架构的手机为例: 在这里插入图片描述 特别需要注意的情况是在命中了文件夹,而未命中so文件这种情况:

比如命中了arm64-v8a文件夹,没有找到需要的so文件,就不会再往下(armeabi-v7a文件夹)找了,而是直接抛出异常。如果你的项目用到了第三方依赖,如果只保留一个ABI的时候,建议在Build中加入ndk.abiFilters 例如:第三方aar文件,如果这个sdk对abi的支持比较全,可能会包含armeabi、armeabi-v7a、x86、arm64-v8a、x86_64五种abi,而你应用的其它so只支持armeabi、armeabi-v7a、x86三种,直接引用sdk的aar,会自动编译出支持5种abi的包。但是应用的其它so缺少对其它两种abi的支持,那么如果应用运行于arm64-v8a、x86_64为首选abi的设备上时,就会crash了哦。

因此,我们需要在我们的app中配置 abiFilter 配置,来避免一些未知的错误。

defaultConfig { ndk { abiFilters "armeabi"// 指定ndk需要兼容的ABI(这样其他依赖包里x86,armeabi,arm-v8之类的so会被过滤掉) } } 我们该如何适配?

明确一个基本原则,abi是向下兼容的,即:

只适配armeabi的APP可以跑在armeabi,x86,x86_64,armeabi-v7a,arm64-v8上只适配armeabi-v7a可以运行在armeabi-v7a和arm64-v8a只适配arm64-v8a 可以运行在arm64-v8a上

因此我们有如下适配方案:

只适配armeabi: 优点:基本可以适配所有手机机型,除了淘汰的mips和mips_64 缺点:在大多数手机上都需要利用辅助ABI或者动态转码来兼容,性能较差

只适配 armeabi-v7a 只是又筛掉了一部分老旧设备,在性能和兼容二者中比较平衡

只适配 arm64-v8 优点:性能最佳(微信大哥采用的) 缺点:只能运行在arm64-v8上,要放弃部分老旧设备用户

上述方案只是我们给出的建议,具体还要看实际的需求和考量:以性能换兼容就arm64-v8,以兼容换性能armeabi,二者稍微平衡一点的就armeabi-v7a。

能否做到性能+兼容都要

上述方案多多少少有一些取舍的,有没有完美的方案,既不放弃性能,也能完全兼容。答案是肯定的,Google已经安排上了,通过abi split,分包,为每一个CUP架构打一个apk,该apk 中就只包含一个平台。 google play支持上传多个apk,但是,据我所知,目前国内的应用商店是不支持的。

android { ... splits { // Configures multiple APKs based on ABI. abi { // Enables building multiple APKs per ABI. enable true // By default all ABIs are included, so use reset() and include to specify that we only // want APKs for x86 and x86_64. // Resets the list of ABIs that Gradle should create APKs for to none. reset() // Specifies a list of ABIs that Gradle should create APKs for. include "x86", "x86_64", "arm64-v8a", "armeabi", "armeabi-v7a" // Specifies that we do not want to also generate a universal APK that includes all ABIs. universalApk false } } }

本文大量参考如下文章,如有侵权,请联系本人删除。 参考文章:https://juejin.cn/post/6844904148589084680



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3