Androidarm64-v8a、armeabi-v7a、armeabi、x86详解
最近在⽤flutter打包的时候,遇到了包打不出来的情况,后⾯查了半天原因,发现是没有配置arm导致的,配了之后就打出来了,乘着这个契机,重头来学习了⼀下abi
android最新版开始之前
开始之前先需要知道lib、libs等知识
⼀. lib和libs
放在lib中的是被reference的,放在libs中的是被include的。
放在libs中的⽂件会⾃动被编辑器所include。所以不要把API放到libs⾥去。
lib的内容是不会被打包到APK中,libs中的内容是会被打包进APK中
⼆. .so库
NDK编译出来的动态链接库。
⼀些重要的加密算法或者核⼼协议⼀般都⽤c写然后给java调⽤。这样可以避免反编译后查看到应⽤的源码。
三. .so库该如何存放
放置 .so ⽂件的正确姿势其实就两句话:
· 为了减⼩ apk 体积,只保留 armeabi 和 armeabi-v7a 两个⽂件夹,并保证这两个⽂件夹中 .so 数量⼀致
· 对只提供 armeabi 版本的第三⽅ .so,原样复制⼀份到 armeabi-v7a ⽂件夹
存放so的规则:
你应该尽可能的提供专为每个ABI优化过的.so⽂件,但要么全部⽀持,要么都不⽀持:你不应该混合着使⽤。你应该为每个ABI⽬录提供对应的.so⽂件。
关于存放的问题,可以看看
四. libs下armeabi等的作⽤是什么
存放.so库,主要针对不同的设备兼容,也可以说是专门针对不同Android⼿机下CPU架构的兼容。
下⾯就来扯⼀下安卓cpu
Android 设备的CPU类型(通常称为”ABIs”)
架构介绍
早期的Android系统⼏乎只⽀持ARMv5的CPU架构,后⾯发展到⽀持七种不同的CPU架构:ARMv5,ARMv7 (从2010年起),x86 (从2011年起),MIPS (从2012年起),ARMv8,MIPS64和x86_64 (从2014年起),每⼀种都关联着⼀个相应的ABI。
应⽤程序⼆进制接⼝(Application Binary Interface)定义了⼆进制⽂件(尤其是.so⽂件)如何运⾏在相应的系统平台上,从使⽤的指令集,内存对齐到可⽤的系统函数库。在Android 系统上,每⼀个CPU架构对应⼀个ABI:armeabi,armeabi-v7a,x86,mips,arm64-v8a,mips64,x86_64。
但是最新的⾕歌官⽅⽂档已经把mips和armv5移除了,如图所⽰:
各版本分析如下:
· mips / mips64: 极少⽤于⼿机可以忽略(⾕歌最新的⽂档已经不⽀持了)
· x86 / x86_64: x86 架构的⼿机都会包含由 Intel 提供的称为 Houdini 的指令集动态转码⼯具,实现 对 arm .so 的兼容,再考虑 x86 1% 以下的市场占有率,x86 相关的两个 .so 也是可以忽略的
· armeabi: ARM v5 这是相当⽼旧的⼀个版本,缺少对浮点数计算的硬件⽀持,在需要⼤量计算时有性能瓶颈
· armeabi-v7a: ARM v7
· arm64-v8a: 64位⽀持,⽬前主流的版本,虽然⽹上很多博客都说v7是主流版本,但是我亲⾃试验了很多⼿机,都是arm64-v8a的架构,测试机型包括⼩⽶5-⼩⽶9,华为P30,华为mate10,魅蓝2等均是v8架构
查询⼿机cpu命令⾏:
adb shell getprop ro.product.cpu.abi
⽆图⽆真相:
只有⼀款不知名的oppo⼿机,android系统4.3,⽤的是v7的架构
ABI是如何⼯作的
设备的主要 ABI,与系统映像本⾝使⽤的机器代码对应。
(可选)与系统映像也⽀持的其他 ABI 对应的辅助 ABI。
此机制确保系统在安装时从软件包提取最佳机器代码。
为实现最佳性能,应直接针对主要 ABI 进⾏编译。例如,基于 ARMv5TE 的典型设备只会定义主 ABI:armeabi。相反,基于 ARMv7 的典型设备将主 ABI 定义为 armeabi-v7a,并将辅助 ABI 定义为 armeabi,因为它可以运⾏为每个 ABI ⽣成的应⽤原⽣⼆进制⽂件。
64 位设备也⽀持其 32 位变体。以 arm64-v8a 设备为例,该设备也可以运⾏ armeabi 和 armeabi-v7a 代码。但请注意,如果应⽤以arm64-v8a 为⽬标,⽽⾮依赖于运⾏ armeabi-v7a 版应⽤的设备,则应⽤在 64 位设备上的性能要好得多。
许多基于 x86 的设备也可运⾏ armeabi-v7a 和 armeabi NDK ⼆进制⽂件。对于这些设备,主 ABI 将是 x86,辅助 ABI 是 armeabi-
v7a。
总的来说,就是⼀个Android设备可以⽀持多种ABI,设备主ABI和辅助ABI,以arm64-v8a为主ABI的设备,辅助ABI为armeabi-v7a和armeabi,以armeabi-v7a为主ABI的设备,辅助ABI为armeabi。
另外,x86 架构的⼿机都会包含由 Intel 提供的称为 Houdini 的指令集动态转码⼯具,实现对 arm .so 的兼容,也就是说有适配armeabi 平台的APP是可以跑在x86⼿机上的。
ABI具体适配流程
对于⼀个cpu是arm64-v8a架构的⼿机,它运⾏app时,进⼊jnilibs去读取库⽂件时,先看有没有arm64-v8a⽂件夹,如果没有该⽂件夹,去armeabi-v7a⽂件夹,如果没有,再去armeabi⽂件夹,如果连这个⽂件夹也没有,就抛出异常;
如果有arm64-v8a⽂件夹,那么就去特定名称的.so⽂件,注意:如果没有到想要的.so⽂件,不会再往下(armeabi-v7a⽂件夹)了,⽽是直接抛出异常。
我们项⽬中该如何适配呢
Q1: 只适配了armeabi-v7a,那如果APP装在其他架构的⼿机上,如arm64-v8a上,会蹦吗?
A: 不会,但是反过来会。
因为armeabi-v7a和arm64-v8a会向下兼容:
只适配armeabi的APP可以跑在armeabi,x86,x86_64,armeabi-v7a,arm64-v8上
只适配armeabi-v7a可以运⾏在armeabi-v7a和arm64-v8a
只适配arm64-v8a 可以运⾏在arm64-v8a上
那我们该如何适配呢?给出如下⼏个⽅案:
⽅案⼀:只适配armeabi
优点:基本上适配了全部CPU架构(除了淘汰的mips和mips_64)
缺点:性能低,相当于在绝⼤多数⼿机上都是需要辅助ABI或动态转码来兼容
⽅案⼆:只适配 armeabi-v7a
同理⽅案⼀,只是⼜筛掉了⼀部分⽼旧设备,在性能和兼容⼆者中⽐较平衡
⽅案三: 只适配 arm64-v8
优点: 性能最佳
缺点: 只能运⾏在arm64-v8上,要放弃部分⽼旧设备⽤户
这三种⽅案都是可以的,现在的⼤⼚APP适配中,这三种都有,⼤部分是前2种⽅案。具体选哪⼀种就看⾃⼰的考量了,以性能换兼容就arm64-v8,以兼容换性能armeabi,⼆者稍微平衡⼀点的就armeabi-v7a。
对于64位⼿机跟64位处理器
ARM64位处理器和电脑的64位处理器是两个截然不容的概念,他并不是64位就能原⽣向下兼容32位程序,⽽是通过64位处理器中集成的32位架构来运⾏32位程序。说得通俗点,它不是以64位形态来运⾏32位程序,却是以32位的形态运⾏32位程序的。
由于⽬前新出的64位处理器包含两个架构,⽽且制程技术没有提升(28nm),同时在⼿机与平板上,芯⽚⾯积有着严格的限定,不能过分增加,这导致64位ARM处理器平均分配到每个架构的晶体管数量锐减,也就是说从64位处理器中的32位架构⽅⾯,对于同规格的32位处理器⽽⾔,不但没有提⾼,性能反⽽是⼀定规模下降的。但处理器⼚家⼜必须给消费者⼀个交代,以更好的推⼴64位,所以⼚家就必须在其他⽅⾯提升性能,以弥补CPU的晶体管数量减少带来的损失。⽐如:更换性能更强的GPU、提升内存带宽、多核⼼虚拟单颗核⼼提升单核性能、联合跑分软件商修改跑分权重(提升GPU分数,降低CPU分数的权重)等等。这样,扬长避短,最终到达消费者⼿⾥,⽤跑分软件⼀跑,确实有提升,⽤户开⼼,⼚家腰包也⿎了。
综上所述,ARM64位处理器从严格意义来说,叫它ARM32+64更加贴切,他相对于ARM32位处理器,有倒退的地⽅,也有进步的余地,但正因为倒退激起了ARM进取的决⼼,让它⼤⼑阔斧的向前变⾰,不得不说也算⼀种进步。但ARM64在的⼿机上真的有⽤吗?我只能说,⽬前确实没啥⽤,但今后或许有。(其他地⽅搜罗的) 综上所述,ARM64位处理器从严格意义来说,叫它ARM32+64更加贴切,他相对于ARM32位处理器,有倒退的地⽅,也有进步的余地,但正因为倒退激起了ARM进取的决⼼,让它⼤⼑阔斧的向前变⾰,不得不说也算⼀种进步。但ARM64在的⼿机上真的有⽤吗?我只能说,⽬前确实没啥⽤,但今后或许有。(其他地⽅搜罗的)
真正的64位⼿机并不⽌单纯停留在处理器上,如果只因为它的处理器是64位,就称其为64位⼿机的话,
我们可以毫不犹疑的说这可能是虚假宣传,好在联想很聪明,在发布A678t和A805e宣传的时候,只说64位处理器⼿机。
“64位处理器⼿机”与“64位⼿机”是两种天壤之别的概念:只要是处理器包含64架构位的,就可以称“64位处理器⼿机”,这种⼿机也许还运⾏不了64位程序,只是⽤来抢占市场,和32位⼿机⽐起来优势并不明显。
“64位⼿机”就不同了:它包含着64位处理器、64位标准系统、64位安卓虚拟机、以及64位程序,这才是真正意义上的64位⼿机!
⾕歌官⽅曾说,安卓很早前就⽀持64位了,这话不假,从Android4.0到Android4.4,安卓系统都⽀持64位的硬件,但是这仅仅表⽰底层驱动⽀持64位,能运⾏在64位的硬件之上,仅此⽽已。然⽽,上层运⾏软件的,⽆论是Dalvik的虚拟机,还是ART虚拟机都是32位的。也就是说,只要你的⼿机系统是Android4.0—4.4,即便你的处理器是64位,也只能在32位虚拟机下运⾏32位程序,就算真的64位程序摆在你眼前,也⽆法安装。。
但是⾕歌官⽅今年年初就已经发布强制需要64位架构:
早在今年(2019)⼀⽉份,Google 就发布通知,在今年 8 ⽉ 1 ⽇开始,上架的 App,除了提供 32 位的
版本之外,还需要提供 64 位的版本。
因此,项⽬之前强制只使⽤armeabi⼀种架构的⽅式已经不⾏了。
那这⾥说的 64 位版本⽀持,到底是什么?
如果你的应⽤,完全是使⽤ Java 或者 Kotlin 编写代码,不包含任何原⽣(Native)的⽀持,那么就表⽰这个应⽤已经⽀持 64 位。
但是应⽤内使⽤了任何原⽣(Native)的⽀持(so 库),就需要针对这些 so ⽂件,针对不同的 CPU 架构提供不同的版本的 so ⽀持。
需要注意的是,有些时候,在我们⾃⾝的代码中,确实没有⽤到原⽣的⽀持,但是在 App 中使⽤的⼀些第三⽅库中却包含了。
此时最稳妥的⽅式,就是针对最终打包⽣成的 APK ⽂件进⾏分析,来判断是否需要提供 64 位架构的⽀持。
打包配置
split分包
这个命令可以按照各种规则去分包,⽐如按照abi,屏幕密度(即ldpi,hdpi等)分包
splits {
abi {
enable true
reset()
include 'x86','armabi'
exclude 'armeabi','armeabi-v7a',"arm64-v8a"
universalApk true
}
}
include就是包括,exclude就是不包括。包括的配置每⼀个项都会⽣成⼀个apk包。
但是这样配置,会⽣成两个包,⼀个只包含x86的so库,⼀个只包含armabi的so库。,显然不符合需求
ndk{abiFilters:}过滤
这个指令可以配置只打包你配置的so库,没有配置的就不打包,很灵活。
第三⽅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 配置,来避免⼀些未知的错误

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。