【金沙澳门官网jin5888】Android APP终极瘦身

专访DroidPlugin作者张勇:安卓黑科技是怎样炼成的 – Android – 掘金

前段时间,奇虎360在Github上发布了一个Android开源项目DroidPlugin,这是一个实现动态加载的Android插件框架,可以免安装、免修改的运行第三方APK。一时间,它被誉为安卓黑科技,引起行业内的关注。
据其官方文档介绍,DroidPlu…

参考文献:APP终极瘦身指南

最近一直在研究关于apk瘦身方面的知识,看了很多文章受益匪浅。原文地址

微信 Android 资源混淆打包工具-安装包立减1M – Android – 掘金

上一篇文章我们讲述了Android减少安装包体积的一些tips,本文主要对前文提到的资源混淆做一个简单的分析。微信中的资源混淆工具主要为了混淆资源ID长度(例如将res/drawable/welcome.png混淆为r/s/a.png),同时利用7z深度压缩,…

随着业务的快速迭代增长,美团App里不断引入新的业务逻辑代码、图片资源和第三方SDK,直接导致APK体积不断增长。包体积增长带来的问题越来越多,如CDN流量费用增加、用户安装成功率降低,甚至可能会影响用户的留存率。APK的瘦身已经是不得不考虑的事情。在尝试瘦身的过程中,我们借鉴了很多业界其他公司提供的方案,同时也针对自身特点,发现了一些新的技巧。本文将对其中的一些做详细介绍。

Android Proguard 指南 – Android – 掘金

android 混淆配置指南英文版 我只是个默默翻译的搬运工
,好吧,翻译是为了提高英文水平。 Android Proguard 指南 Android
Proguard 混淆配置指南 ProGuard 这个ProGuard工具可以通过删…

前言

在开始讲瘦身技巧之前,先来讲一下APK的构成。

「个人总结」APK 瘦身实践 – Android – 掘金

因为推广的需要,公司需要把APK的大小再“减小”一下,4M以内!当达到4M以内之后,公司建议说,能否再压压?2M如何?
瘦身前因为平时就考虑到大小的限制,所以很多工作已经做过了,如下列举现在的状态:
7.3M(Debug版本)和6.5M(Release版本…

因公司中有个项目是商城和直播融合在一体的,apk包足足有50多M,因客户推广的需要,公司需要把APK的大小再“减小”一下

可以用Zip工具打开APK查看。比如,美团App 7.8.6的线上版本的格式是这样的:

新一代 Android 渠道打包工具:1000 个渠道包只需要 5 秒 – Android – 掘金

源码:https://github.com/mcxiaoke/packer-ng-plugin
最新版本 v1.0.4 – 2016.01.19 – 完善获取APK路径的方法,增加MarketInfo
v1.0.3 – 2016.01.14 – …

瘦身前,因为平时就考虑到大小的限制,所以很多工作已经做过了,如下列举现在的状态:

金沙澳门官网jin5888 1

App 瘦身最佳实践 – Android – 掘金

本文会不定期更新,推荐watch下项目。如果喜欢请star,如果觉得有纰漏请提交issue,如果你有更好的点子可以提交pull
request。本文的示例代码主要是基于作者的经验来编写的,若你有其他的技巧和方法可以参与进来一起完善这篇文章。
本文固定连接:ht…

1、开启minifyEnabled

2、开启shrinkResources

3、已经去除不相关的大型库

4、图片和代码已经经历过粗略的一轮清理

可以看到APK由以下主要部分组成:

所以现在是在这个基础上再进行一轮瘦身:

水果 价格
lib/ 存放so文件,可能会有armeabi、armeabi-v7a、arm64-v8a、x86、x86_64、mips,大多数情况下只需要支持armabi与x86的架构即可,如果非必需,可以考虑拿掉x86的部分
res/ 存放编译后的资源文件,例如:drawable、layout等等
assets/ 应用程序的资源,应用程序可以使用AssetManager来检索该资源
META-INF/ 该文件夹一般存放于已经签名的APK中,它包含了APK中所有文件的签名摘要等信息
classes.dex classes文件是Java Class,被DEX编译后可供Dalvik/ART虚拟机所理解的文件格式
resources.arsc 编译后的二进制资源文件
AndroidManifest.xml Android的清单文件,格式为AXML,用于描述应用程序的名称、版本、所需权限、注册的四大组件

1、tinypng有损压缩

当然还会有一些其它的文件,例如上图中的org/,src/,push_version等文件或文件夹。这些资源是Java
Resources,感兴趣的可以结合编译工作流中的流程图以及MergeJavaResourcesTransform的源码看看被打入APK包中的资源都有哪些,这里不做过多介绍。

android打包本身会对png进行无损压缩,不信大家可以看看apk中的图片的大小实际上比你代码工程里的图片要小(针对没进行过无损压缩的那些png图)。

金沙澳门官网jin5888,所以,纯粹的进行无损压缩并不会对apk的减小有任何效果,这是我特别想在这里强调的一个经验。

现在大家主流的比较喜欢用的tinypng其实是有损压缩:

https://tinypng.com/

[原文] TinyPNG uses smart lossy compression techniques to reduce the
file size of your PNG files…

[翻译] TinyPNG使用智能有损压缩技术,来减少PNG文件的大小…

通过tinypng确实能在尽量少的损失下再减小apk,如果图片资源多或者大的话,效果还是很明显的。

具体减少多少,因为这个处理过程我们是间隔做的,无法准确给出结果,就按200k~500k算吧。

在充分了解了APK各个组成部分以及它们的作用后,我们针对自身特点进行了分析和优化。下面将从Zip文件格式、classes.dex、资源文件、resources.arsc等方面来介绍下我们发现的部分优化技巧。

2、把png转为jpg,再转为webg

前面介绍了APK的文件格式以及主要组成部分,通过aapt l -v xxx.apk或unzip -l
xxx.apk来查看APK文件时会得到以下信息,见下面截图:

⚠️注意:在4.0 ~
4.2.1的设备上无法显示带有透明度的webp,比如,把png转成webp则无法显示,但是如果把png先转成jpg再转成webp则能正常显示了,但会丢失透明度。参考链接:http://developer.android.com/guide/appendix/media-formats.html

金沙澳门官网jin5888 2

3、大图压缩

通过上图可以看到APK中很多资源是以Stored来存储的,根据Zip的文件格式中对压缩方式的描述Compression_methods可以看出这些文件是没有压缩的,那为什么它们没有被压缩呢?从AAPT的源码中找到以下描述:

如果经过上面的步骤,依然存在大图的话,说明确实图有点大了,可能真的有点大了!所以,要考虑的问题是,是否有必要保证如此的大小?能否缩小?如果这方面能减小的话,apk瘦身的效果必然又会上一个档次。这种情况下的apk的减小是不可估量的。

/* these formats are already compressed, or don't compress well */static const char* kNoCompressExt[] = { ".jpg", ".jpeg", ".png", ".gif", ".wav", ".mp2", ".mp3", ".ogg", ".aac", ".mpg", ".mpeg", ".mid", ".midi", ".smf", ".jet", ".rtttl", ".imy", ".xmf", ".mp4", ".m4a", ".m4v", ".3gp", ".3gpp", ".3g2", ".3gpp2", ".amr", ".awb", ".wma", ".wmv", ".webm", ".mkv"};

4、覆盖aar里的一些默认的大图,去除无用的语言资源

可以看出AAPT在资源处理时对这些文件后缀类型的资源是不做压缩的,那是不是可以修改它们的压缩方式从而达到瘦身的效果呢?

5、删除armable-v7包的so和删除x86包的so

在介绍怎么做之前,先来大概介绍一下App的资源是怎么被打进APK包里的。Android构建工具链使用AAPT工具来对资源进行处理,来看下图(图片来源于Build
Workflow):

6、微信资源压缩打包

金沙澳门官网jin5888 3通过上图可以看到Manifest、Resources、Assets的资源经过AAPT处理后生成R.java、Proguard
Configuration、Compiled
Resources。其中R.java大家都比较熟悉,这里就不过多介绍了。我们来重点看看Proguard
Configuration、Compiled Resources都是做什么的呢?

详情参考:Android资源混淆工具使用说明

原理介绍:安装包立减1M–微信Android资源混淆打包工具

  • Proguard
    Configuration是AAPT工具为Manifest中声明的四大组件以及布局文件中(XML
    layouts)使用的各种Views所生成的ProGuard配置,该文件通常存放在${project.buildDir}/${AndroidProject.FD_INTERMEDIATES}/proguard-rules/${flavorName}/${buildType}/aapt_rules.txt,下面是项目中该文件的截图,红框标记出来的就是对AndroidManifest.xml、XML
    Layouts中相关Class的ProGuard配置。

    金沙澳门官网jin5888 4

  • Compiled
    Resources是一个Zip格式的文件,这个文件的路径通常为${project.buildDir}/${AndroidProject.FD_INTERMEDIATES}/res/resources-${flavorName}-${buildType}-stripped.ap_。
    通过下面经过Zip解压后的截图,可以看出这个文件包含了res,AndroidManifest.xml和resources.arsc的文件或文件夹。结合Build
    Workflow中的描述,可以看出这个文件(resources-${flavorName}-${buildType}-stripped.ap_)会被apkbuilder打包到APK包中,它其实就是APK的“资源包”(res,AndroidManifest.xml和resources.arsc)。金沙澳门官网jin5888 5我们就是通过这个文件来修改不同后缀文件资源的压缩方式来达到瘦身效果的,而在后面“resources.arsc的优化”一节中也是操作的这个文件。

7、proguard深度混淆代码

笔者在自己的项目中是通过在package${flavorName}Task(感兴趣的同学可以查看源码)之前进行这个操作的。

8、深度清理代码和资源

下面是部分代码片段:

新发现或者新引入的无用图片

这几张图怎么一样

这个类好像没有用

没用的类相关的图片也没用

有些图片可以用着色方案替换

有些图片可以用shape来代替

hdpi里的ic_luancher.png好像也可以删掉

appPlugin.variantManager.variantDataList.each { variantData -> variantData.outputs.each { def sourceApFile = it.packageAndroidArtifactTask.getResourceFile(); def destApFile = new File("${sourceApFile.name}.temp", sourceApFile.parentFile); it.packageAndroidArtifactTask.doFirst { byte[] buf = new byte[1024 * 8]; ZipInputStream zin = new ZipInputStream(new FileInputStream(sourceApFile)); ZipOutputStream out = new ZipOutputStream(new FileOutputStream(destApFile)); ZipEntry entry = zin.getNextEntry(); while (entry != null) { String name = entry.getName(); // Add ZIP entry to output stream. ZipEntry zipEntry = new ZipEntry; if (ZipEntry.STORED == entry.getMethod() && !okayToCompress(entry.getName { zipEntry.setMethod(ZipEntry.STORED) zipEntry.setSize(entry.getSize zipEntry.setCompressedSize(entry.getCompressedSize zipEntry.setCrc(entry.getCrc } else { zipEntry.setMethod(ZipEntry.DEFLATED) ... } ... out.putNextEntry; out.closeEntry(); entry = zin.getNextEntry(); } // Close the streams zin.close(); out.close(); sourceApFile.delete(); destApFile.renameTo(sourceApFile); } }}

9、proguard去符号表和去除provided关键字

当然也可以在其它构建步骤中采用更高压缩率的方式来达到瘦身效果,例如采用7Zip压缩等等。

在Proguard保留了符号表的

-keepattributes SourceFile,LineNumberTable

PS:友盟上看推广渠道的bug要辛苦一点,手动上传mapping.txt了

去除provided关键字

provided ‘com.android.support:support-annotations:22.0.0’

本技巧的使用需要注意以下问题:

  • 如果音视频资源被压缩存放在APK中的话,在使用一些音频、视频API时尤其要注意,需要做好充分的测试。
  • resources.arsc文件最好不要压缩存储,如果压缩会影响一定的性能。
  • 如果想在Android
    6.0上开启android:extractNativeLibs=”false”的话,.so
    文件也不能被压缩,android:extractNativeLibs的使用姿势看这里:App
    Manifest — application。

10、表情包在线化,图标可以使用iconfont管理

如何优化classes.dex的大小呢?大体有如下套路:

11、全版本兼容的着色方案

  • 时刻保持良好的编程习惯和对包体积敏锐的嗅觉,去除重复或者不用的代码,慎用第三方库,选用体积小的第三方SDK等等。
  • 开启ProGuard来进行代码压缩,通过使用ProGuard来对代码进行混淆、优化、压缩等工作。

考虑着色方案主要目的是更方便支持多主题,减轻UI工作量,减少工程里一大堆selector文件等,然后才是,顺便的减小一下apk大小。

针对第一种套路,因各个公司的项目的差异,共性的东西较少,需要case by
case的分析,这里不做过多的介绍。

12、去除重复库、无用库

可以通过开启ProGuard来实现代码压缩,可以在build.gradle文件相应的构建类型中添加minifyEnabled
true。

13、使用更小的库

  • 请注意,代码压缩会拖慢构建速度,因此应该尽可能避免在调试构建中使用。不过一定要为用于测试的最终APK启用代码压缩,如果不能充分地自定义要保留的代码,可能会引入错误。

相关文章