随着公司项目在不断的改版迭代中,项目中代码和各种依赖及图片资源在不断的累加,apk包已经到了40+M了。包大了,这样对于用户下载体验就不好(浪费流量和下载时长),只能好好搞一下。优化过后包大小为29M左右。下面就阐述我的apk瘦身心得了。

我做瘦身优化的时主要的几个步骤:
1:对apk进行结构分析
2:分析完后的实际操作
其中第二步实际操作又分为
1:对Lib目录下的文件进行瘦身处理
2:重新编译so文件,用更小的库代替
3:优化res.assets文件
3.1:手动lint检查,删除无用资源
3.2:使用tinypng对图片进行压缩
3.3:对图片使用Webp格式代替
3.4:尽量不在项目中使用帧动画
3.5:使用gradle开启shrinkResources
4:减少classes.dex大小
5:其它
3:总结

  1. 对apk进行结构分析

首先上传一张瘦身前通过Analyze app分析出来的图片(打开方式:Android Studio下 ——> Build——> Analyze app):(这是已经做了一次优化后的截图)

android 包瘦身 安卓软件瘦身_Android


APK包结构如下:

lib/:包含特定于处理器软件层的编译代码。该目录包含了每种平台的子目录,像armeabi,armeabi-v7a, arm64-v8a,x86,x86_64,和mips。大多数情况下我们可以只用一种armeabi-v7a,后面会讲到原因。
assets/:包含应用可以使用AssetManager对象检索的应用资源。
res/:包含未编译到的资源 resources.arsc,主要有图片资源文件。
META-INF/:包含CERT.SF和 CERT.RSA签名文件以及MANIFEST.MF 清单文件。
resources.arsc:包含已编译的资源。该文件包含res/values/ 文件夹所有配置中的XML内容。打包工具提取此XML内容,将其编译为二进制格式,并将内容归档。此内容包括语言字符串和样式,以及直接包含在resources.arsc文件中的内容路径 ,例如布局文件和图像。
classes.dex:包含以Dalvik / ART虚拟机可理解的DEX文件格式编译的类。
AndroidManifest.xml:包含核心Android清单文件。该文件列出应用程序的名称,版本,访问权限和引用的库文件。该文件使用Android的二进制XML格式。
通过分析图可以知道,目前app主要是res文件占比比较大,占了16M,占了整个应用约是45.6%。然后是so文件,整个目录占了7.1M,其次是assets目录,整个目录占了3.4M,第三就是资源文件res目录了。所以接下来我们处理步骤就是按这个顺序来处理。(简单说下图中的Raw File Size(磁盘解压后的大小)和DownLoad Size(从应用商店下载的大小),分析了包结构组成之后,我们可以开始瘦身操作了。

2.对apk进行具体实操

  1. 修改lib配置:
    so文件的优化:通常我们在使用NDK开发的时候,我们经常会有如下这么一段代码: ndk { abiFilters “armeabi-v7a”, “x86”, “arm64-v8a”, “x86_64”, “armeabi” }//设置支持的so库架构
    最后我的修改代码如下:ndk{abiFilters “armeabi-v7a”}//设置支持的so库架构
  2. android 包瘦身 安卓软件瘦身_android 包瘦身_02

  3. 接下来说明这么做的依据:
    看上面图分析,armeabi-v7主要不支持ARMv5(1998年诞生)和ARMv6(2001年诞生).目前这两款处理器的手机设备基本不在我公司的适配范围(市场占比太少)。
    而许多基于 x86 的设备也可运行 armeabi-v7a 和 armeabi NDK 二进制文件。对于这些设备,主要 ABI 将是 x86,辅助 ABI 是 armeabi-v7a。
    最后总结一点:如果适配版本高于4.1版本,可以直接像我上面这样写,当然,如果armeabi-v7a不是设备主要ABI,那么会在性能上造成一定的影响。
    打完包后会缩小一部分,这就是良好的开端,接着让我们继续
  4. 重新编译so文件,用更小的库代替:
相信很多开发者都有这种苦恼,很多第三方我们导入进来只用到其中很小一部分功能,大部分功能都是我们用不上的。这时候我们找到源代码,将我们需要的那部分代码提取出来,重新编译成新的so文件,再导入到我们项目中。当然,如果之前没有编译过so文件,这部分建议做最后的优化去处理。不然你会遇到很多问题,本文没有对这里做额外处理,因为项目中没有用到很多第三方的so文件,所以省略,有做过或者需要的同学可以一起讨论
  1. 优化res,assets文件大小
    (1). 手动lint检查,手动删除无用资源
在Android Studio中打开“Analyze” 然后选择"Inspe
   ![在这里插入图片描述]()
   (2). 使用tinypng等图片压缩工具对图片进行压缩。

  打开网址,将大图片导入到tinypng,替换之前的图片资源。

(3). 大部分图片使用Webp格式代替。

可以给UI提要求,让他们将图片资源设置为Webp格式,这样的话图片资源会小很多。如果想了解更多关于webp,请点击这里webp,当然,如果对图片颜色通道要求不高,可以考虑转jpg,最好用webp,因为效果更佳。

(4). 尽量不要在项目中使用帧动画

一个帧动画几十张图片,再怎么压缩都还是占很大内存比重的。所以建议是让UI去搞,这里可以参考使用lottie-android,如果项目中动画效果多的话效果更加明显。当然这就要辛苦我们UI设计师大大了。

(5). 使用gradle开启shrinkResources

移除无用资源文件,下面是我的配置:
    ![在这里插入图片描述]()
    通过上述步骤操作,apk效果
    ![在这里插入图片描述]()

一共优化了将近6.5M,别问我为什么res还有11.5M,里面大量的gif和webp格式的动图,lib包还有5.9M.后面再慢慢细究这个问题。后面要做的两部分,一部分是将资源文件下的所有gif图放后台下载处理,第二个是和UI讨论下如何减小webp 动图的大小。

  1. 减少chasses.dex大小
classes.dex中包含了所有的java代码,当你打包时,gradle会将所有模板力的.class文件转换成classes.dex文件,当然,如果方法数超过64K,将要新增其他文件进行存储。可以通过multidexing分多个文件,比如我这里的chasses2.dex。换句话说,就是减少代码量。我们可以通过以下方法来实现:

尽量减少第三方库的引用,这个在上面我们已经做过优化了。避免使用枚举,这里特别去网上查了一下,该如何用?,得出的结论是,可能几十个枚举的内存占有量才相当一张图片这样子,优化效果也不会特别明显。当然,如果你是个追求极致的人,我不反对你用静态常量替代枚举。如果你的dex文件太大,检查是否引入了重复功能的第三方库(图片加载库,glide,picasso,fresco,image_loader,如果不是你一个人单独开发完成的很容易出现这种情况),尽量做到一个功能点一个库解决。

  1. 其他
    1.删除无用的zip包
    2.删除翻译资源,只保留上架地区语言
    3.使用动态加载so文件,插件化开发
    4.大资源放到服务器请求
    5.android-support包尝试剔除项目

3.总结
到这里所做的优化基本就结束了,apk也从41M左右减小到26M左右,第一阶段目标暂时告一段落,其中有些优化本文只是列举了出来,但是并没有去做,比如:重新编译so文件,用更小的库代替/大部分图片使用Webp格式代替和其它里面的优化措施,因为项目需求原因,所以我暂时就不进行优化了,如果上面提到的都能做到,理论上apk应该在15-20M左右,当然也只是个人的揣测,如果有伙伴有其它更好的瘦身经验或者我没有提到的方法或者我说的不对的地方,还请指出,让我们一起进步,最后:感谢阅读!