首发地址:http://www.jayfeng.com/2015/12/29/APK%E7%98%A6%E8%BA%AB%E5%AE%9E%E8%B7%B5/html
由于推广的须要,公司须要把APK的大小再“减少”一下,4M之内!
当达到4M之内以后,公司建议说,可否再压压?2M如何?java
由于平时就考虑到大小的限制,因此不少工做已经作过了,以下列举如今的状态:android
- 7.3M(Debug版本)和6.5M(Release版本)
- 开启minifyEnabled
- 开启shrinkResources
- 已经去除不相关的大型库
- 图片和代码已经经历过粗略的一轮清理
...
android打包自己会对png进行无损压缩,不信你们能够看看apk中的图片的大小实际上比你代码工程里的图片要小(针对没进行过无损压缩的那些png图)。
因此,纯粹的进行无损压缩并不会对apk的减少有任何效果,这是我特别想在这里强调的一个经验。
如今你们主流的比较喜欢用的tinypng实际上是有损压缩:git
https://tinypng.com/
[原文] TinyPNG uses smart lossy compression techniques to reduce the file size of your PNG files...
[翻译] TinyPNG使用智能有损压缩技术,来减小PNG文件的大小...github
经过tinypng确实能在尽可能少的损失下再减少apk,若是图片资源多或者大的话,效果仍是很明显的。
具体减小多少,由于这个处理过程咱们是间隔作的,没法准确给出结果,就按200k~500k算吧。web
经验发现,一些背景,启动页,宣传页的PNG图片比较大,这些图片图形比较复杂,若是转用有损JPG可能只有不到一半(固然是有损,不过经过设置压缩参数能够这种损失比较小到忽略)。
由于都是大图,因此这种方式能有效减少apk的大小。
这种状况下的apk的减少是不可估量的。
json
若是png大图转成jpg仍是很大,或者想压的更小,而尽可能不下降画质,那么能够考虑一下webp。bash
android 4.0+才原生支持webp, 可是咱们的app是兼容2.3+,因此4.0如下的设备将没法看到图片。微信
咱们选择不对4.0如下作webp兼容处理,不显示就不显示。不然,要引入webp相关so文件增大apk大小。网络
经过把下面四张大图换成webp,webp的quality参数按50配置(听说官方评测75是最佳值),清晰度勉强能够接受,这个值你们具体按产品要求来定。
其中安装jpg转webp工具:
brew install webp
转换命令以下
cwebp -q <quality> input.jpg -o output.webp // Example: cwebp -q 50 a.jpg -o a.webp
更多下载:https://developers.google.com/speed/webp/docs/precompiled
最终,apk减少了188k。
补充:
在4.0 ~ 4.2.1的设备上没法显示带有透明度的webp,好比,把png转成webp则没法显示,可是若是把png先转成jpg再转成webp则能正常显示了,但会丢失透明度。参考连接:http://developer.android.com/guide/appendix/media-formats.html
若是通过上面的步骤,依然存在大图的话,说明确实图有点大了,可能真的有点大了!
因此,要考虑的问题是,是否有必要保证如此的大小?可否缩小?
若是这方面能减少的话,apk瘦身的效果必然又会上一个档次。
这种状况下的apk的减少是不可估量的。
一些aar库里面包含根本就没有用的图。最典型的是support-v4兼容库中包含一些“可能”用到的图片,实际上在你的app中不会用到。
我没有把全部图都替换掉,只是把几张大一点点的图(选中的那些图)用1x1的图片替换,若是9patch图的话,要作成3x3的9patch图替换。
support库可能还算好的,就怕有些库引用了一些大图而不自知,能够在
apk减少了18k。
感谢@杨辉__ ,@kymjs张涛的提醒,armable-v7和armable文件夹能够只保留armable。
固然,armable-v7a的库会对图形渲染方面有很大的改进,由于咱们主要是一些业务上动态库,因此删掉无大碍。
apk减少了191k。
这个方案网上一直在说,以前一直没有需求或者动力实践,在这里感谢一下@裸奔的凯子哥的推荐和交流,他那边的apk能够压小1M,效果仍是比较惊人的。
这个步骤我是在后面不少步压缩以后测试的,每一个阶段的压缩结果都会有些许出入,因此数据仅供参考。
经过正常压缩,apk包减少了464k。
若是开启7zip,apk包减少了594k。
apk减少了594k。
PS: 关于这个压缩,我集成到了gradle脚本中了,新建了一个Task,大概代码以下:
task compressReleaseApp { // 在现有release的版本上生成到compressed目录下 def appid = "appid" def channel = "abcdefghijkl" def guardJarFile = file('../AndResGuard/andresguard-1.1.jar') def guardConfigFile = file('../AndResGuard/config.xml') def originApkFile = file("../app.${appid}/build/outputs/apk/release/${appid}-release-${rootProject.ext.versionName}-${rootProject.ext.versionCode}-${channel}.apk") def outputDir = file("../app.${appid}/build/outputs/apk/compressed/") def keystoreFile = file(RELEASE_STORE_FILE) // 开始执行压缩命令 def proc = "java -jar ${guardJarFile} ${originApkFile} -config ${guardConfigFile} -out ${outputDir} -signature ${keystoreFile} ${RELEASE_STORE_PASSWORD} ${RELEASE_KEY_PASSWORD} ${RELEASE_KEY_ALIAS}".execute(); proc.waitFor(); println "return code: ${ proc.exitValue()}" + ", stderr: ${proc.err.text}" + " stdout: ${proc.in.text}" }
config开启了7zip, 部分配置以下:
<?xml version="1.0" encoding="UTF-8"?> <resproguard> <!--defaut property to set --> <issue id="property" > <seventzip value= "true" /> <!-- ... --> </issue> <issue id="whitelist" isactive="true"> <path value ="com.xxx.yyy.R.drawable.emoji_*" /> <path value ="com.xxx.yyy.... /> </issue> <issue id ="compress" isactive="true"> <!-- ... --> </issue> </resproguard>
详情参考:Android资源混淆工具使用说明
原理介绍:安装包立减1M--微信Android资源混淆打包工具
以前为了简单起见,不少包都直接忽略了,如今启动严格模式,把能混淆的都混淆了:
采用微信压缩方案最终效果比较:
apk减少了215k。
PS:混淆后,必定要通过严格测试,有时候甚至很难发现错误,好比我开启严格混淆,用了一段时间以后慢慢发现了两个bug,排除了两个包程序才正常。
有意思的是,不管什么时候何地去清理代码和资源,总能有新的发现:
- 新发现或者新引入的无用图片
- 这几张图怎么同样
- 这个类好像没有用
- 没用的类相关的图片也没用
- 有些图片能够用着色方案替换
- 有些图片能够用shape来代替
- hdpi里的ic_luancher.png好像也能够删掉
- ...
apk减少了66k。
以前为了保留调试信息,咱们是在Proguard保留了符号表的:
-keepattributes SourceFile,LineNumberTable
官方渠道我以为仍是尽可能保留这个,如今针对推广渠道,只能采用特殊手段,注释这一行。
apk减少了230k。
ps:之后友盟上看推广渠道的bug要辛苦一点,手动上传mapping.txt了。
能够对仅在运行时须要的库设置provided关键字,实际并不被打包:
provided 'com.android.support:support-annotations:22.0.0'
我没有发现这样的场景,若是说有的话,就是support-annotations,可是通过后来的测试验证,support-annotations原本就会在release版本中被minifyEnabled掉,因此对support-annotations设置provided是没有意义的。
若是有实际场景,欢迎留言说明,不甚感激。
apk没有减少。
虽然应用的表情很少,只有50来个,可是若是能把这部分表情放到网上,不只能有效减少apk大小,还能够方便后期扩展支持:
打包成emoji_v1.zip, 大小是202k。
如今把emoji_v1.zip放到网上,按需下载后使用,最终对比结果以下:
apk减少了193k。
考虑着色方案主要目的是更方便支持多主题,减轻UI工做量,减小工程里一大堆selector文件等,而后才是,顺便的减少一下apk大小。
经过着色方案,咱们去除了10多张纯色的按下状态图片和对应的xml等等。
apk减少了15k。
PS: 具体实现能够参考 http://www.race604.com/tint-drawable/ ,而我也把它集成到了个人LessCode库中了:DrawableLess.java
发现两个地方:
- 如今发现七牛的SDK引用了android-async-http-1.4.6.jar,虽然不大,只有95.4k,可是感受彻底能够写一个轻量级的jar,控制在10~20k就足够了,具体能够在现有的网络库上实现。
- 本身工程使用的是UIL,可是引入的第三方库引用了picasso,两个重复的图片下载库也是彻底没用必要的。
如今尚未处理这块,新任务介入,延期优化,敬请期待。
这是一个很基本的点,可是确很容易被人忽视,当你仔细回顾的时候,有一些鸡肋的功能或者库,是几无用处的。不如干脆去掉。
好比,在很早的时候,我就把咱们app里的sharesdk删除了,由于对于咱们的产品定位和推广来看,这毫无心义。
这种状况下的apk的减少是不可估量的。
这个视具体状况决定。
由于咱们的APP里面包含友盟和百度两套统计系统,早期老板要求,事实上后面已经不多看这方面的数据,百度统计的数据几乎没用人去看,能够暂时先去除。
本来的百度统计的jar有130多k,去除以后的apk的减少会远远没有这么多。
apk减少了20k。
使用更小的库不该该成为你选择方案的决定性因素,可是能够做为参考因素(freso确实太大了,这个大小也能够成为决定性因素)。
图片下载,网络请求,json解析等等的库和它的竞品都有多大,你内心有数吗?
以工具库为例,网上有不少工具库,可是每每它们的大小很难控制。
- xutils-3.2.6.aar -- 843.8k
- lite-common-1.1.3.jar -- 148.1k
- lesscode-core-0.8.2.aar -- 64k
- ...
上面最后一个库LessCode是我本身收集的工具类集合,很是小:LessCode,混淆后只有不到50k大小。
不只提升了开发效率,减小了冗余代码,并且能避免引用一些其余大型的库,有效避免包的增大。
好比,咱们碰到过这样的一个bug,快速点击按钮屡次触发跳转,如今RxJava结合RxBind有这样的一个场景解决方案,若是引入这些库的话必然会增大apk大小,实际上就几行代码,我把这样的解决方案集成到了LessCode,下次别的项目碰到这样的问题不用再犹豫是否要引入一个这么大的库了。
这些小的工具库,建议根据本身的经验人手总结一个,不求全,但求精!
这种状况下的apk的减少是不可估量的。
尴尬的是,咱们所呈现的功能大部分都是重要的不可分割的功能,很难从业务上分离出来。
今年预计要实践一个轻量级的插件化方案,用别人的也好,本身写也好,但愿能解决或者优化一些安装包加载多模块,或者主题切换,或者热修复的问题。
这里做为候选方案备用。
这种状况下的apk的减少是不可估量的。
一开始考虑瘦身,领导是容许适当的砍掉一些功能,由于4M的目标咱们已经实现了,因此如今尚未到砍功能的地步。
这里做为候选方案备用。
这种状况下的apk的减少是不可估量的。
文章发出后,收到了一些朋友的建议,补充几点。
感谢@牧志轩的建议,经过配置resConfigs能够选择只打包哪几种语言,进而去掉各类aar包中全世界的语言,尤为是support包中的。
选择保留什么语言要根据产品的用户和市场来定,若是只选择默认英语和中文语言,配置以下
android { defaultConfig { resConfigs "zh" } }
看看效果:
若是不采用微信压缩方案结果对比,apk减少了197k。
若是采用微信压缩(开启7zip)对比结果,apk只减少了16k,由于微信对resources.arsc进行了强力压缩,厉害!
apk减少了16k。
再次感谢@杨辉__的建议,x86的包删除了以后,测试反应好像有些机器容易崩溃,未能通过严格测试,因此主版本又复原了,只在个别渠道执行这条措施。
通常状况下不会有问题,测试了一下效果,apk减少了78k。
这里做为候选方案备用。
最终,咱们成功的把apk压到了2.9M,若是把上面遗漏的步骤继续再作,应该还能再减少一点。 客户反应压的好小,领导简直不敢相信~ 瘦身不难,难的是魔鬼瘦身!