Android Develop:减小APK大小

用户通常会避免下载过大的app,尤其是在新兴市场,那里的设备网络连接2G和3G往往参差不齐,或者以按流量收费的形式。这篇文档描述了如何减少你的app的APK大小,它会使得更多的用户下载你的app; 


理解APK的结构
 
-------------------------------------------------------------------------------- 

在讨论如何减少你的app的大小之前,理解一个app的apk结构是非常有用的。一个APK文件是一个zip压缩文件,它包含你的app的所有文件。这些文件包含Java类文件,资源文件,和一个编译资源的文件。 

一个APK包含下面的目录: 

  • META-INF/:包含CERT.SF和CERT.RSA签名文件,和MANIFEST.MF清单文件; 

  • assets/:包含app的assets,app可以使用一个AssetManager对象获取它; 

  • res/:包含没有编译到resources.arsc中的资源; 

  • lib/:包含为特定处理器编译的代码。这个目录包含不同平台类型的子目录,如armeabi,armeabi-v7a,arm64-v8a,x86,x86_64和mips; 

一个APK也包含下面的文件。在它们里面,只有AndroidManifest.xml是必须的。 

  • resources.arsc:包含被编译的资源。这个文件包含来自res/values目录下所有配置的XML内容。打包工具提取XML内容,将它们编译为二进制的形式,并且打包。这些内容包含语言字符串和样式,和在resources.arsc文件不包含的内容的路径,如布局文件和图片; 

  • Classes.dex:包含被编译的类,以Dalvik/ART虚拟机能理解的dex文件格式; 

  • AndroidManifest.xml:包含核心的Android清单文件。这个文件罗列了名称,版本,访问权限,和app引用的库文件。这个文件使用Android的二进制XML格式; 


减少资源数目和大小
 
-------------------------------------------------------------------------------- 

你的apk的大小对你的app的加载速度,使用内存大小和消耗功率多少有一定影响。使你的apk变小的一种简单方式就是减少它包含资源的数目和大小。尤其是,你要移除你的app不再使用的资源,并且你可以使用Drawable对象代替图片文件。这个章节讨论了这些,和其它一些能减少你的app资源的方法,来减少你的APK的整体大小。
 

移除不使用的资源 

在Android Studio中的一个静态代码工具lint,检测在你的/res目录下代码没有引用的资源。当lint工具在你的项目中发现一个潜在的未使用的资源,它会打印一条如下示例的消息。 

res/layout/preferences.xml: Warning: The resource R.layout.preferences appears 
    to be unused [UnusedResources] 

注意:lint工具没有扫描assets/目录,assets通过反射引用,或者你的app链接的库文件。另外,它不会移除资源;它仅仅是提醒你它们的存在; 

你添加到你的代码中的库可能包含未使用的资源。如果你在你的app的build.gradle文件中启动shrinkResourcesGradle,它能自动替你删除这些资源。 

android{ 
   // Other settings 
 
    buildTypes{ 
        release{ 
            minifyEnabledtrue 
            shrinkResourcestrue 
            proguardFiles getDefaultProguardFile('proguard-android.txt'),'proguard-rules.pro' 
       } 
   } 
} 

为了使用shrinkResources,你必须启动代码压缩。在构建的过程中,首先ProGuard移除了没有使用的代码,但是还存在没有使用的资源。然后Gradle会移除没有使用的资源。 

更多关于ProGuard的信息,和其它Android Studios帮助你减少APK大小的方式,查阅Shrink Your Code and Resources。 

在Android Gradle插件0.7或者更高版本,你可以声明你的app支持该配置。Gradle通过使用resConfig和resConfigs flavor和defaultConfig向构建系统传递信息。构建系统然后禁止在APK中出现其它来源的资源,不支持的配置,减小APK的大小。更多的关于这个功能的信息,请查阅Remove unused alternative resources。 


减少库中使用的资源
 

在开发Android app的时候,你通常会使用扩展库来提升你的app的可用性和多功能性。例如,你可能引用Android Support Library来提升在老设备上的用户体验,或者你可能使用Google Play Services来检索自动翻译你的app中的文本。 

如果一个库针对server和desktop设计,它会包含许多你的app不需要的对象和方法。为了仅仅包含你的app需要的库的这部分,如果允许你修改这个库,你可以编辑这个库的文件。你也可以使用一个可选的,针对移动端设计的库来为你的app添加具体的功能。 

注意:ProGuard能清除导入的库不必要的代码,但是它不能移除库庞大的内部依赖。 


只支持特定的密度
 

Android支持一个非常大的设备集合,包括各种屏幕密度。在Android4.4(API Level 19)和更高版本,framework支持各种各样的密度:ldpi,mdpi,tvdpi,xhdpi,xxhdpi和xxxdpi。尽管Android支持所有这些密度,你不需要为每个密度制作资源。 

如果你知道你的用户只有一小部分使用特定密度,考虑是否需要将这些密度捆绑你的app中。如果你不包含某一指定屏幕密度的资源,Android自动缩放存在的,原来为其它屏幕密度设计的资源。 

如果你的app仅仅需要被缩放的图片,你可以通过在drawable-nodpi/目录中保存图片的一个变体,来节省更多的空间。我们要求任何app至少包含一个xxxhdpi图片变体; 

更多关于屏幕密度的信息,请查阅Screen Sizes and Densities。 


减少动画帧
 

帧动画可以彻底减少你的APK的大小。下图展示了一个帧动画分离成多张图片保存在目录中的例子。每个图片在动画中是为一帧。 

对于你添加到动画中的每一帧,你增加了在APK中图片的数量。如下图,在app中这个图片动画30帧。如果图片动画用仅仅15帧代替,这个动画仅仅需要一半数量的帧。 

图像


使用Drawable对象
 

一些图片不需要一个静态的图片资源;framework能运行时动态的绘制图片来替代。Drawable对象(在XML中的<shape>)占用你的APK较少的空间。另外,XML Drawable对象能产生符合材料设计指南的纯色图片。 


重用资源
 

你可以为一个图片的变种使用一个单独资源,例如同一个图片的着色,阴影,或者旋转版本。我们推荐使用,然而你视运行时需要,重用同一个资源集合和定制它们。 

Android提供了多种方式来改变asset的颜色,在Android5.0(API level 21)或者更高版本,使用android:tint和tintMode的任意一个。对于更低版本的平台,使用ColorFilter类。 

你也可以省略资源,当它等同于仅仅将其它资源旋转的时候。下面的代码片段提供了一个示例,通过对原来图片简单的180度旋转,将一个“展开”箭头转换为“收起”箭头。 

<?xml version="1.0"encoding="utf-8"?> 
<rotatexmlns: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"/> 


代码中渲染
 

你也可以通过代码来渲染你的图片来减少你的APK的大小。代码渲染减少了空间,因为不在你的APK中保存图片文件。 


处理PNG文件
 

appt工具可以在构建过程中,使用无损压缩的方式优化放在/res/drawable目录下的图片资源。例如,aapt工具能将一个不需要256颜色真色彩的PNG转化为8-bit调色板的PNG。这样做的结果是一个相同质量的图片但是消耗更小的内存。 

记住aapt有如下限制: 

  • aapt工具不会压缩在asset/目录下的PNG文件; 

  • aapt工具只优化使用256或者更少的颜色的图片文件; 

  • aapt工具可能会增加已经被压缩过的PNG图片。为了防止这个,你可以在Gradle中使用cruncherEnabled标识来取消PNG图片的优化过程; 

aaptOptions{ 
    cruncherEnabled=false 
} 


压缩PNG和JPEG文件
 

你可以使用如pngcrush,pngquant或者aopflipng来减小PNG文件的大小,并且不降低图片的质量。所有的这些工具都可以减少图片的大小并且保持图片的质量。 

pngcrush工具尤其有效:这个工具迭代PNG过滤器和zlib参数,使用每个过滤器组合和参数来压缩图片。然后选择最小压缩配置输出。 

对于JPEG文件,你可以使用如packJPG工具来将JPEG文件压缩为更紧凑格式。 


使用webp文件格式
 

你可以使用WebP文件格式,代替使用PNG或者JPEG文件。Webp格式支持有损压缩(像JPEG)和透明度(如PNG),但比JPEG或PNG的压缩更好。 

使用WebP文件格式有几个显著的缺点。首先,在低于Android3.2系统版本(API level 13)不支持Webp格式。其次,系统解码WebP相比PNG图片会消耗了更多的时间。 

注意:Google Play仅仅接受使用PNG格式图标的APK。如果你想通过Google Play发布你的app的话,你不能使用其它文件格式如JPEG或者WebP用户app的图标。 


使用矢量图
 

你可以使用矢量图来创建独立于分辨率的图标和其它可扩展的媒体。使用这些图标可以大大减少你的apk。矢量图在Android中以VectorDrawable对象代表。使用VectorDrawable对象,一个100-byte文件可以生成一个屏幕大小清晰图像。 

然而,每个VectorDrawable对象的渲染明显的消耗了系统时间,并且更大的图片需要更长的时间来展示在屏幕上。因此仅仅在显示小的图片的时候考虑使用矢量图。 

更新关于使用VectorDrawable对象的信息,请查阅Working With Drawables。 


减少Native和Java代码
 
-------------------------------------------------------------------------------- 

这里有几种你可以用来减少app的Java和native代码大小的方式。 


删除不必要生成的代码
 

一定要明白任何自动生成代码的足迹。例如,许多协议缓冲工具生成过多的方法和类,它会两三倍的增加你的app的大小。 


移除枚举
 

一个枚举会增加你的app的class.dex文件大约1.0到1.4K的大小。对于复杂的系统或者共享库这种情况会更加明显。如果可能的话,考虑使用@IntDef和ProGuard来剥离枚举,并转换成Integer。这种类型转换保留了所有枚举的安全效益。 


减少Native库的大小
 

如果你的app使用了native代码和Android NDK,你也可以通过优化你的代码减少你的app的大小。两个有用的技术是移除Debug符号和避免取native库。 

移除Debug符号 

使用debug符号意味着着你的应用程序正在开发并且持续需要debug。使用在Android NDK中提供的arm-dabi-strip工具,来移除不必要的native库的debug符号。在这之后,你可以编译你的release构建。 

避免提取Native库 

保存APK中解压的.so文件,并且设置在你的应用清单文件中<application>元素中的android:extractNativeLibs标识为false。这将会阻止PackageManager在安装的过程中从APK中复制出.so文件到文件系统中,并且将增加使得你的app的增量更新更小的好处。 


维护多个精简的APK
 

-------------------------------------------------------------------------------- 

你的apk包含了用户下载但是从来不使用的内容,例如区域的或者语言信息。为了给你的用户提供一个最小的下载,你可以以屏幕尺寸或者GPU类型划分,将你的app分给为多个APK。 

当一个用户下载你的应用的时候,他们的设备根据设备的功能和配置获取对应的APK。这种方式下,设备不会获取它没有功能的资源。例如,如果一个用户有一个hdpi的设备,他们不需要xxxhdpi资源,你可能为了更高的密度设备显示而包含。 

更多信息,查阅Configure APK Splits和Maintaining MUltiple APKs。 


文档url:https://developer.android.com/topic/performance/reduce-apk-size.html

新技术,新未来!欢迎大家关注 “1024工场”微信服务号 ,时刻关注我们的最新的技术讯息! (甭客气!尽情的扫描或者长按!)

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值