#|Android(So库适配简单总结)

前言
日常开发我们经常会使用到第三库,涉及到底层的语音,视频等都需要添加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
QQ 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上

当然这会损失一些性能。见下图,你就明白了:
#|Android(So库适配简单总结)
文章图片

适配方案
综合上面市场占有及大厂适配方案来看,我们只需要适配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
参考
【#|Android(So库适配简单总结)】https://mp.weixin.qq.com/s/jnZpgaRFQT5ULk9tHWMAGg

    推荐阅读