文档章节

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

gavin_jin
 gavin_jin
发布于 2016/11/12 00:14
字数 3262
阅读 49
收藏 3
点赞 1
评论 0

前言

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

用户经常会避免下载看起来过大的应用程序,特别是在新兴市场,设备连接到常见的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大小的其他方法的详细信息。

在Android Gradle Plugin 0.7及更高版本中,你可以声明你的应用程序支持的配置。 Gradle使用 resConfig 、 resConfigs flavor 和 defaultConfig 选项并将此信息传递给构建系统。然后,构建系统会阻止来自其他不受支持的配置的资源出现在APK中,从而减少APK的大小。

最小化库中的资源使用

开发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 图片版本。

减少动画帧

逐帧动画会大幅增加APK的大小。图1显示了在目录中分成多个PNG文件的逐帧动画的示例。每个图像是动画中的一帧。

对于添加到动画中的每个帧,都需要增加APK中存储的图片数量。在图1中,图像在应用程序中以30 FPS动画。如果图像仅以15FPS动画化,则动画将仅需要所需帧的数目的一半。

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

使用Drawable对象

一些图像不需要静态图像资源; framework可以在运行时动态地绘制图像。

(XML中的 <shape> )可能会占用你APK中的少量空间。此外,XML对象还能产生符合 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"
    android:fromDegrees="180"
    android:pivotX="50%"
    android:pivotY="50%"
    android:toDegrees="180" />

从代码中呈现

你还可以通过程序性渲染图片来减少APK大小。这个过程也释放了空间,因为你不再在APK中存储图像文件。

压缩PNG文件

aapt 工具可以在构建过程期间优化放置在 res / drawable / 中的图像资源,以及无损压缩。例如, aapt 工具可以将不需要多于256种颜色的真彩色PNG转换为带有调色板的8位PNG。这样做会产生质量相同但占用内存较小的映像。

请记住, aapt 有以下限制:

  • aapt 工具不会压缩资源/文件夹中包含的PNG文件
  • 图像文件需要使用256个或更少的颜色的 aapt 工具来优化它们。
  • aapt 工具可能会使已压缩的PNG文件膨胀。为了防止这种情况,你可以在Gradle中使用 cruncherEnabled 标志为PNG文件禁用此过程:
    aaptOptions {
      cruncherEnabled = false
    }

压缩PNG和JPEG文件

你可以使用像 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文件需要更长的时间。

注意:只有当所包含的图标使用PNG格式时,Google Play才接受APK。如果你打算通过Google Play发布应用,则无法对应用图标使用其他文件格式(如JPEG或WebP)。

使用矢量图形

你可以使用矢量图形创建独立于分辨率的图标和其他可伸缩图片。 使用这些图形可以大大减少APK的大小。 矢量图形在Android中表示为 VectorDrawable 对象。 使用 VectorDrawable 对象,100字节的文件可以生成屏幕大小的清晰图像。 然而,系统渲染每个 VectorDrawable 对象需要大量的时间,较大的图像需要更长的时间才能出现在屏幕上。 因此,只有在显示小图像时才考虑使用这些矢量图形。

三、减少原生和Java代码

有几种方法可以用来减少应用程序中Java和原生代码库的大小。

删除不必要的生成的代码

确保了解自动生成的任何代码的足迹。例如,许多协议缓冲工具生成过多的方法和类,可以使应用程序的大小增加一倍或三倍。

删除枚举

单个枚举可以使应用程序的 classes.dex 文件添加大约1.0到1.4 KB的大小。 这些添加可以快速积累为复杂的系统或共享库。 如果可能,请考虑使用 @IntDef 注释和 ProGuard 来除去枚举并将它们转换为整数。 此类型转换保留枚举的所有类型的安全性好处。

减少本地二进制文件的大小

如果你的应用使用原生代码和Android NDK,你还可以通过优化代码来减小应用的大小。两个有用的技术是删除调试符号和提取原生库。

  • 删除调试符号

    如果你的应用程序正在开发中并仍需要调试,则使用调试符号很有意义。 使用Android NDK中提供的 arm-eabi-strip 工具从本机库中删除不必要的调试符号。 之后,你可以编译你的发行版。
  • 避免提取原生库

    将 .so 文件存储在APK中未压缩的文件,并在应用清单的 <application> 元素中将 android:extractNativeLibs 标记设置为false。 这将防止 PackageManager 在安装过程中将 .so 文件从APK复制到文件系统,并且将具有使你的应用程序的delta更新更小的额外好处。

四、维护多个精益版APK

你的APK可以包含用户下载但从不使用的内容,例如区域或语言信息。 要为用户创建最低限度的下载,你可以将应用细分为多个APK,并根据屏幕尺寸或GPU纹理支持等因素进行区分。

当用户下载你的应用时,其设备会根据设备的功能和设置接收正确的APK。这样,设备不会接收设备没有的功能的资源。例如,如果用户具有 hdpi 设备,则他们可能不需要你为具有更高密度显示的设备添加的 xxxhdpi 资源。

 

本文转载自:http://www.jianshu.com/p/6df0dc494019

共有 人打赏支持
gavin_jin
粉丝 26
博文 109
码字总数 115950
作品 0
海淀
技术主管
[译] 如何优化您的 Android 应用(Go 版)

原文地址:How to optimize your app for Android (Go edition) 原文作者:Raj Ajrawat 译文出自:掘金翻译计划 本文永久链接:github.com/xitu/gold-m… 译者:androidxiao 洞察力可帮助您创...

Android_开发者
06/25
0
0
Android动态化框架App Bundles

Android App Bundles 在今年的Google I/O大会上,Google向 Android 引入了新 App 动态化框架(即Android App Bundle,缩写为AAB),与Instant App不同,AAB是借助Split Apk完成动态加载,使用...

code_xzh
05/16
0
0
Android App补丁更新

上一周比较忙,忙的不可开交,写的文章也就两篇,在此希望大家见谅。这周呢,突然闲下来了,有时间了,就重构了下代码,捣鼓点前卫的技术,沉淀沉淀。所以呢,今天就分享下这几天研究的东西。...

Jack_1900
2014/08/14
0
4
Android热修复Tinker接入实战

自2016年底Android Studio3.0版本退出以来,Android提出了InstantRun热修复方案,基于这种机制,各种热修复框架竞相涌现,国内的软件大厂纷纷开发了自己的热修复框架。对于热修复的更多介绍大...

code_xzh
05/04
0
0
Android官方提供的支持不同屏幕大小的全部方法

本文将告诉你如何让你的应用程序支持各种不同屏幕大小,主要通过以下几种办法: 让你的布局能充分的自适应屏幕 根据屏幕的配置来加载合适的UI布局 确保正确的布局应用在正确的设备屏幕上 提供...

带梦想一7飞
2013/06/05
0
0
Google I/O 之 Android App Bundles 是个啥

  Android App Bundles(以下简称AAB)是今年Google I/O大会带来的一款全新动态化框架,与Instant App不同,AAB是借助Split Apk完成动态加载。介绍AAB之前,先来了解下SplitApk。   Spl...

Android群英传
05/15
0
0
eclipse和android源码编译应用效果有差异

一般来说,eclipse只是IDE开发工具,它虽然能编译apk,但是大多数开发情况下,都会要求必须在源码里编译通过,达到工程化,而不是单单的demo。 问题: 这次悲催而又诡异的遇到了这么个问题:...

blackylin
2013/06/27
0
2
【用tcl/tk语言开发android应用】

用tcl/tk语言开发android应用 tcl/tk 的跨平台能力如其官方说的一样:“native applications that run unchanged across Windows,Mac OS X, Linux and more” 除了前面提到的,还有BSD、UIN...

名字不能长
2015/05/13
0
0
android apk 防止反编译技术第三篇-加密

经过了忙碌的一周终于有时间静下来写点东西了,我们继续介绍android apk防止反编译技术的另一种方法。前两篇我们讲了加壳技术(http://my.oschina.net/u/2323218/blog/393372)和运行时修改字节...

lonely1986
2015/04/12
0
9
android apk 自我保护技术-加密apk

经过了忙碌的一周终于有时间静下来写点东西了,我们继续介绍android apk防止反编译技术的另一种方法。前两篇我们讲了加壳技术(http://my.oschina.net/u/2323218/blog/393372)和运行时修改字节...

HAOMCU
2015/04/13
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

Android 复制和粘贴功能

做了一回搬运工,原文地址:https://blog.csdn.net/kennethyo/article/details/76602765 Android 复制和粘贴功能,需要调用系统服务ClipboardManager来实现。 ClipboardManager mClipboardM...

她叫我小渝
今天
0
0
拦截SQLSERVER的SSL加密通道替换传输过程中的用户名密码实现运维审计(一)

工作准备 •一台SQLSERVER 2005/SQLSERVER 2008服务 •SQLSERVER jdbc驱动程序 •Java开发环境eclipse + jdk1.8 •java反编译工具JD-Core 反编译JDBC分析SQLSERVER客户端与服务器通信原理 SQ...

紅顏為君笑
今天
6
0
jQuery零基础入门——(六)修改DOM结构

《jQuery零基础入门》系列博文是在廖雪峰老师的博文基础上,可能补充了个人的理解和日常遇到的点,用我的理解表述出来,主干出处来自廖雪峰老师的技术分享。 在《零基础入门JavaScript》的时...

JandenMa
今天
0
0
linux mint 1.9 qq 安装

转: https://www.jianshu.com/p/cdc3d03c144d 1. 下载 qq 轻聊版,可在百度搜索后下载 QQ7.9Light.exe 2. 去wine的官网(https://wiki.winehq.org/Ubuntu) 安装 wine . 提醒网页可以切换成中...

Canaan_
今天
0
0
PHP后台运行命令并管理运行程序

php后台运行命令并管理后台运行程序 class ProcessModel{ private $pid; private $command; private $resultToFile = ''; public function __construct($cl=false){......

colin_86
今天
1
0
数据结构与算法4

在此程序中,HighArray类中的find()方法用数据项的值作为参数传递,它的返回值决定是否找到此数据项。 insert()方法向数组下一个空位置放置一个新的数据项。一个名为nElems的字段跟踪记录着...

沉迷于编程的小菜菜
今天
1
1
fiddler安装和基本使用以及代理设置

项目需求 由于开发过程中客户端和服务器数据交互非常频繁,有时候服务端需要知道客户端调用接口传了哪些参数过来,这个时候就需要一个工具可以监听这些接口请求参数,已经接口的响应的数据,这种...

银装素裹
今天
0
0
Python分析《我不是药神》豆瓣评论

读取 Mongo 中的短评数据,进行中文分词 对分词结果取 Top50 生成词云 生成词云效果 看来网上关于 我不是药神 vs 达拉斯 的争论很热啊。关于词频统计就这些,代码中也会完成一些其它的分析任...

猫咪编程
今天
0
0
虚拟机怎么安装vmware tools

https://blog.csdn.net/tjcwt2011/article/details/72638977

AndyZhouX
昨天
1
0
There is no session with id[xxx]

参考网页 https://blog.csdn.net/caimengyuan/article/details/52526765 报错 2018-07-19 23:04:35,330 [http-nio-1008-exec-8] DEBUG [org.apache.shiro.web.servlet.SimpleCookie] - Found......

karma123
昨天
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部