}
}
效果如下:
可以看到,只生成了我们指定CPU架构的so文件,包的大小也减少了5.3MB。
Android CPU架构在当前市场的占有率
Android目前支持7种ABIs:mips, mips64, X86, X86–64, arm64-v8a, armeabi, armeabi-v7a
- arm64-v8a: 第8代、64位ARM处理器,目前主流版本。
- armeabi-v7a: 第7代及以上的 ARM 处理器,2011年15月以后的生产的大部分Android设备,现在以arm64-v8a为多。
- armeabi: 第5代、第6代的ARM处理器,早期的手机用的比较多,可以兼容所有ARM设备,速度比较慢。
- x86 / x86_64: 平板、模拟器用得比较多,x86 架构的手机都会包含由 Intel 提供的称为 Houdini 的指令集动态转码工具,实现对 arm .so 的兼容,而且目前 x86市场占有率很低,可能只有1%,所以x86相关的两个so文件是可以忽略的。
- mips / mips64: NDK 以前支持 ARMv5 (armeabi) 以及 32 位和 64 位 MIPS,但 NDK r17 已不再支持,极少用于手机,可以忽略。
目前手机市场上,x86 / x86_64/armeabi/mips / mips6 的架构,基本可以不不考虑了,它们的占有量应很少很少了,arm64-v8a作为最新一代架构,应该是目前的主流,armeabi-v7a只存在少部分老旧手机。
Google Play 从2019年8月开始,就强制APP适配arm64-v8a,以慢慢淘汰32位的armeabi-v7a。
查看手机的CPU ABI
通过 adb 命令查看
- 连接手机到电脑上
- 打开 cmd 命令窗口,输入命令 adb shell
- 然后输入命令 cat /proc/cpuinfo
通过代码获取
Build.CPU_ABI、Build.CPU_ABI2,API level 大于等于21时,使用Build.SUPPORTED_ABIS
如何适配
ABI是如何工作
一般来说,一个Android设备可以支持多种ABI,设备主ABI和辅助ABI,以arm64-v8a为主ABI的设备,辅助ABI为armeabi-v7a和armeabi,以armeabi-v7a为主ABI的设备,辅助ABI为armeabi,也就是说他是向下兼容的,即arm64-v8a>armeabi-v7a>armeabi。
例如:对于一个cpu是arm64-v8a架构的手机,它运行app时,进入jnilibs去读取库文件时,先看有没有arm64-v8a文件夹,如果没有该文件夹,去找armeabi-v7a文件夹,如果没有,再去找armeabi文件夹,如果连这个文件夹也没有,就抛出异常;
如果有arm64-v8a文件夹,那么就去找特定名称的.so文件,注意:如果没有找到想要的.so文件,不会再往下(armeabi-v7a文件夹)找了,而是直接抛出异常。
Exception:Java.lang.UnsatisfiedLinkError: dlopen failed: library “/***.so” not found
特别需要注意的情况是在命中了文件夹,而未命中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-v7a和arm64-v8a会向下兼容:
- 只适配armeabi的APP可以跑在armeabi,x86,x86_64,armewabi-v7a,arm64-v8上
- 只适配armeabi-v7a可以运行在armeabi-v7a和arm64-v8a
- 只适配arm64-v8a 可以运行在arm64-v8a上
ye 那我们该如何适配呢?
一、只适配armeabi
- 优点:基本上适配了全部CPU架构(除了淘汰的mips和mips_64)
- 缺点:性能低,相当于在绝大多数手机上都是需要辅助ABI或动态转码来兼容
二、只适配 armeabi-v7a
能运行在arm64-v8和armeabi-v7a机器上,在性能和兼容二者中比较平衡
三、只适配 arm64-v8
只能运行在arm64-v8上,要放弃部分老旧设备用户,优点就是:性能最佳
这三种方案都是可以的,现在的大厂APP适配中,这三种都有,大部分是前2种方案。 具体选哪一种就看自己的考量了,以性能换兼容就arm64-v8,以兼容换性能armeabi,二者稍微平衡一点的就armeabi-v7a。 最后,根据市场上ABI的占有率情况,我们可以选择第二种方案,性能和兼容二者中比较平衡,一则armeabi类型的手机已经很少了,二则可以兼容armeabi-v7a;若你比较看重性能的也可以选择第一种方案。
abi split分包
abi split,分包就是为每个CPU架构单独打一个APK,为了性能和兼容同时兼得,Google提供了abi split分包的机制:
在gradle 中添加如下配置:
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
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)
最后
写到这里也结束了,在文章最后放上一个小小的福利,以下为小编自己在学习过程中整理出的一个学习思路及方向,从事互联网开发,最主要的是要学好技术,而学习技术是一条慢长而艰苦的道路,不能靠一时激情,也不是熬几天几夜就能学好的,必须养成平时努力学习的习惯,更加需要准确的学习方向达到有效的学习效果。
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!
…(img-koGaCzF5-1713099316665)]
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!