您的位置:首页 > 其它

如何做到将apk大小减少6M

2016-03-01 10:07 393 查看
我们的apk去年业务需求增长迅速,伴随而来的是apk大小由年初的20M以下,增长到年底的30M。

包大小增长的坏处有:

过大的下载包会降低新用户的下载兴趣
增加下载安装中失败的风险
提高各个渠道下载发布的成本(渠道是会根据你的包大小设置收费规则的)

因此,减少包大小的工作看上去不痛不痒,其实还挺重要的。

接下来,我将分享下我在包大小瘦身方面的努力。

技术列表

lint检查
微信资源压缩
webp本地图片处理
tiny图片处理
proguard

lint检查清除冗余

实践方式

Android Studio

Analyze -> Run Inspection by Name

unusedResources

unused declaration

结果:

我们apk里引用了近一百的aar。我对他们进行逐一检查。

发现了300+冗余文件 节省了700+KB字节占用



建议:

各业务团队因养成定期检查的良好习惯。即减少了冗余,又能减少平时开发业务中无用代码的干扰。

微信资源压缩

简单原理介绍:

apk代码运行时,是通过 code ->R ->res找到对应资源的。

而R ->res的映射关系是打包时写在resources.arsc里的。

所以对生成的apk进行的操作如下:

先解压缩包
然后对res目录下的文件夹和文件进行名称替换
同时修改resources.arsc里对应的R与资源的映射关系
然后再打包签名生成新的apk

使用说明

命令:

Java -jar andresguard-1.1.jar mogujie.apk -config

weixinResShrinkConfig.xml

输入:

andresguard-1.1.jar
需要处理的apk文件
配置文件config.xml

输出:

处理后的apk
mapping文件,记录名称变动前后对应关系

config.xml配置了

whitelist  (com.mogujie.R.XXX.XXX)
sign (签名文件路径和密码)
其他相关处理(如:是否压缩资源,是否用7Z压缩等)

结果:

能将apk包大小减少2M+

处理后的apk资源变成混淆名称,起到一定的安全保护作用



日常维护注意事项:

代码中有通过getIdentifier 获取的资源文件需要添加白名单



推广:

微信资源压缩工具与业务代码无关,我们已经把这部分技术处理整合到打包系统里,推荐大家在发布你们的apk时加入微信资源压缩,效果杠杠的。

附:

微信Android资源混淆打包工具原理:

http://mp.weixin.qq.com/s?__biz=MzAwNDY1ODY2OQ==&mid=208135658&idx=1&sn=ac9bd6b4927e9e82f9fa14e396183a8f#rd

github地址:

https://github.com/shwenzhang/AndResGuard/blob/master/README.zh-cn.md

webp本地图片处理

背景

Android4.0+原生支持,无需修改代码。
相同图片效果,webp的文件占用空间更小。
解码和渲染时间比png,jpg高出几倍,但用户体验几乎不受影响。

关于webp与png,jpg详细对比评测,可参考腾讯团队webp探索之路:

http://isux.tencent.com/introduction-of-webp.html

wep命令的安装与使用,参考:

https://developers.google.com/speed/webp/

实践



文件夹名称文件夹描述大小
pdrawable-xhdpi-v4里的jpg和png图片1409张 3.8M
cwebpp通过webp有损压缩全部图片后的文件夹1409张 2M
webpp-lossless通过webp无损压缩后的文件夹1396张 3.5M
经过大量的测试,最后将webp处理设置为:有损,质量75

cwebp -q 75 -m 6 a.png -o a.webp

考虑到drawable-xhdpi-v4以外的文件夹下的图片,webp压缩能减少2M+的apk空间

应用

因为webp的图片格式没有默认的图片浏览器,必须通过chrome浏览器打开,影响了平时业务开发的便捷性。因此,我设计将webp图片处理工作放在了主客build时进行。

gradle build主客时,有一个mergeXXXResource Task,它将主客和aar中所有的res资源统一整合到/build/intermediates/res/flavorName/{buildType}目录下。



因此,我写了一个gradle plugin插件 webpConvertPlugin,在mergeXXXResource Task执行后,processXXXResource Task前,插入新的webpConvertPlugin Task 将上述目录下中drawable项目目录里的png,jpg图片(不包含.9图片,webp转换后显示效果不佳)批量处理成webp图片。这样最后打包生成的apk里就是webp图片了。

问题:

在我们上线webp插件时遇到了一个无法规避的严重问题。有alpha值的jpg图片,经过webp转换后,无法在4.0,4.1的Android系统上运行。经过调研从http://developer.android.com/guide/appendix/media-formats.html中找到了答案:



只有在4.2.1+以上的机型,才能解析无损或者有透明度调整的webp图片

然后我又用imagemagick的命令遍历apk中所有图片,统计出1500+张的图片只有80多张图片没有alpha值。

因此,在4.0 4.1目前还有大量用户的前提下,webp本地图片批量替换的方案无法上线。

推广

webp批量处理本地图片的插件适用于各个Android项目,我们开源了自写的webp插件,请参考:

https://github.com/mogujie/WebpConvert_Gradle_Plugin

tiny图片处理

https://tinypng.com/

目前所知图片压缩效果最好的网站。谁用谁知道。

为解决日常开发中,大家手动去此网站挨个处理图片的困扰。我利用tiny提供的jar包做了个批量处理本地图片的tinyPIC gradle plugin。它在build 中插入一个新的tinyPicPlugin task.遍历寻找项目res中以drawable开头的文件夹中的图片资源,调用tiny API进行压缩工作并替换原来的文件。

重要文件

tinypic_white_list.txt(白名单,可设置不进行处理的图片)
tinypic_compressed_list.txt(记录处理过的图片,避免重复压缩)

推广

tinyPIC插件适用于各个Android项目,我们也开源了自写的tiny 插件,接入方法请参考:

https://github.com/mogujie/TinyPIC_Gradle_Plugin

Proguard

Proguard是编译时对java代码进行压缩,混淆,优化,预编译等操作的集成化工具。达到删除冗余,增加安全防护,减小大小的功效。具体介绍,可参考

http://mobile.mogujie.org/doc/android/mixup.html

项目的应用



1. mogu_proguard_annotations.pro 支持proguard注解的使用
(你可以在~/Android/sdk/tools/proguard/examples/annotations/lib中找到配置文件annotations.pro)

2. mogu_proguard.pro 保证功能正常运行的相关配置(根据项目自行配置)

如何写proguard.pro的配置

mogu_proguard.pro的配置主要是为了解决项目在proguard使用中遇到的问题。

遇到的问题又分为两个阶段:

编译时的报错 Problems while processing

常见于第三方API的Warning: can’t find referenced class

解决方法如:

-dontwarn com.google.**
-keep class  com.google.** { *;}


运行时异常 Problems at run-time

原因基本都是原本需要具体名字的上下文,混淆后找不到造成的。主要有,native方法失效,注解失效,json数据解析失败,反射失效。

解决方法:

无源代码的第三方API,添加对应的-dontwarn -keep

自有代码使用注解,注解前build.gradle里加入

dependencies {
compile "com.infstory:proguard-annotations:1.0.2"
}

或在~/Android/sdk/tools/proguard/examples/annotations/lib里找到并引入annotations.jar

你的xxx.pro配置文件里

-keep class  proguard.annotation.* {*;}

然后分别按照下面的情况使用注解

.so native方法找不到引起的问题

请将有.so native的类加上

@proguard.annotation.KeepClassMembers


注解类失效

请将注解类加上

@proguard.annotation.Keep


根据写死的或者重服务器传过来的类名称 反射实例化类相关的功能失效

请将需要反射的类加上

@proguard.annotation.Keep


json数据解析,数据展示不出来

请将需要json解析的类加上

@proguard.annotation.KeepClassMembers


更多关于注解的使用,可参考:https://github.com/yongjhih/proguard-annotations

异常日志的转义

混淆后的错误日志会变成这样

java.lang.NoSuchFieldError: USER_COMMENT

at e.a.a.a(Unknown Source)

为了定位问题代码,需要使用mapping文件。

简单点的日志可直接在mapping中搜索e.a.a.a,获取对应的源文件

复杂点的就要用到proguardgui.jar这个工具了。在你的Android sdk/tools/proguard/lib

目录中可以找到。



因业务代码不断更新,无法统计具体数值,故大致给出每个技术减少的合理效果范围

成果

技术名称减少大小范围
lint检查删除冗余700kb ~ 800kb
微信资源压缩2M左右
微信webp本地图片处理压缩未上线
tiny图片处理0.8M ~ 1.3M
proguard1.8M ~ 2.3M
总计6M左右
微信资源压缩和proguard 提供了Android apk 一定的资源文件和源代码的安全保护能力

结语

以上就是目前想到并运用的瘦身技术,写这个的目的是希望能帮助到需要瘦包的同学,望能给您带来一点启示。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: