在开发过程中;由于业务的扩展;版本的迭代;第三方的集成等开发工作,我们安装包越越来越大;导致下载安装的过程中越来越慢.影响到用户的体验,瘦身的目的最明显的一个就是:提高下载转化率。怎么理解呢?举个例子来说,假如我们的盛钱包成长版应用包20MB+,有100个潜在用户想要去下载尝试使用你的应用,在移动网络的情况下,结果有20个用户嫌弃安装包太大而直接放弃,有30个用户在等待下载的过程中取消下载,在wifi情况最终只有50个用户下载安装了应用。这时你的应用的实际下载转化率其实是50/100 =50%。
另外一个;apk的瘦身;可以为用户节省不少的流量;对我手机流量不多的人;是一个福音啊....
简单的总结:安装包越小,用户下载等待的时间越短,对手机配置要求的也越小,设备的体验愈佳,应用的下载转化率也就越高。
开始瘦身前,需要先了解一下APK都主要由哪些成分组成.我以盛代宝目前安装包的分析结果图如下:
(TIP:比例分析构成图(比例会自动按从大到小排好序呈现 )
(TIP :目前盛代宝经过优化打出的包的大小是6.33M)
APK 的瘦身 主要针对assets、classes.dex、lib、res内容进行精简.
目前网络上现在大部分都有混淆模板,以及在GitHub 上也有混淆的插件可以集成 AndroidProGuard 插件;一般都是基于混淆模板上去添加自己想要的混淆规则,一般遵循以下混淆规则
###-----------基本配置-不能被混淆的------------###-
-keep public class * extends android.app.Activity
-keep public class * extends android.app.Fragment
-keep public class * extends android.app.Application
-keep public class * extends android.app.Service
-keep public class * extends android.content.BroadcastReceiver
-keep public class * extends android.content.ContentProvider
-keep public class * extends android.app.backup.BackupAgentHelper
-keep public class * extends android.preference.Preference
###-----------support.v4/v7包不混淆------------###-
###-----------保持Serializable不混淆------------###-
###-----------保持 Parcelable 不混淆------------###-
###-----------不混淆资源类------------###-
###-----------保持 native 方法不被混淆------------###-
###-----------保持自定义控件类不被混淆------------###-
###-----------保持枚举 enum 类不被混淆------------###-
###-----------保持自定义控件类不被混淆------------###-
###-----------保持实体类不被混淆------------###-
###-----------保持jar包不被混淆------------###-
###-----------保持反射相关的类和方法不被混淆------------###-
###-----------保持webview 与js互相调用的类 不被混淆------------###-
###-----------保持注解继承类不混淆------------###-
Tip:另外如果我们项目应用到第三方sdk 的混淆;如百度,友盟,极光等一般都是从官网上提供的混淆规则里复制;避免出现意外的错误
不要只是注释,担心可能以后会用到。因为一般的开发都会使用版本控制工具git svn等,所以这种担心是多余的。
发现有重复功能实现的代码或者框架要及时重构,删除重复部分的代码和框架。出现重复功能代码的情景大多如下:已经有了的功能代码或框架,团队成员不知道自己又写了一套或者引入另外的相同功能的框架。这种情况的发生也反映出你们团队之间的沟通存在一定的问题。有可能是个人经验问题,也有可能是整个团队的规范,共识问题,导致大家都不重视。
插件化,一种懒加载思想的体现,先让用户能够安装宿主包,对于一些功能模块做插件化,在特定的时机再下载安装。
(Tip 比如现在github比较火的Small ,滴滴插件;还有360插件化,有空可以研究研究以下;绝对有好处)
放在assets下的文件不会生成ID,存放的文件形式可以是多样的比如音频、图片、html,配置信息相关的等等,精简体积也就是精简这些内容。
简单介绍下resources.arsc文件来源与作用:除了assets和res/raw资源被原装不动地打包进APK之外,其它的资源都会被编译或者处理。除了assets资源之外,其它的资源都会被赋予一个资源ID。打包工具负责编译和打包资源,编译完成之后,会生成一个resources.arsc文件和一个R.java,前者保存的是一个资源索引表,后者定义了各个资源ID常量,供在代码中索引资源。所有的png文件是以STORE的方式存储到apk里的,通俗的说,当文件是STORED的方式存储到zip,表示这个文件并没有经过压缩,现在业内有一个开源的插件针对以上原理进行了一定的压缩;它就是如下压缩插件
lib目录用于存放通过C或C++编写编译生成的so文件(native库/JNI开发)
目前市场上主流的架构还主要是arm架构,所以如果不是必要的话,可以考虑不支持x86和mips架构,但这并不意味着CPU是x86或mips架构的手机就不能正常安装使用APK了,因为放在arm目录下的so库是可以兼容到其他架构的;
另外arm架构中的eabi-v7a相比于eabi只是在图形渲染方面有了很大的改进,所以如果so库对图形渲染没有很高的要求的话,完全可以把so库只存放在arm eabi目录中,这样可以大大减小APK的体积。
lib瘦身主要是减小对 CPU 架构的支持,配置起来很简单,在 build.gradle 使用 abiFilters 配置需要用到的 CPU 架构,并将不需要兼容的 so 文件从项目中移除即可。 一般只要支持armabi和x86就够了 示例代码块如下:
res文件夹里面主要就是包括各种布局文件,value文件,图片文件,原生文件。这一块的处理方案主要采用2种方式,一是压缩资源,二是删除未使用的资源。
A) 在工程里面直接删除没有使用的资源 Android Studio 选中项目右键 =>Refactor =>Remove Unused Resources
B)不打包不需要使用的资源 利用Android Plugin开启gradle 的Resource shrinking进行构建打包,这时候没有被使用的资源将不会打进包里
开发目录下会有个drawable或者mipmap目录用于适配不同dpi的屏幕,Android界面尺寸:480*800、720*1280、1080*1920 (美工在切图是基于一套分辨率进行切图) 目前市面上绝大部分机型都处于xxhdpi的适配范围,所以可以考虑只保留xxhdpi目录下一份图片资源即可;目前公司基于720 来切图就可以了;
一些情况下,我们可以考虑使用 Drawable XML 来代替 PNG,如:渐变的背景图,用几行 XML 就可以描绘出来,何必使用几十到上百K的 PNG 文件, 如下图其实都是可以不用图片就可以实现的一些简单的功能
图形显示;比如圆角的按钮,圆形的UI 我们自己绘制,可以减少图片的导入;减少APK 的体积.
WebP是谷歌研发出来的一种图片数据格式,它是一种支持有损压缩和无损压缩的图片文件格式,如果应用支持到Android 4.0+,那么我们可以使用WebP格式代替PNG,我们的资源大小能降低50%多。
不过就目前来说,对于4.0+ 到 4.2.1 ,原生只支持完全不透明的webp图,4.2.1+ 对于webp的是完全支持的(包含半透明的webp图)。所以说对于4.2.2(API17)以下的版本,还是需要引入兼容库来解决。但是另外一点,引入兼容库又会导致包体变大。不过这种增量或许和把所有png图换成webp所带来的减量比较或许不值得一提,特别是图片特别多的应用,这种增量几乎可以不计。另外也要注意的是,某些国产rom会代理类Resource为自己定义的,例如小米2刷成4.xx的手机上,小米机器代理了类Resource为MIUIResource,但是这个MIUIResource未能正确识别webp资源,会导致加载资源文件失败而出现崩溃。所以应该考虑自己用户的机型分布,考虑使用WEBP图片资源格式替换png格式。
APK 的瘦身好处; 就不言而喻了;或许还有其他有用的方案;这些也需要大家提出完善;可能我总结的还不是很完美;目前我是拿了盛代宝做试点;效果还是看的见; 目前经过不断的优化; 目前包的大小维持在5M+;个人觉得还有优化的空间; 如果时间充裕,这个我会持续的优化下去;项目都是在不断优化;不要怕犯错,用心去做一件事;你会收获很多,善于总结;经验是累积的 我相信你可以为了你的项目瘦身做出很大的贡献。如果有好的建议;欢迎大家都提出来;我将继续完善这个文档.