相关文章推荐
寂寞的杯子  ·  opengl ...·  1 年前    · 
谦虚好学的毛衣  ·  How to round up ...·  1 年前    · 
减少APK的大小,Android官方这样说

减少APK的大小,Android官方这样说

前言:最近项目终于到了收尾上线阶段,由于引用了不少第三方的框架和SDK,导致APK非常的大。强迫症犯了,就想减小APK的大小。到处搜索一下各路大神的方法。还是觉得无论从原理上还是具体做法上都是官方的比较全面。所以就翻译了一下,分享出来。主要是用Google Translate,然后自己稍微按照中文逻辑修了一下。如有不妥的地方,请多提意见。(PS:另外还碰到了传奇的65535方法数这个大坑,后面再写这个。文中有些超链接可能需要梯子)

Android官网链接: Reduce APK Size
用户经常会避免下载看起来过大的应用程序,特别是在新兴市场,设备连接到常见的2G和3G网络或者使用按字节付费的网络。本文介绍如何减少应用程序的APK大小,让更多使用者下载你的应用程序。

一、了解APK结构

在讨论如何缩小应用程序的大小之前,先了解应用程序APK的结构,是有帮助的。APK文件包含ZIP文件,其中包含构成应用程序的所有文件。这些文件包括Java类文件,资源文件和已编译资源的文件。
APK包含以下目录:

  • META-INF/:包含CERT.SF和CERT.RSA签名文件,以及MANIFEST.MF清单文件。
  • assets/:包含应用程序的资源,应用程序可以使用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清单文件。此文件列出应用程序的名称,版本,访问权限和引用的库文件。该文件使用Android的二进制XML格式。

二、减少资源数量和大小

APK的大小会影响你的应用加载速度,使用的内存以及它消耗的电量。使APK更小的简单方法之一是减少它包含的资源的数量和大小。特别是,你可以删除你的应用程序不再使用的资源,你可以使用可扩展的 Drawable 对象代替图像文件。本节讨论这些方法以及其他几种可以减少应用程序资源从而减少APK整体大小的方法。

删除未使用的资源

lint 工具,是一个在Android Studio中的静态代码分析器,用来检测你的代码中没有用到的res /文件夹中的资源。

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

注意 lint 工具不扫描assets/文件夹,它是通过反射来发现引用的资源或已链接到你的应用程序的库文件。此外,它不会删除资源;它只会提醒你们他们的存在。

你添加到代码的库可能包含未使用的资源。如果在应用程序的build.gradle文件中启用 shrinkResources ,Gradle可以自动删除资源。

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

要使用shrinkResources,必须启用代码缩减。在构建过程中,首先要用 ProGuard 删除未使用的代码,但留下未使用的资源。然后Gradle删除未使用的资源。
有关ProGuard和Android Studio帮助你减少APK大小的其他方法的详细信息,请参阅 Shrink Your Code and Resources
在Android Gradle Plugin 0.7及更高版本中,你可以声明你的应用程序支持的配置。 Gradle使用resConfig 、resConfigs flavor和defaultConfig选项并将此信息传递给构建系统。然后,构建系统会阻止来自其他不受支持的配置的资源出现在APK中,从而减少APK的大小。有关此功能的详细信息,请参阅 Remove unused alternative resources

最小化库中的资源使用

开发Android应用程序时,通常使用外部库来提高应用程序的可用性和多功能性。
例如,你可以引用 Android Support Library 以改善旧设备上的用户体验,或者你可以使用 Google Play Services 检索应用内文字的自动翻译。
如果库是为服务器或桌面设计的,它可能包括你的应用程序不需要的许多对象和方法。要仅包含应用程序需要的库的部分,你可以编辑库的文件(如果许可证允许你修改库)。你也可以使用其他适合移动设备的库给你的应用添加特定功能。

注意 ProGuard 可以清理引用库导入的一些不必要的代码,但它不能删除库的大型内部依赖项 。

仅支持特定密度

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动画化,则动画将仅需要所需帧的数目的一半。



图1.作为资源存储的逐帧动画。

使用Drawable对象

一些图像不需要静态图像资源; framework可以在运行时动态地绘制图像。 Drawable
(XML中的<shape>)可能会占用你APK中的少量空间。此外,XML Drawable 对象还能产生符合Material Design准则的单色图像。

重用资源

你可以为图像的变体使用单一的资源,例如同一图像的有色,阴影或旋转版本。但是,我们建议你重复使用相同的资源集,在运行时根据需要进行自定义。
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"