唯有美食

不可辜负

温度与风度同在,它虽然地处边角、远离喧嚣,但是到处都满载着精彩,周围弥漫着优雅的闲情逸致。

Android性能优化之APK瘦身


  • 面试中面试官常常会问道有关性能优化的问题,而性能优化中,APK瘦身也是一个比较关键的知识点,经过查阅资料和汇总,集各位大神的文章于一文。


为什么APK要瘦身?APK越大,在下载安装过程中,他们耗费的流量会越多,安装等待时间也会越长;对于产品本身,意味着下载转化率会越低(因为竞品中,用户有更多机会选择那个体验最好,功能最多,性能最好,包最小的),所以apk的瘦身优化也很重要。

在Android Studio工具栏里,打开build–>Analyze APK, 选择要分析的APK包   可以看到占用空间的主要是代码、图片、资源和lib和assert文件,主要方向精简代码、压缩图片、去除无用的库、减少asserts里面文件。[AndroidStudio2.2.3之后支持]

使用一套资源

对于绝大对数APP来说,只需要取一套设计图就足够了。鉴于现在分辨率的趋势,建议取720p的资源,放到xhdpi目录。
相对于多套资源,只使用720P的一套资源,在视觉上差别不大,很多大公司的产品也是如此,但却能显著的减少资源占用大小,顺便也能减轻设计师的出图工作量了。

注意,这里不是说把不是xhdpi的目录都删除,而是强调保留一套设计资源就够了。

开启minifyEnabled混淆代码

在gradle使用minifyEnabled进行Proguard混淆的配置,可大大减小APP大小:

android {
    buildTypes {
        release {
            minifyEnabled true
        }
    }
}

在proguard中,是否保留符号表对APP的大小是有显著的影响的,可酌情不保留,但是建议尽量保留用于调试。参数:

-include {filename}    从给定的文件中读取配置参数   
-basedirectory {directoryname}    指定基础目录为以后相对的档案名称   
-injars {class_path}    指定要处理的应用程序jar,war,ear和目录   
-outjars {class_path}    指定处理完后要输出的jar,war,ear和目录的名称   
-libraryjars {classpath}    指定要处理的应用程序jar,war,ear和目录所需要的程序库文件   
-dontskipnonpubliclibraryclasses    指定不去忽略非公共的库类。   
-dontskipnonpubliclibraryclassmembers    指定不去忽略包可见的库类的成员。

保留选项

-keep {Modifier} {class_specification}    保护指定的类文件和类的成员   
-keepclassmembers {modifier} {class_specification}    保护指定类的成员,如果此类受到保护他们会保护的更好   
-keepclasseswithmembers {class_specification}    保护指定的类和类的成员,但条件是所有指定的类和类成员是要存在。   
-keepnames {class_specification}    保护指定的类和类的成员的名称(如果他们不会压缩步骤中删除)   
-keepclassmembernames {class_specification}    保护指定的类的成员的名称(如果他们不会压缩步骤中删除)   
-keepclasseswithmembernames {class_specification}    保护指定的类和类的成员的名称,如果所有指定的类成员出席(在压缩步骤之后)   
-printseeds {filename}    列出类和类的成员-keep选项的清单,标准输出到给定的文件  

压缩

-dontshrink    不压缩输入的类文件   
-printusage {filename}   
-whyareyoukeeping {class_specification}  

优化

-dontoptimize    不优化输入的类文件   
-assumenosideeffects {class_specification}    优化时假设指定的方法,没有任何副作用   
-allowaccessmodification    优化时允许访问并修改有修饰符的类和类的成员  

混淆

-dontobfuscate    不混淆输入的类文件   
-printmapping {filename}   
-applymapping {filename}    重用映射增加混淆   
-obfuscationdictionary {filename}    使用给定文件中的关键字作为要混淆方法的名称   
-overloadaggressively    混淆时应用侵入式重载   
-useuniqueclassmembernames    确定统一的混淆类的成员名称来增加混淆   
-flattenpackagehierarchy {package_name}    重新包装所有重命名的包并放在给定的单一包中   
-repackageclass {package_name}    重新包装所有重命名的类文件中放在给定的单一包中   
-dontusemixedcaseclassnames    混淆时不会产生形形色色的类名   
-keepattributes {attribute_name,...}    保护给定的可选属性,例如LineNumberTable, LocalVariableTable, SourceFile, Deprecated, Synthetic, Signature, and InnerClasses.  
-renamesourcefileattribute {string}    设置源文件中给定的字符串常量 

开启shrinkResources将无用的一些资源全部去除

在gradle使用shrinkResources去除无用资源,效果非常好。

android {
    buildTypes {
        release {
            shrinkResources true
        }
    }
}

清理无用资源、删除无用的语言资源

无用资源清理

版本迭代过程中,不但有废弃代码冗余,肯定会有无用的图片存在。
在build.gradle 里面配置shrinkResources true,在打包的时候会自动清除掉无用的资源,但经过实验发现打出的包并不会,而是会把部分无用资源用更小的东西代替掉。

注意,这里的“无用”是指调用图片的所有父级函数最终是废弃代码,而shrinkResources true 只能去除没有任何父函数调用的情况,真正起效果只能通过Android Studio自带的 “Remove Unused Resources”小插件来实现了,直接上图:

更人性化是该查找结果可以“一键删除”。

当然,可能图片是经过反射或字符拼接等方式获取,所以这个检测列表也不是全对,删除后很大概率编译失败或部分页面挂死、无图等问题,这个无解,工具还没智能到这个地步,你只能一遍又一遍“编译—解决部分问题—再编译再解决”

删除无用的语言资源
大部分应用其实并不需要支持几十种语言的国际化支持。还好强大的gradle支持语言的配置,比如国内应用只支持中文:

android {
    defaultConfig {
        resConfigs "zh"
    }
}

使用tinypng有损压缩

TinyPNG工具只支持上传PNG图片到官网上压缩,然后下载保存,在保持alpha通道的情况下对PNG的压缩可以达到1/3之内,而且用肉眼基本上分辨不出压缩的损失.
Tinypng的官方网站

使用jpg格式、使用webp格式

jpg格式:

如果对于非透明的大图,jpg将会比png的大小有显著的优势,虽然不是绝对的,但是通常会减小到一半都不止。
在启动页,活动页等之类的大图展示区采用jpg将是非常明智的选择。

webp格式:

webp支持透明度,压缩比比jpg更高但显示效果却不输于jpg,官方评测quality参数等于75均衡最佳。
相对于jpg、png,webp作为一种新的图片格式,限于android的支持情况暂时还没用在手机端广泛应用起来。从Android 4.0+开始原生支持,但是不支持包含透明度,直到Android 4.2.1+才支持显示含透明度的webp,使用的时候要特别注意。
官方介绍

覆盖第三库里的大图

有些第三库里引用了一些大图但是实际上并不会被我们用到,就可以考虑用1x1的透明图片覆盖。
你可能会有点不舒服,因为你的drawable下竟然包含了一些莫名其妙的名称的1x1图片…

缩小大图

如果经过上述步骤之后,你的工程里面还有一些大图,考虑是否有必要维持这样的大尺寸,是否能适当的缩小。
事实上,由于设计师出图的原因,我们拿到的很多图片完全可以适当的缩小而对视觉影响是极小的。

使用微信资源压缩打包工具

微信资源压缩打包工具通过短资源名称,采用7zip对APP进行极致压缩实现减小APP的目标,效果非常的好,强烈推荐。
建议开启7zip,注意白名单的配置,否则会导致有些资源找不到,官方已经发布AndResGuard到gradle中了,比较方便:

apply plugin: 'AndResGuard'
buildscript {
    dependencies {
        classpath 'com.tencent.mm:AndResGuard-gradle-plugin:1.1.7'
    }
}
andResGuard {
    mappingFile = null
    use7zip = true
    useSign = true
    keepRoot = false
    // add .R.drawable.icon into whitelist.
    // because the launcher will get thgge icon with his name
    def packageName = 
            whiteList = [//for your icon
    packageName + ".R.drawable.icon",//for fabric
            packageName + ".R.string.com.crashlytics.*",//for umeng update
            packageName + ".R.string.umeng*",
            packageName + ".R.string.UM*",
            packageName + ".R.string.tb_*",
            packageName + ".R.layout.umeng*",
            packageName + ".R.layout.tb_*",
            packageName + ".R.drawable.umeng*",
            packageName + ".R.drawable.tb_*",
            packageName + ".R.anim.umeng*",
            packageName + ".R.color.umeng*",
            packageName + ".R.color.tb_*",
            packageName + ".R.style.*UM*",
            packageName + ".R.style.umeng*",
            packageName + ".R.id.umeng*"
    ]
    compressFilePattern = ["*.png","*.jpg","*.jpeg","*.gif","resources.arsc"
    ]
    sevenzip {
        artifact = 'com.tencent.mm:SevenZip:1.1.7'//path = "/usr/local/bin/7za"
    }
}

会生成一个andresguard/resguard的Task,自动读取release签名进行重新混淆打包。

可使用矢量图

矢量图是由点与线组成,和位图不一样,它再放大也能保持清晰度,而且使用矢量图比位图设计方案能节约30~40%的空间,现在谷歌一直在强调扁平化方式,矢量图可很好的契合该设计理念。

  • 优势
    (1)占用存储空间小
    (2) 无极拉伸不会出现锯齿,可以照顾不同尺寸的机型
    (3)Android Studio自带很多资源,减小UI工作量

  • 劣势
    (1) 只支持5.0及以上系统
    (2) 与位图相比多了一层计算,需消耗更多性能
    (3) 不支持.9图
    (4)不适合表现真实照片和复杂图形,一般使用在简单的icon和动画上

使用shape背景

在扁平化盛行的当下,很多纯色的渐变的圆角的图片都可以用shape实现,代码灵活可控,省去了大量的背景图片

使用selector文件着色方案

相信你的工程里也有很多selector文件,也有很多相似的图片只是颜色不同,通过着色方案我们能大大减轻这样的工作量,减少这样的文件。
借助于android support库可实现一个全版本兼容的着色方案,参考代码:
DrawableLess.java

精简SO

删除armable-v7包下的so

基本上armable的so也是兼容armable-v7的,armable-v7a的库会对图形渲染方面有很大的改进,如果没有这方面的要求,可以精简。
这里不排除有极少数设备会Crash,可能和不同的so有一定的关系,请大家务必测试周全后再发布。

删除x86包下的so

与使用webp格式不同的是,x86包下的so在x86型号的手机是需要的,如果产品没用这方面的要求也可以精简。
建议实际工作的配置是只保留armable、armable-x86下的so文件,算是一个折中的方案。

使用provided编译

对于一些库是按照需要动态的加载,可能在某些版本并不需要,但是代码又不方便去除否则会编译不过。

使用provided可以保证代码编译通过,但是实际打包中并不引用此第三方库,实现了控制APP大小的目标。

但是也同时就需要开发者自己判断不引用这个第三方库时就不要执行到相关的代码,避免APP崩溃。

在线化素材库

如果你的APP支持素材库(比如聊天表情库)的话,考虑在线加载模式,因为往往素材库都有不小的体积。

这一步需要开发者实现在线加载,一方面增加代码的复杂度,一方面提高了APP的流量消耗,建议酌情选择。

避免重复库

避免重复库看上去是理所当然的,但是秘密总是藏的很深,一定要当心你引用的第三方库又引用了哪个第三方库,这就很容易出现功能重复的库了,比如使用了两个图片加载库:Glide和Picasso。

通过查看exploded-aar目录和External Libraries或者反编译生成的APK,尽量避免重复库的大小,减小APP大小。

清理第三方库和冗余代码

版本迭代过程中,因为删减功能经常有冗余代码和第三方库留下,这或多或少都会增加包体,这种情况没有捷径,只能每个文件查找,这是苦力活。

还有要查看第三方库有没可能精简,比如谷歌分基础、广告和分析包,网络库、supportv4等,这个就具体情况具体分析,不多阐述。

支持插件化

插件化技术支持动态的加载代码和动态的加载资源,把APP的一部分分离出来了,对于业务庞大的项目来说非常有用,极大的分解了APP大小。

因为插件化技术需要一定的技术保障和服务端系统支持,有一定的风险,如无必要(比如一些小型项目,也没什么扩展业务)就不需要了,建议酌情选择。

Facebook的redex优化字节码

redex是facebook发布的一款android字节码的优化工具,需要按照说明文档自行配置一下。

redex input.apk 
    -o output.apk --sign 
    -s <KEYSTORE> -a <KEYALIAS> -p <KEYPASS>

据反应redex后会有崩溃的现象,这个要留意一下。但是它的压缩效果还是很可观的。

redex详情

点击蓝字关注我哦

androidstudio打包apk 文件_每天一个小知识——APK瘦身相关推荐

  1. newduba首页怎么去掉_京喜小程序首页瘦身实践

    前言 在 web 开发场景,减少代码体积虽然是性能优化的一个方向,还没到锱铢必较的程度.但是在小程序场景,由于代码包上传阶段限制了主包 2M 和总包 16M(近期微信官方正在内测将总包上限调整至 20 ...

  2. dmsetup remove_all 这命令干啥的_分一个小知识,服务器上的一个解压与压缩文件的命令....

    在服务器上对文件做解压操作,是一件非常常见的操作,如安装软件就有很多是要用的到这个操作的.去官网下载一个压缩包,然后解压,编译,再安装.当然网上是能找到相应的命令操作.但是每次都要去找命令,就算记住了 ...

  3. 关于手动注册dll文件遇到的一个小问题

    手动注册dll文件遇到的一个小问题里 由于安装一些系统的需要,要手动注册dll文件. 我采取的方式是以管理员身份进入命令控制台,执行 regsvr32 dll文件路径 可是一直提示我找不到dll文件( ...

  4. 计算机教室如何防火,2020校园防火安全小知识_消防安全小知识顺口溜

    消防安全知识必须人人懂,火灾隐患无处不在,稍不注意就容易引发大祸.所以,我们要从身边做起,从自己做起.以下是小编整理了关于2020校园防火安全小知识_消防安全小知识顺口溜,希望你喜欢. 校园防火安全小 ...

  5. android 环境配置和安装, Android系统包说明,基本控件,常用代码,ADB 命令行,APK文件确解,小技艺,...

    一.             环境配置和安装(Android2.2) 参考文章:这里 1.1     JDK 1.2     SDK 下载地址:http://dl.google.com/android ...

  6. java文件打包jar文件_把java文件打包成.jar (jar命令详解)

    把java文件打包成.jar (jar命令详解) 先打开命令提示符(win2000或在运行框里执行cmd命令,win98为DOS提示符),输入jar Chelp,然后回车(如果你盘上已经有了jdk1. ...

  7. apktoolkit apk反编译没有文件_[工具] Mac下一键APK逆向环境

    安装apktool和dex2jar,jd-gui homebrew安装: brew install apktool brew install dex2jar JD-GUI去http://jd.beno ...

  8. webpack打包样式资源_使用loader去打包css文件_打包less文件---webpack工作笔记004

    然后我们再来看看,怎么用webpack打包css资源文件, 因为我们知道webpack可以直接处理js,json文件,但是不能直接处理css文件,img文件对吧.. 我们现在,通过webpack的组件 ...

  9. formdata上传文件_封装一个多文件断点续传、分片上传、秒传、重试机制的组件...

    本文为:多文件断点续传.分片上传.秒传.重试机制 的更新版,若想看初始版本的实现,请查看该文章. 凡是要知其然知其所以然 文件上传相信很多朋友都有遇到过,那或许你也遇到过当上传大文件时,上传时间较长, ...

最新文章

  1. 皮一皮:这小伙子怎么能掌握这么多高深技术!!!
  2. 几款开源的数据挖掘工具
  3. jvm二:类加载,连接,初始化
  4. C语言 | 用51单片机实现公历与农历星期的转换(完整源代码)
  5. 超大数据量存储常用数据库分表分库算法总结
  6. GC之G1垃圾收集器
  7. Linux安装ntp同步时间
  8. LeetCode 404. 左叶子之和
  9. bk3432开发的应用实例_SpringCloud应用在Kubernetes上的最佳实践—诊断(线上联调)...
  10. ASP.NET站点构建之减少不必要的请求
  11. mysql命令单词_mysql命令大全
  12. Artifacts Gallery - Seahorse Collector, The
  13. php留言板上传图片,thinkphp3.2.3留言板带管理没有后台ajax上传图片功能
  14. Visual Studio中从应用程序中调试SQL脚本
  15. 计算机中图分类法,计算机中图分类号.doc
  16. 免费在线pdf转word
  17. 把手机当作电脑显示器指导参考
  18. 求伯君,一个你必须知道的程序员
  19. 初识micro:bit
  20. 岭南学院python课程作业5-2

热门文章

  1. login-webflow.xml初步分析
  2. 2019秋季学习计划
  3. HBase 学习(三) JavaAPI的使用
  4. NVisionXR_iOS教程十二 —— 多图识别
  5. python-打开网页
  6. 带线程池的socket客户端与服务端
  7. 百度地图开发的时候遇到的问题(二)
  8. sql 删除重复记录
  9. 性能测试搭建Jmeter分布式压测与监控
  10. 集合框架(List、Collection、迭代器)