APK Shrink探索--(一)SO方面

背景与问题

随着客户端接入业务的日益增加和集成功能的日益丰富,客户端APK安装包也随之增大。
过大的安装包会带来的不利影响如下:
1.对外,增加用户下载时的流量消耗,延长应用安装时间,降低用户体验。
2.对内,增加了企业“打包-上线-发布”流程消耗的时间成本,同时也会影响到开发时的单次构建效率。

解决方案

APK瘦身

利用AS对APK包进行分析,结果如图:
这里写图片描述

由图可知,APK大小中占比重较大的主要为lib,resource(res,assets),dex,因此APK瘦身主要针对这三者进行处理。本篇就先从lib入手。

1. lib目录优化分析
由图可知,当前lib目录下包含armeabi、armeabi-v7a,x86三个子目录,它们分别代表三种ABI,并包含支持该ABI的so库文件。
查看三个子目录,发现三个ABI目录下包含同名so文件,armeabi-v7a额外包含一些so文件,那么,这些同名so文件是否可以只保留一份?如何选择?
同时,对支付宝、微信等大厂的APK进行解包可以看到,可以看到这些大厂的APK中,lib目录下是只保留一份armeabi的。

2.Android SO与ABI
ABI简介

  • Android设备可支持ARMv5,ARMv7,X86,ARMv8,X86_64等多种CPU架构
  • 每种CPU架构都定义一种 ABI(Application Binary Interface,应用二进制接口),ABI定义了其所对应的CPU架构能够执行的二进制文件(如.so文件)的格式规范。
CPUARMv5ARMv7x86MIPSARMv8MIPS64x86_64
ABIarmeabiarmeabi-v7ax86mipsarmeabi-v8amips64x86-64

SO简介

  • so(shared object,共享库)是机器可以直接运行的二进制代码,是Android上的动态链接库,类似于Windows上的dll.
  • 每一个Android应用所支持的ABI是由其APK提供的.so文件决定的. 例如:
    lib
    |
    ├── armeabi
    │ └── libmath.so
    ├── armeabi-v7a
    │ └── libmath.so
    ├── mips
    │ └── libmath.so
    └── x86
    └── libmath.so

    说明该应用所支持的ABI为armeabi, armeabi-v7a, mips, 和x86。

Android系统的ABI支持

  • Android可以在运行期间确定当前系统所支持的ABI,这是由系统编译时的具体参数指定的:
    primary ABI(主ABI):对应当前系统中使用的机器码类型
    secondary ABI(副ABI):表示当前系统支持的其他ABI类型
    这里写图片描述
    上图可知,该设备的primary ABI是arm64-v8a

  • 许多手机支持不止一个ABI,比如,一个基于ARMv7的设备会将armeabi-v7a定义为primary ABI,armeabi作为secondary ABI,意味着这台机器同时支持armeabi-v7a和armeabi

  • X86手机存在一个Binary Translator(二进制转换中间层) houdini. 它会在运行期间动态的读取arm指令并将之转换为x86指令去执行。
  • 许多基于x86的设备也可以运行armeabi-v7a和armeabi的so,对于这些机器,primary ABI是x86,secondary ABI则是armeabi-v7a.

APK安装时对so的选择过程

  • 应用安装时,Package Manager会扫描整个apk文件,寻找符合下面文件路径格式的动态链接库:
    lib//lib.so

  • 如果在apk内并没有找到适合当前机器primary-abi的so,Package Manager会尝试寻找适合secondary-abi的so文件: lib//lib.so

  • 如果找到了合适的so文件,包管理器会将该ABI文件夹下所有so库全部拷贝至应用的data目录下: data/data//lib/

  • 运行时找不到so,则会报Java.lang.UnsatisfiedLinkError问题
  • 安装APK时PMS只负责拷so,至于这个so是何种ABI是不感知的。
  • 支持armeabi-v7a的设备同样支持armeabi的so文件,反之不行。

3.SO精简处理方案
通过对使用用户中各ABI的分布对比,armeabi和x86占比极小,所以选择不考虑保留armeabi和x86,只保留armeabi-v7a。
通过修改gradle文件,在buildType模块增加对打包时ABI的指定,如下:

ndk {
    abiFilters "armeabi"        
    }

经过so的精简,APK大小减小了7M+,下一步会继续研究下对资源文件和dex文件的精简。

在 CSS 中,`flex-shrink` 属性是个用于设置弹性盒子元素缩放比例的属性,它允许我们在容器受到约束尺寸调整子元素的大小。当个弹性盒子容器内的空间不足以容纳所有的子元素,`flex-shrink` 属性较高的元素会自动减少其尺寸,以便容器内的所有元素都能适应容器的空间。 `flex-shrink` 属性的值通常是个正整数,数值越小表示该元素收缩的程度越大,在空间不足的情况下倾向于缩小更多。默认值是 1,意味着元素不会主动缩小(除非有其他元素的 `flex-shrink` 值更大)。 ### 使用示例: 假设我们有个包含三个 `<div>` 元素的弹性盒子容器,并希望当容器尺寸受限,元素能够适当地缩小: ```css .container { display: flex; } .box { width: 50%; background-color: lightblue; padding: 20px; margin: 10px; } /* 定义每个 div 的 flex-shrink */ .box:first-child { flex-shrink: 1; } .box:nth-child(2) { flex-shrink: 2; } .box:last-child { flex-shrink: 3; } ``` 在这个例子中: -个元素 (`<div>` 元素) 的 `flex-shrink: 1;` 表示它与其他元素有相同的收缩倾向。 - 第二个元素的 `flex-shrink: 2;` 表示它比其他元素更容易收缩。 - 最后个元素的 `flex-shrink: 3;` 表示它是最容易收缩的。 这使得当容器宽度不足以放置所有元素,最易于收缩的元素(在这个例子中是最后个元素)将会最先减少其尺寸,以此来保证容器内元素的布局尽可能地紧凑。 ### 应用场景: - 当我们需要创建自适应布局,特别是响应式网页设计,`flex-shrink` 可以帮助元素在屏幕尺寸变化调整大小,以填充容器。 - 在构建网格系统或其他需要元素按照定规则自动调整大小以适应内容或设备的场景中非常有用。 - 为了优化视觉效果或避免元素间因尺寸差异而显得拥挤或空旷的情况,合理配置 `flex-shrink` 可以提供更好的用户界面体验。 总之,`flex-shrink` 是个强大的工具,可以帮助开发者更好地控制弹性盒子布局下的元素大小,从而达到理想的视图效果并提升用户体验。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值