写点什么

APP 终极瘦身方案

用户头像
Android架构
关注
发布于: 1 小时前

可以这样理解 CERT.SF 的作用:


  • 该文件是 MANIFEST.MF 的二次编码后产生的文件。

  • 如果逆向修改了任何文件,则 MANIFEST.MF 文件必定会发生改变,从而和 CERT.SF 不匹配。

  • CERT.SF 二次编码的特点是用于在 APK 安装时校验 MANIFEST.MF 是否被篡改

  • 若根据修改的文件伪造了一份新的 CERT.SF 文件,那么数字签名值必定与 CERT.RSA 中的记录不一样


CERT.RSA:包含了公钥和加密算法等信息,而最重要的信息是“对 CERT.SF 用私钥进行加密之后的值”。


META-INF 文件夹下的文件环环相扣,总结如下:


  • 如果逆向修改了 APK 包中的文件,那么被修改的文件的摘要和 MANIFEST.MF 中的信息则不对应

  • 如果修改了某个文件,则必须修改 MANIFEST.MF 中对应的摘要值,必须保证对应关系

  • 要修改 MANIFEST.MF 的摘要值,会产生新的 MANIFEST.MF,必然和 CERT.SF 中的记录不匹配

  • CERT.SF 中记录了 MANIFEST.MF 整个文件的编码和其所有内容的编码值,逆向时必须修改 CERT.SF

  • 修改了 CERT.SF 后,安装 apk 时 CERT.RSA 文件中的内容和修改后的 CERT.SF 会不匹配,出现安装失败

  • 逆向者只有拿到了开发者的秘钥才能完全创造一个相同的 apk


优化建议:通过分析得出,除了 RSA 没有缩减机会外,其余两个文件都可以通过混淆资源名称的方式进行压缩。

优化 Res 目录

  • 打包时剔除无用资源:shrinkResources true shrinkResources 意思是收缩资源,将它设置为 true,每次打包时就会自动排除无用的资源,不仅作用于图片,还会清理无用的 layout 资源等,但是只有配合开启混淆才能生效。

  • 删除无用的语言:大部分 app 其实不需要支持几十种语言,国内应用,可以只支持中文


defaultConfig {


...


resConfig "zh"


}


这样配置后,打包时会排除私有项目、Android support 库、三方库中的非中文资源文件。


  • 控制 raw 中的资源大小:Raw 和 Assets 可以用来存放资源,但两者有以下差异:


  1. Assets 目录允许下面有多级子目录,而 Raw 不允许存在字目录结构。

  2. Assets 目录不会产生 R 文件,Raw 则相反

  3. 因为 Raw 文件会产生 R 文件的映射,所以可以被 lint 分析,而 Assets 不能

  4. Raw 不支持子目录让其无法成为存放多种类文件的目录


Raw 虽然不会对文件大小有限制,但是存放的音频文件尽量不要使用无损格式,可以考虑同等质量但文件更小的音频格式,如 OGG、wav、mp3 等格式

减少 layout 文件

减少 layout 有两个方法:复用和融合。


复用:把一些页面共用的布局抽出来,这对于 layout 文件的管理还是瘦身都非常有用。


融合:对于不会被复用的 layout 呢?


  • shatter 是一个类似于 Fragment 的解耦库,可以为同一个 layout 中不同区域的 view 进行逻辑解耦,还可以尽可能少的建立 layout 文件。

  • 将没有必要复用的 header 头布局和 ListView/RecycleView 放在同一个 layout 布局中,通过代码完成头部的添加

动态下载图片

贴纸、表情这类的文件是相当大的,对于这类图片资源,强烈建议通过在线的方式获取,虽然有一点的复杂度和出错率,但是投入产出比还是不错的。

分目录放置图片

不同分辨率的图片应该放在不同的目录中,如果放错了,对于 app 运行时的内存大小会有一定的影响。


如果把一个本来应该放在 drawable-xxhdpi 里面的图片放在了 drawable 文件夹中,会出现什么问题呢? 在 xxhdpi 设备上,图片会放大 3 倍,图片内存占用会变为原来的 9 倍。


因为不同分辨率的图片大小有差距,很多认为可以使用一套图片来做,不用多套图,借此达到瘦身的目的。但谷歌建议针对不同分辨率出不同的图片。 比较通用的做法是:


  • 聊天表情就出一套图,放在 hdpi 中(因为此类图片对于清晰度要求不高)

  • 纯色小 icon 用 svg 制作,用矢量图适配所有分辨率

  • 对于背景图等大图,出一套放在 hdpi 或者 xxhdpi 中

  • logo 等权重较大的图片可针对 hdpi、xhdpi、xxhdpi 做多套图

  • 如果某些图在真机中展示异常,就用多套图适配

  • 如果有特殊机型,可针对性的补图

优化图片资源

图片的优化,最重要的是知道选择什么样的图片格式。


  • 如果是纯色的 icon,推荐使用 svg

  • 如果是两种以上颜色的 icon,推荐使用 webp

  • 如果 webp 无法达到效果,则选择用 png

  • 如果图片没有 alpha 通道,则考虑使用 jpg

  • 因为 svg 是通过 xml 描述的,所以可以享受到资源优化和代码压缩,通常可以压缩到 1kb

  • 对于无透明度的大图,可以换为 jpg 格式进行有损压缩


webp 格式从 4.0 开始原生支持,知道 4.2.1 才支持显示含有透明度的 webp,一般 png 转换为 webp,大小可以减少一半


另外,在大型项目中,会引入汗多 support 库以及三方库,如果库中包含一些大图,并且不会用到的话,可以用 1x1 的同名透明图片替代,达到技能编译通过,又能缩小体积的目的。


针对动画,尤其是帧动画,一直是相当占用资源的,现在可以使用 svg 动画或者 Airbnb 公司的 Lottie 动画库实现,如果使用 Lottie 可以直接使用 json 文件描述动画,图片会减少很多。

优化 dex

dex 文件是 class 文件被编译后可供 art 虚拟机理解的文件格式,可以理解为 java 代码包。

利用 lint 分析无用代码

可以借助 Inspect Code,对工程做静态代码检查。Lint 是一个强大的工具,它能做的事情不限于检查无用资源和代码,它能检测丢失的属性、写错的单位、会引起内存溢出的代码等,当然 Lint 虽然强大,但也会带来一些缺点,就是生成的信息量过大,不适合快速定位无用的代码。除此之外,Lint 会提示不要使用枚举方法,如果将枚举变为 int,apk 的大小也会缩小一些,没减少一个 enum,可以减少大约 1 到 4kb 的大小。


![image.png]


《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》
浏览器打开:qq.cn.hn/FTe 免费领取
复制代码


(https://static001.geekbang.org/infoq/1e/1ea2ee8da6688038690837e962fbfbb9.png)

删除 R 文件

Android 中的 R 文件,除了 styleable 类型外,所有的字段都是 int 型变量或者常量,且在运行期间都不会改变。可以在编译时记录 R 中所有字段的名称以及对应值,然后利用 ASM 工具遍历所有 class,将引用 R 字段的地方替换成对应的常量 ThinRPlugin插件可以方便地将 R.xxx 的地方替换为具体值,可以减少一部分 dex 大小。


在最外层的 build.gradle 中加入如下依赖:


classpath 'com.mogujie.gradle:ThinRPlugin:0.0.2'


在内层的 gradle 文件中加入如下代码:


apply plugin: 'thinR'


thinR {


//为了不影响日常开发的编译速度,debug 版本可以不用删除 R


skipThinRDebug = true


}

启用 ProGuard:

ProGuard 是一款优秀的代码优化、混淆工具,适用于 java 和 Android。关于 ProGuard,最需要了解的是它的方法检测机制。它将产出的 class 作为输入,然后寻找代码中所有的调用点,计算出代码中可达的调用关系图,然后移出剩余的部分,将真正用到的方法变量保留下来进行优化,最终输出一个新的 class。



上图简单描述了什么是可达和不可达的代码


buildTypes {


release {


minifyEnabled true


shrinkResources true //压缩资源


proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'


}


}


虽然这种方式成果显著,但也要配合正确的 ProGuard 规则才能起作用。



这张图展示了原始 apk 和混淆后 apk 的大小差异


每次构建时,ProGuard 都会输出下列文件:


  • dump.txt:说明 APK 中所有类文件的内部结构

  • mapping.txt:提供原始与混淆过的类、字段、属性、方法之间的映射关系

  • seeds.txt:列出未进行混淆的类和成员

  • usage.txt:列出从 apk 中移除的类和代码


利用混淆来删除代码的方式是一种保险措施,真正治本的方法是在开发过程中随手删除无用的代码。

用户头像

Android架构

关注

还未添加个人签名 2021.10.31 加入

还未添加个人简介

评论

发布
暂无评论
APP终极瘦身方案