故事背景

今天公司项目打完包,突然发现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

Android ndk.abiFilters armeabi-v7a、arm64-v8a、arneabi、x86、x86-64 解析相关推荐

  1. ReactNative进阶(三十八):Android ndk abiFilters 详解

    一.前言 二.ABI 是什么 三.为何设置 ndk 的 abiFilters 四.如何配置 gardle 五.ABI支持详解 六.支持建议 七.拓展阅读 一.前言 Android 系统本质是一个经过改 ...

  2. Android ndk abiFilters 无效 解决方案

    1.问题产生原因 项目引用远程gradle配置,该配置已经默认数种cpu架构类型,但是我在当前项目由于某种原因只想要其中一种架构,怎么处理? 原配置 ndk {abiFilters 'armeabi- ...

  3. android配置so支持armeabi,安卓项目中so库选择(ndk abiFilters设置,armeabi,armeabi-v7a,arm64-v8a)...

    背景 Android 系统本质是一个通过改造的 Linux 系统,so库是Linux系统上使用的共享库(相似windows上的dll).最先,Android 系统只支持 ARMv5 的 CPU 构架, ...

  4. 安卓项目中so库选择(ndk abiFilters设置,armeabi,armeabi-v7a,arm64-v8a)

    背景 Android 系统本质是一个经过改造的 Linux 系统,so库是Linux系统上使用的共享库(类似windows上的dll).最早,Android 系统只支持 ARMv5 的 CPU 构架, ...

  5. android ndk之opencv+MediaCodec硬编解码来处理视频动态时间水印

    android ndk之opencv+MediaCodec硬编解码来处理视频水印学习笔记 android视频处理学习笔记.以前android增加时间水印的需求,希望多了解视频编解码,直播,特效这一块, ...

  6. 【错误记录】p7zip 交叉编译 Android 版本 NDK 报错 ( Application.mk | APP_ABI := armeabi-v7a arm64-v8a x86 x86_64 )

    文章目录 一.报错信息 二.解决方案 一.报错信息 下载 7zip 源码 , 下载页面 https://sourceforge.net/projects/p7zip/files/ , 解压源码 , 进 ...

  7. android ndk开发中初始化char数组报错问题

    Android Studio报错: error: constant expression evaluates to -14 which cannot be narrowed to type 'char ...

  8. Android、Flutter为不同的CPU架构包打包APK(v7a、v8a、x86)

    默认情况下,Android和Flutter打包出来的Apk都是包含了所有架构的,这样打出来的apk体积相对于单架构的apk有点大. 这时,我们就需要分别打出不同的架构包. 架构 一般来说,x86代表3 ...

  9. android so abi适配,Android NDK学习(六): so文件兼容之abiFilters的使用

    最近项目中遇到了要使用JavaCV的情况,涉及到了abi兼容的选择.因为如果全部都适配的话,包很大,这样兼容那些用户数极少的cpu就很不划算,所以我只适配了armeabi-v7a这一个.但是今天在x6 ...

最新文章

  1. Opencv轻松入门:OpenCV入门难?资料少?看完这篇文章就稳了
  2. FPGA视频加速的未来
  3. java adapter 模式_Java设计模式之适配器模式(Adapter模式)介绍
  4. leetcode —— 面试题 04.03. 特定深度节点链表
  5. ojdbc14_g.jar与ojdbc14.jar区别
  6. MySQL 连接报错:mysql access denied for user@ip
  7. 结对-结对编项目作业名称-设计文档
  8. php开源框架和平台(XAMPP、Wamp5和AppServ)简述
  9. Add NIC to Openfiler 2.3
  10. 腾讯云TCA运维工程师认证题库及例题示范
  11. 技术狂潮下的生理性健忘:科技产品如何影响我们的大脑?
  12. ap接口 php_php中api接口什么用
  13. 2019软件测试学习教程(学习路线+课程大纲+视频教程+学习工具)
  14. 如何利用 onlyoffice 实现文档格式转换
  15. 78 岁华科教授逐梦 40 载,国产数据库达梦冲刺 IPO
  16. 基于fpga的FlexRay总线设计
  17. CSharp代码示例每日一讲: 在GDI+中使用画笔和画刷
  18. 填数字游戏ABCD*E=DCBA
  19. 转 做个男人,做个成熟的男人,做个有城府的男人
  20. 数据库的“读写分离”

热门文章

  1. tomcat启动时错误:Failed to start component [StandardEngine[Catalina].StandardHost[localhost].错误
  2. 【那些对传智播客的攻击】第八篇 zuoyi 归来
  3. DOM解析Xml文件,以及新建asserts文件目录
  4. ImportNew Spring Boot教程系列
  5. 关于Flutter的安装入门教程
  6. java mirai-2.15 qq机器人扫码登录或springboot项目进行扫码登录
  7. 正交实验设计插值方法C语言,正交试验设计及C语言实现.doc
  8. 微信小程序这么受欢迎,有什么特点和作用?
  9. 为 TradingView 添加电话报警(纯文本格式)
  10. 安卓 TV 网络判断(含PPPOE) 封装