Android性能优化-减小APK大小
前言
用户通常会避免下载比较大的应用,特别是连接到2G和3G网络,或者按流量收费的设备。这篇文章描述了如何减小apk的大小,帮助你让更多的用户下载你的app。
一 理解APK的结构
在讨论如何减小apk大小之前,理解apk的结构很有必要。一个APK文件包括一个ZIP 文件,该ZIP包含app的所有文件。包括java 字节码文件,资源文件和一个包含了编译后的资源文件。APK包含以下目录:
META-INF/
:包含了CERT.SF
和CERT.RSA
签名文件, 以及MANIFEST.MF
manifest 文件.assets/
: 包含了app的assets,app可以通过AssetManager
对象获取到这些资源res/
: 包含了那些没有被编译到resources.arsc
的资源lib/
: 包含了用于软件处理器的编译代码,该目录包含一个子目录,针对不同平台:armeabi
,armeabi-v7a
,arm64-v8a
,x86
,x86_64
, andmips
.
一个APK也包含了下面的文件,但只有 AndroidManifest.xml
是强制性的
resources.arsc
:包含了编译后的资源。该文件包含了
res/values/
文件夹下的所有XML内容。打包工具抽取了XML内容,将它编译成二进制格式,并且进行了压缩。该内容包括language strings和styles,以及未直接包含在resources.arsc
文件中的内容路径。比如layout文件和图片。classes.dex
:包含可以被Dalvik/ART 识别,以dex文件格式编译后的代码
AndroidManifest.xml
:包含了Android核心mainfest文件。该文件罗列了app名字,版本,访问权限,和引用的library文件。该文件采用二进制XML格式。
二 减少资源的数量和大小
APK的大小对app的加载速度以及内存的使用和电量消耗都有影响。一种减小APK大小的最简单方法就是减少APK的资源文件数量和大小。也可以移除那些app不再使用的资源,或者使用可扩展的 Drawable
对象替代图片文件。这部分讨论了这些方法,以及其它几种减小app资源以便最终达到减小APK总体大小的其它方法。
移除无用资源
使用 lint
工具,AndroidStudio中的一个静态的代码分析工具。可以检测res/
目录下那些没有被引用的资源. 当 lint
工具发现了项目中潜在的无用资源,就会打印类似如下的信息:
res/layout/preferences.xml: Warning: The resource R.layout.preferences appears
to be unused [UnusedResources]
|
注意: lint
工具不能够扫描assets/
目录, assets 资源是通过反射的方式引用的,或者app中引用的其它library 文件。但lint并不会移除资源,它只会提示它们的存在。
你引入的Libraries有可能引入了无用的资源。Gradle可以通过在 build.gradle
文件中开启shrinkResources
来帮你自动的移除这些资源:
android {
// Other settings
buildTypes {
release {
minifyEnabled true
shrinkResources true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
|
为了使用 shrinkResources
,你应该开启code shrinking,在build处理期间, ProGuard 首先会移除无用的代码但是会保留无用的资源。之后Gradle会移除无用的资源。
关于ProGuard和使用Android Studio帮助你减小APK大小的更多信息,可以参考 Shrink Your Code and Resources.
在Android Gradle Plugin 0.7以及更高的版本中,你可以声明app支持的配置。Gradle通过 resConfig
和 resConfigs
flavors 和 defaultConfig
选项把这些信息传递给构建系统。构建系统会阻止来自其它不受支持的资源出现在APK中,从而减少APK的大小。更多信息可以参考 Remove unused alternative resources。
最小化使用Libraries中的资源
在开发App的时候,通常会使用外部libraries去提升app的可用性和功能扩展。比如,你可能会引用Android Support Library去提升老设备的用户体验。或者使用 Google Play Services 为app提供自动翻译。
如果一个library被设计用于桌面服务,那么就可能包含很多app不需要的对象和方法。为了只保留library中app需要的代码,如果license许可的话,你需要编辑library文件。你也可以使用一个移动端友好的替代库。
注意: ProGuard 可以清除一些从library中导入的不需要的代码。但是不会移除一个 library的内部依赖。
只支持特定的分辨率
Android支持非常大的设备集,包括各种屏幕密度。 在Android 4.4(API级别19)及更高版本中,框架支持各种分辨率:ldpi,mdpi,tvdpi,hdpi,xhdpi,xxhdpi和xxxhdpi。 虽然Android支持所有这些分辨率,但你不需要导出光栅化资源到每种分辨率。
如果你知道只有一小部分用户使用特定分辨率的设备,请考虑是否需要支持这些分辨率。 如果你不包括特定屏幕密度的资源,Android会自动缩放最初为其他屏幕密度设计的现有资源。
如果您的应用只需要缩放的图片,您可以通过在drawable-nodpi /中使用图片的单个版本来节省更多空间。 我们建议每个应用至少包含一个xxhdpi图片版本。
更多屏幕分辨率的信息,可以参考 Screen Sizes and Densities.
减少动画帧数
逐帧动画可能会大幅增加APK的大小。 图1中展示了一个帧动画被分成多个PNG文件的情况。 每个图像是动画中的一帧。
对于添加到动画中的每一帧,都会增加APK中存储的图片数量。 在图1中,图像在应用程序中以30 FPS动画。 如果图像仅以15FPS动画化,则动画将仅需要所需帧的数目的一半。
Use Drawable Objects
一些图像不需要静态图像资源; 框架可以在运行时动态地绘制图像。 相反,Drawable对象(XML中的)可能只会占用APK中的一小部分空间。 此外,XML形式的Drawable对象可以生成符合MaterialDesign指南的单色图像。
减少资源
你可能为同一种图像的不同形式都提供了独立的资源,例如同一图像的有色,阴影或旋转版本。 但是,我们建议你重复使用相同的资源,在运行时根据需要进行自定义。
Android提供了几个工具来更改资源的颜色,可以在Android 5.0(API级别21)以及更高版本上使用android:tint和tintMode属性。 对于较低版本的平台,请使用ColorFilter类。
您还可以节约那些只是某一种资源做了旋转的资源。 以下代码段提供了一个例子,通过简单地将原始图像旋转180度,将“展开”箭头转换为“折叠”箭头图标:
<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="@drawable/ic_arrow_expand"
android:fromDegrees="180"
android:pivotX="50%"
android:pivotY="50%"
android:toDegrees="180" />
|
从代码中渲染
You can also reduce your APK size by procedurally rendering your images. Procedural rendering frees up space because you no longer store an image file in your APK.
你也可以通过程序对图像渲染来减少APK大小。 通过程序渲染可以节约空间是因为不需要在APK中存储图像文件。
压缩PNG文件
aapt工具可以在构建过程期间优化放置在res / drawable /中的图像资源,以及无损压缩。 例如,aapt工具可以将不需要多于256种颜色的真彩色PNG转换为具有调色板的8位PNG。 这样做会产生质量相同但占用内存较小的映像。
但请记得aapt有以下限制:
- aapt工具不会收缩asset/文件夹中包含的PNG文件。
- 图像文件需要使用256个或更少的颜色的aapt工具来优化它们。
- aapt工具可能会填充已压缩的PNG文件。 为了防止这种情况,您可以在Gradle中使用cruncherEnabled标志为PNG文件禁用此过程:
aaptOptions {
cruncherEnabled = false
}
|
压缩PNG和JPG文件
你可以使用像 pngcrush, pngquant, 或zopflipng等工具来减少PNG文件大小,而不会损失图像质量。 所有这些工具都可以减少PNG文件大小,同时保持图像质量。
pngcrush工具特别有效:此工具在PNG过滤器和zlib(Deflate)参数上迭代,使用每个过滤器和参数的组合来压缩图像。 然后选择产生最小压缩输出的配置。
对于JPEG文件,您可以使用 packJPG 等工具将JPEG文件压缩为更紧凑的形式。
使用WebP 文件格式
除了使用PNG或JPEG文件,你还可以使用WebP的图像文件。 WebP格式提供有损压缩(如JPEG)和透明度(如PNG),但可以提供比JPEG或PNG更好的压缩。
但是,使用WebP文件格式有一些显着的缺点。 首先,在低于Android 3.2(API级别13)的平台版本中不支持WebP。 第二,系统解码WebP比PNG文件需要更长的时间。
注意:Google Play只接受使用PNG格式的图标。 如果你打算通过Google Play发布应用,图标就不能使用其他文件格式(如JPEG或WebP)。
使用矢量图形
你可以使用矢量图形创建分辨率独立的图标和其他可伸缩媒体。 使用这些图形可以大大减少APK体积。 矢量图像在Android中表示为VectorDrawable对象。 使用VectorDrawable对象,100字节的文件可以生成屏幕大小的清晰图像。
然而,系统渲染每个VectorDrawable对象需要大量的时间,较大的图像则需要更长的时间才能出现在屏幕上。 因此,只有在显示小图像时才考虑使用这些矢量图形。
有关使用VectorDrawable对象的更多信息,请参考 Working with Drawables.
三 减少Native和Java代码
删除不必要的生成代码
确保你能够理解那些任何自动生成的代码部分。 例如,许多协议缓冲工具生成过多的方法和类,可以使应用程序的大小增加一倍或两倍。
删除枚举
单个枚举可能为应用程序的classes.dex文件添加大小为1.0到1.4 KB的大小。 对于复杂的系统或者共享库,这种增加可能比较快迅速。 如果可能,请考虑使用@IntDef注解和ProGuard 来除去枚举并将它们转换为整数。 这种类型转换保留了枚举的所有类型安全的好处。
减少本地二进制文件的大小
如果你的应用使用本地代码和Android NDK,你还可以通过优化这些代码来减小应用的大小。 两个有用的方式是删除debug标记,不提取本地库。
删除Debug符号
如果你的应用程序正在开发中并仍需要调试,那么使用debug标记很有意义。 使用Android NDK中提供的 arm-eabi-strip
工具从本地库中删除不必要的调试标记。 之后,再编译release版本。
避免提取本地库
将.so文件存储在APK中未压缩的文件中,并在应用清单的``元素中将android:extractNativeLibs标记设置为false。 这将防止PackageManager在安装过程中将.so文件从APK复制到文件系统,并且有一个额外的好处,会让app的差分更新变得更小。
四 维护多个精简版APK
你的APK可能包含用户下载但从不使用的内容,例如区域或语言信息。 为了让用户提供最小化的下载,你可以将应用细分为多个APK,并根据屏幕尺寸或GPU纹理支持等因素进行区分。
当用户下载您的应用时,其设备会根据设备的功能和设置接收正确的APK。 这样,设备不会接收设备没有的功能的资源。 例如,如果用户拥有的是hdpi设备,那么他们不需要你为更高分辨率设备提供的xxxhdpi资源。
更多信息请参考Configure APK Splits and Maintaining Multiple APKs.
来源:http://www.lightskystreet.com/2016/10/17/android-optimize-apk/
Android性能优化-减小APK大小的更多相关文章
- 程序性能优化之APK大小优化(六)上
阿里P7移动互联网架构师进阶视频(每日更新中)免费学习请点击:https://space.bilibili.com/474380680 本篇文章将继续从APK瘦身来介绍APK大小优化:文章主要内容从理 ...
- 程序性能优化之APK大小优化(六)下篇
阿里P7移动互联网架构师进阶视频(每日更新中)免费学习请点击:https://space.bilibili.com/474380680 本篇文章将继续从微信资源混淆AndResGuard原理来介绍AP ...
- Android性能优化-减小图片下载大小
原文链接 https://developer.android.com/topic/performance/network-xfer.html 内容概要 理解图片的格式 PNG JPG WebP 如何选 ...
- Android性能优化系列之apk瘦身
Android性能优化系列之布局优化 Android性能优化系列之内存优化 为什么APK要瘦身.APK越大,在下载安装过程中.他们耗费的流量会越多,安装等待时间也会越长:对于产品本身,意味着下载转化率 ...
- android 性能优化
本章介绍android高级开发中,对于性能方面的处理.主要包括电量,视图,内存三个性能方面的知识点. 1.视图性能 (1)Overdraw简介 Overdraw就是过度绘制,是指在一帧的时间内(16. ...
- Android 性能优化之工具和优化点总结
Android性能优化学习 最近公司主抓性能优化工作,借此春风也学习到了许多Android性能优化方面的知识.由于组内队友的给力,优化的成果也是比较喜人.同时也学习和实践了不少知识,特此记录. 1.性 ...
- 【腾讯Bugly干货分享】Android性能优化典范——第6季
本文来自于腾讯bugly开发者社区,非经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/580d91208d80e49771f0a07c 导语 这里是Android性能优 ...
- 【转】Android性能优化之布局优化篇
转自:http://blog.csdn.net/feiduclear_up/article/details/46670433 Android性能优化之布局优化篇 分类: andorid 开发2015 ...
- Android性能优化典范(二)
Google前几天刚发布了Android性能优化典范第2季的课程,一共20个短视频,包括的内容大致有:电量优化,网络优化,Wear上如何做优化,使用对象池来提高效率,LRU Cache,Bitmap的 ...
随机推荐
- hdu4768二分答案
/* 如果发的传单是偶数,那么所有人都收到双数张. 仅考虑发了单数张传单,二分答案x,如果x左边是偶数,那么答案在右侧,如果x左边是奇数,那么答案在左侧 */ #include<iostream ...
- hdu1556 树状数组区间更新单点查询板子
就是裸的区间更新: 相对于直观的线段树的区间更新,树状数组的区间更新原理不太相同:由于数组中的一个结点控制的是一块区间,当遇到更新[l,r]时,先将所有能控制到 l 的结点给更新了,这样一来就是一下子 ...
- 【HTTP】 Fiddler简介
1.为什么是Fiddler? 抓包工具有很多,小到最常用的web调试工具firebug,达到通用的强大的抓包工具wireshark.为什么使用fiddler?原因如下: a.Firebug虽然可以抓包 ...
- python 全栈开发,Day127(app端内容播放,web端的玩具,app通过websocket远程遥控玩具播放内容,玩具管理页面)
昨日内容回顾 1. 小爬爬 内容采集 XMLY 的 儿童频道 requests 2. 登陆 注册 自动登陆 退出 mui.post("请求地址",{数据},function(){} ...
- 使用vmware提示无法打开内核设备 \\.\Global\vmx86: 系统找不到指定的文件
问题描述 打开虚拟机时候提示 “vmware没有正常关闭,再次打开使用时蓝屏,在安全模式下再次打开不会蓝屏,但提示“无法打开内核设备 \\.\Global\vmx86: 系统找不到指定的文件,你想要安 ...
- poj 3415
对拍没错..莫名wa了 利用容斥求每个串的重复子串 其实就是找到每个元素能扩展到的最大元素 即(rr-i)*(i-lr)*(w[i]-kk) 就可以了 然后处理这个先离散化再搞 另外是x y要清空 # ...
- jQuery如何退出each循环 和如何退出function函数
1.在函数内部使用return false是跳出function; 2.在each的回调函数中使用return false,是跳出each循环;return true 进入下一个循环: 3.break ...
- java中对于二位数组的简单操作,进而可以递推复杂操作
1.程序 2.结果 3.内循环的次数 arr[x].length
- mybatis DATE_FORMAT 格式化时间输出
参考:http://www.cnblogs.com/yangy608/p/3950095.html 一.在oracle中,当想把字符串为‘2011-09-20 08:30:45’的格式转化为日期格式, ...
- NPM 上传自己的包
NPM 上传自己的包 项目中经常 npm install,npm init啥的,那么如何上传自己的包到npm上呢. 注册账号 NPM官网 本地弄一个包 创建npm_test 文件夹 注:不能够有一些特 ...