前言
日常开发我们经常会使用到第三库,涉及到底层的语音,视频等都需要添加so库。
而so库的体积一般来说非常的大,不搞清楚随意添加会导致apk体积暴增。
本文只做一个简单的学习总结。强烈建议阅读文章:
为何大厂APP如微信、支付宝等只适配了armeabi-v7a/armeabi?
CPU架构
Android目前支持以下7种ABIs(Application Binary Interface的缩写,即应用二进制接口):
mips, mips64, X86, X86–64, arm64-v8a, armeabi, armeabi-v7a
CPU架构 | 描述 | 市场占有 |
---|---|---|
arm64-v8a | 第8代ARM,64位 | 目前主流版本 |
armeabi-v7a | 第7代ARM,32位 | 一些老旧手机 |
armeabi | 第5代ARM,32位,NDK r17不再支持 | 极少,可忽略 |
x86_64/X86 | intel,64位/32位,可兼容arm的so库 | 1%以下 |
mips64/mips | NDK r17不再支持 | 极少用于手机,可以忽略 |
x86_64/X86:架构的手机都会包含由Intel提供的称为Houdini的指令集动态转码工具实现对arm.so的兼容,再考虑x86 1%以下的市场占有率,x86 相关的两个 .so 也是可以忽略的。
如何选择?
我们来看一下大厂App如何选择so库:
App | cpu |
---|---|
微信 | arm64-v8a |
支付宝 | armeabi |
armeabi | |
手机淘宝 | armeabi-v7a |
值得一提的是,这4大App都只适配了一种Cpu架构。
上面这些APP只适配了一种CPU架构,比如只适配了armeabi-v7a,那如果APP装在其他架构的手机上,如arm64-v8a上,会崩溃吗?
答案是不会的。
因为armeabi-v7a和arm64-v8a会向下兼容:
只适配armeabi的APP可以跑在armeabi,x86,x86_64,armewabi-v7a,arm64-v8上
只适配armeabi-v7a可以运行在armeabi-v7a和arm64-v8a
只适配arm64-v8a 可以运行在arm64-v8a上
当然这会损失一些性能。见下图,你就明白了:
适配方案
综合上面市场占有及大厂适配方案来看,我们只需要适配arm架构即可,即armeabi,armewabi-v7a,arm64-v8
三选一。
1.方案一:只适配armeabi
优点:基本上适配了全部CPU架构(除了淘汰的mips和mips_64)
缺点:性能低,相当于在绝大多数手机上都是需要辅助ABI或动态转码来兼容
2.方案二:只适配armeabi-v7a
同理方案一,只是又筛掉了一部分老旧设备,在性能和兼容二者中比较平衡
3.方案三: 只适配arm64-v8
优点: 性能最佳
缺点:只能运行在arm64-v8上,要放弃部分老旧设备用户
Google Play 从2019年8月开始,就强制APP适配arm64-v8a,以慢慢淘汰32位的armeabi-v7a。
所以全面适配arm64-v8是迟早的事,因此新项目建议提前适配arm64-v8。
如果我们既不想放弃旧设备用户,也要保证性能,就只能牺牲apk的体积为代价:
ndk {
abiFilters "armeabi", "arm64-v8a"
}
使用abiFilters,就能指定app打中包含哪些Cpu架构的so库,不指定的则被忽略。
注意事项
需要注意的是,虽然ABI加载So会向下兼容。但是如果你的App同时存在两种架构如:"armeabi", "arm64-v8a"。
那么不同Cpu架构的手机便只会加载对应的SO库不再向下兼容。
比如a.so存在armeabi中,不存在arm64-v8a中。那么arm64-v8a手机加载a.so库时,便会崩溃。
因此需要每个So库同时添加到每种架构中。
armeabi-v7a与armeabi都适用于32位CPU架构,因此理论上他们的So库时完全通用的,即如果你的项目只适配了armeabi架构,
但是第三方框架只提供了armeabi-v7a的So库,也是可以直接用的。但是arm64-v8a是64位的,所以无法通用。
一些没人维护的第三方库,年久失修,可能没有arm64-v8a架构的So库。
我们这个时候就要考虑是否适配arm64-v8a架构,或者使用其他库代替。
番外篇--性能+兼容能否兼得?
除了适配所有全部CPU架构外,就特么不能性能和兼容同时兼得吗?其实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
}
}
}
就能为每个CPU架构单独打一个APK,该apk中就只包含一个架构。
这样,又能保证性能,又能不额外增加APK的大小,同时又又很完美的兼容,因为可以为所有架构都单独打一个包,一举多得。
Google Play 支持上传多个不同平台的APK,这样,就能根据不同的CPU架构,下载不同的包。
但是,很遗憾,国内的应用商店目前还不支持!因此看看就好 23333
参考
https://mp.weixin.qq.com/s/jnZpgaRFQT5ULk9tHWMAGg