`

如何给你的Android 安装文件(APK)瘦身

 
阅读更多


文章目录

    APK 文件格式
    如何减少apk文件大小
        掌握良好的编码习惯
        使用 Proguard
        广泛使用 Lint
        对资源文件进行取舍
        资源文件最少化配置
        压缩图片
        限制app支持的cpu 架构的数目
        尽可能地重用
        在合适的时候使用代码渲染图像
    如何更进一步?
    总结

原文出处: Cyril Mottier   译文出处:Android Cool Posts

Android的apk文件越来越大了这已经是一个不争的事实。在Android 还是最初版本的时候,一个app的apk文件大小也还只有2 MB左右,到了现在,一个app的apk文件大小已经升级到10MB到20MB这个范围了。apk文件大小的爆炸式增长主要是因为用户对app质量的期待越来越高以及开发者的开发经验增长,具体体现在以下几个方面:

    Android设备 dpi 的多样化 ([l|m|tv|h|x|xx|xxx]dpi)
    Android平台的进化,开发工具的改进以及开源类库生态系统的丰富
    用户对高质量UI的期待
    其他原因

Android开发者在设计一个app的时候应该将最终发布一个轻量级app作为一个最佳实践来考虑。为什么?首先这就意味着你拥有了一个简洁,易维护代码基础。其次,官方应用商店对超过50MB的apk设置了拓展包文件下载选项,apk文件在50MB以下更容易让用户下载。最后,我们的应用程序环境是一个带宽有限,存储空间有限的环境,apk安装文件越小,下载就会越快,安装也会更快,良性循环,最后说不定用户因为这个给好评。

在大部分情况下,apk大小的增长是为了满足消费者的需要和期待。然而,我认为apk大小的增速已经超过了用户对app期待的增速。所以,很大程度上,官方应用商店里面的那些程序可以瘦身至它们现在大小的一半甚至更多。在这篇文章里面,我将写下一些关于如何给apk文件瘦身的招式,希望你们能够喜欢。

如何给你的Android 安装文件(APK)瘦身

 
APK 文件格式

在说如何给apk瘦身之前,让我们先来看看apk文件内部的结构到底是怎么一回事。说简单点,一个apk文件就是包含一些文件的压缩包。作为开发者,我们通过使用 unzip 命令解压这个apk文件一探apk的内部结构。下面的文件结构就是我们使用 unzip <your_apk_name>.apk1这个命令所获得的:

/lib
  /armeabi
  /armeabi-v7a
  /x86
  /mips
/META-INF
  MANIFEST.MF
  CERT.RSA
  CERT.SF
/res
AndroidManifest.xml
classes.dex
resources.arsc

我们可能对上面大部分的文件和目录都很熟悉。它们和我们在实际开发app的时候所看到得项目结构一样,包含了: /assets, /lib, /res,AndroidManifest.xml. 还有一些文件可能是我们第一次看到。一般说来,classes.dex, 它包含了我们所写的Java代码经过编译后class文件;resources.arsc 包含了预编译之后的资源文件(比如values文件,XML drawables 文件等。)。

由于apk文件只是一个简单地压缩文件,这就意味着它有两种大小:即压缩前的大小和压缩后的大小。这篇文章我将主要关注压缩后的大小。
如何减少apk文件大小

减少apk文件大小可以从几个方面入手。由于每个app都是不同的,所以没有什么绝对规则来给apk文件瘦身。作为apk文件的三个重要组成部分,我们可以考虑从它们开始入手:

    Java 源代码
    资源文件(resources/assets)
    native code

所以接下来的招式都是由减少这些组件的大小出发,进而减少整个app的大小。
掌握良好的编码习惯

这是减少apk文件至关重要的第一步。你要对自己的代码了如子掌。你要移除掉所有无用处的dependency libraries,让你的代码一天比一天优秀,持续地优化你的代码。总而言之,保持一个简洁,最新的代码基础是减少apk文件至关重要的一环。

当然,从零开始一个项目并为这个项目保持一份简洁的代码基础很容易。项目越老,这个工作就越困难。事实上,拥有一大段历史背景的项目必须要去处理各种死代码和无用代码。还好有许多的开发工具可以帮我们来做这些事情……
使用 Proguard

Proguard 是一个很强悍的工具,它可以帮你在代码编译时对代码进行混淆,优化和压缩。它有一个专门用来减少apk文件大小的功能叫做 tree-shaking。Proguard 会遍历你的所有代码然后找出无用处的代码。所有这些不可达(或者不需要)的代码都会在生成最终的apk文件之前被清除掉。Proguard 也会重命名你的类属性,类和接口,然整个代码尽可能地保持轻量级水平。

也许现在你会认为 Proguard 是一个相当有效地工具。但是能力越大,责任也就越大。现在许多开发这认为Proguard有点让人不省心,因为它会重度依赖反射。哪些类或者属性需要被处理或者不能处理都要开发者对 Proguard 进行配置。
广泛使用 Lint

Proguard 只会对 Java 代码起作用,那么对哪些资源文件呢?比如一张图片 my_image 在 res/drawable 文件夹中,没有被使用,Proguard 只会移除掉 R 类中的引用,但是图片依然还在文件夹中。

Lint 一个静态的代码分析器,你只需通过调用 ./gradlew lint这个简单地命令它就能帮你检查所有无用的资源文件。它在检测完之后会提供一份详细的资源文件清单,并将无用的资源列在“UnusedResources: Unused resources” 区域之下。只要你不通过反射来反问这些无用资源,你就可以放心地移除这些文件了。

Lint 会分析资源文件(比如 /res 文件夹下面的文件) ,但是会跳过 assets 文件 ( /assets 文件夹下面的文件)。事实上assets 文件是可以通过它们的文件名直接访问的,而不需要通过Java引用或者XML引用。因此,Lint 也不能判定某个 asset 文件在项目中是否有用。这全取决于开发者对这个文件夹的维护了。如果你没有使用某个asset 文件,那么你就可以直接清除这个文件。
对资源文件进行取舍

Android 支持多种设备。Android的系统设计让它可以支持设备的多样性:屏幕密度,屏幕形状,屏幕大小等等。到了Android 4.4,它支持的屏幕密度包括: ldpi, mdpi, tvdpi, hdpi, xhdpi, xxhdpi and xxxhdpi。但是你要知道的一点是,Android 支持这么多的屏幕密度并不意味着你需要为每一个屏幕密度提供相应的资源文件。

如果你知道某些屏幕密度的设备只有很少部分用户在使用,那么你就可以直接不需要使用相应屏幕密度的资源文件。就我个人而言,我只会为我的应用提供 hdpi, xhdpi and xxhdpi2 这几个屏幕密度的支持。如果某些设备不是这几个屏幕密度的,不用担心,Android 系统会自动使用存在的资源为设备计算然后提供资源文件。

我这么做得原因很简单。首先,这些设备屏幕密度就能覆盖我 80% 的用户。其次,xxxhdpi 这个屏幕密度只是在为未来的设备做准备,但是未来还未到来。最后,我真的不怎么关心低屏幕密度(比如mdpi 和 ldpi),无论我为这几个屏幕密度努力,结果都是令人伤心地,还不如直接让Android系统对 hdpi 资源文件进行适当地缩放来匹配相应地低端机型。

同样地,在 drawable-nodpi 文件夹里面维持一个文件也能节省空间。当然前提是你觉得对这个文件进行相应地缩放之后呈现的效果你能接受或者这个文件出现的几率很少。
资源文件最少化配置

Android 开发经常会依赖各种外部开源代码库,比如Android Support Library, Google Play Services, Facebook SDK 等等。但是这些库里面并不是所有的资源文件你都会用到。比如, Google Play Services 里面会有一些为其他语种提供翻译,而你的app又不需要这个语种的翻译,而且这个库里面还包含了我的app中不支持的 mdpi 资源文件

还好从Android Gradle Plugin 0.7 开始,你可以配置你的app的build系统。这主要是通过配置 resConfig 和 resConfigs 以及默认的配置选项。下面的 DSL (Domain Specific Language)就会阻止 aapt(Android Asset Packaging Tool)打包app中不需要的资源文件。

defaultConfig {
    // ...

    resConfigs "en", "de", "fr", "it"
    resConfigs "nodpi", "hdpi", "xhdpi", "xxhdpi", "xxxhdpi"
}

压缩图片

Aapt(Android Asset Packaging Tool)就内置了 保真图像压缩算法。例如,一个只需 256 色的真彩PNG图片会被aapt 通过一个颜色调色板转化成一个 8-bit PNG 文件。这可以帮助你减少图片文件的大小。当然你还可以通过Google查找相应的优化工具,比如 pngquant, ImageAlpha 和 ImageOptim 等。你可以从中选择一个适合你的工具。

还有一种只在Android平台上存在的图片文件也可以优化,它就是 9-patches。就我目前所知道,我还没发现有这个文件的优化工具。然而你只需要求你的设计师将它的可扩展区域和内容区域尽可能地减少即可。这不但可以减少资源文件的大小,还能使得以后资源文件的维护变得更加简单。
限制app支持的cpu 架构的数目

一般说来Android 使用Java 代码即可以满足大部分需求,不过还是有一小部分案例需要使用一些 native code。就像之前对资源文件那样opinionated,你可以这些 native code opinionated。 在当前的Android 生态系统中,让你的app支持 armabi 和 x86 架构就够了。这里有一篇相当不错的关于如何瘦身native 代码库的文章,你可以参考参考。
尽可能地重用

重用资源可能是你在进行移动开发时需要了解的最重要的优化技巧之一。比如在一个 ListView 或者 RecyclerView,重用可以帮助你在列表滚动时保持界面流畅。重用还可以帮你减少apk文件的大小。例如,Android 提供了几个工具为一个asset文件重新着色,在Android L中你可以使用 android:tint 和android:tintMode 来达到效果,在老版本中则可以使用 ColorFilter 。

如果系统中有两种图片,一种图片是另一种图片翻转180°得到的,那么你就可以移除一种图片,通过代码实现。比如你现在有两种图片分别命名为 ic_arrow_expand 和 ic_arrow_collapse :

如何给你的Android 安装文件(APK)瘦身

你可以直接移除掉 ic_arrow_collapse 文件,然后在ic_arrow_expand 的基础上创建一个 RotateDrawable 。这个方法也可以让你减少设计人员的工作:

<?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" />

在合适的时候使用代码渲染图像

在某些情况下,直接使用Java 代码渲染图像也能获得不错的效果。比如逐帧动画就是一个很好的例子。最近我都在尝试一些Android Wear 的开发,了解了一下Android wearable support library。就像其他的Android support library 一样,这个库里面也有一些工具来处理穿戴设备的。

不过让我吃惊的是,当我简单地构建了一个 “Hello World”示例,最后得到的apk文件竟然有1.5MB。于是我快速地研究了一下 wearable-support.aar 文件,发现这个库有两个逐帧动画,并分别支持了3种不同的屏幕密度:一个 “success” 动画 (31 frames) 和一个 “open on phone” 动画 (54 frames)。

如何给你的Android 安装文件(APK)瘦身

 

这个逐帧success动画是被一个叫做 AnimationDrawable 所定义的:

<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android" android:oneshot="true">
    <item android:drawable="@drawable/generic_confirmation_00163" android:duration="33"/>
    <item android:drawable="@drawable/generic_confirmation_00164" android:duration="33"/>
    <item android:drawable="@drawable/generic_confirmation_00165" android:duration="33"/>
    <item android:drawable="@drawable/generic_confirmation_00166" android:duration="33"/>
    <item android:drawable="@drawable/generic_confirmation_00167" android:duration="33"/>
    <item android:drawable="@drawable/generic_confirmation_00168" android:duration="33"/>
    <item android:drawable="@drawable/generic_confirmation_00169" android:duration="33"/>
    <item android:drawable="@drawable/generic_confirmation_00170" android:duration="33"/>
    <item android:drawable="@drawable/generic_confirmation_00171" android:duration="33"/>
    <item android:drawable="@drawable/generic_confirmation_00172" android:duration="33"/>
    <item android:drawable="@drawable/generic_confirmation_00173" android:duration="33"/>
    <item android:drawable="@drawable/generic_confirmation_00174" android:duration="33"/>
    <item android:drawable="@drawable/generic_confirmation_00175" android:duration="333"/>
    <item android:drawable="@drawable/generic_confirmation_00185" android:duration="33"/>
    <item android:drawable="@drawable/generic_confirmation_00186" android:duration="33"/>
    <item android:drawable="@drawable/generic_confirmation_00187" android:duration="33"/>
    <item android:drawable="@drawable/generic_confirmation_00188" android:duration="33"/>
    <item android:drawable="@drawable/generic_confirmation_00189" android:duration="33"/>
    <item android:drawable="@drawable/generic_confirmation_00190" android:duration="33"/>
    <item android:drawable="@drawable/generic_confirmation_00191" android:duration="33"/>
    <item android:drawable="@drawable/generic_confirmation_00192" android:duration="33"/>
    <item android:drawable="@drawable/generic_confirmation_00193" android:duration="33"/>
</animation-list>

这样做得好处就是 (我当然在讽刺) 每帧显示33ms,这使得整个动画保持在30fps的频率。如果每帧16ms这将会导致整个库是之前的两倍大。如果你去看源码你会发现很有趣。在 generic_confirmation_00175 这一帧 (15 行) 将持续显示 333ms。 generic_confirmation_00185 紧跟着它。这个优化节省了9个类似的帧 (包含了从176 帧到 184 帧) 。不过最后神奇的是 wearable-support.aar 竟然神奇的包含了这个9个完全无用的帧,而且还以3中屏幕密度展示。3

在代码中来渲染这样的动画明显会很花时间。然而当你维持动画运行在60fps这样的频率可以大幅度的减少apk的大小。在写这篇博文的时候,Android还没提供工具来渲染这样的动画。但是我希望Google正在开发新一代的轻量级实时渲染系统来保证material design的细节呈现。当然“Adobe After Effect to VectorDrawable” 之类的设计工具也能提供很多方便。
如何更进一步?

上面所有的招式都集中在app或者library 开发者。也许我们还可以在app分发渠道方面为apk大小做出一些改变?我想可以在app 分发服务器端做一些改进,或者在官方应用商店。例如,我们可以期待官方应用商店在用户安装app的时候为设备绑定相应的native 库而摒弃那些无用的。

同样地,我们还可以想象只根据目标设备的配置来打包应用。不幸的是,这可能破坏Android 生态一个重要的功能特性:配置热置换。事实上,Android一开始就是位处理各种实时的配置更改(语言,屏幕转向)而设计的。如果我们移除掉与目标屏幕不兼容的资源文件,这可以极大的减少文件大小。不过Android需要处理实时的屏幕密度更改。即便我们假设废除这种功能,我们仍然需要处理为不同的屏幕密度设计的图片以及其他配置(比如屏幕朝向,最小宽度等)。

服务器端的apk打包看起来很强大。但这样会冒很大得风险,因为最终传送给用户的apk会于开发者发给的服务器的完全不同。分发一些缺失资源文件的apk可能会导致app崩溃。
总结

设计就是在一个约束集里面找出最好的方案。显然apk文件的大小就是一个约束。不要害怕为了让多个方面变得更好而放松一个方面的约束。例如,当你要降低UI的渲染效果时,不要犹豫,因为这可以让apk的大小减小,同时使得app的运行也更加流畅。你99%的用户是感受不到UI质量变低的,但是他们会注意到apk文件变小了,运行也更加流畅了。总之,你需要将app各方面进行整体考虑,而不是仅仅几个方面的斟酌。

分享到:
评论

相关推荐

    APK瘦身优化检测工具-Matrix ApkChecker 使用(csdn)————程序.pdf

    Matrix ApkChecker 是一个强大的Android APK分析和优化工具,它能够帮助开发者检查APK安装包中可能存在的问题,以实现APK的瘦身和性能优化。该工具通过一系列预设的规则进行检测,并生成详细的报告,便于分析和解决...

    从加固讲APK瘦身.pdf

    《从加固讲APK瘦身:优化移动应用的全方位策略》 在移动应用开发领域,APK文件的大小和性能往往成为用户体验的关键因素。随着应用程序功能的复杂化和安全需求的提高,APK文件的体积日益膨胀,这不仅影响了用户的...

    藏经阁-从加固讲APK瘦身-16.pdf

    《藏经阁-从加固讲APK瘦身》是关于如何优化Android应用程序,特别是APK文件大小的专业讲座。本文主要从加固、混淆、反混淆等方面探讨了如何有效地减小APK的体积,提升用户体验。 首先,APK瘦身的重要性在于解决体积...

    Android APK+Dex文件反编译及回编译工具

    全新 APK文件安装器  2.修复 签名工具 开启速度慢问题  3.工具包体积瘦身 50%  4.其他微调整 【安装:由于更新较多,请卸载掉旧版后,再安装!!!】 v.1.6.0 beta2 2011.11.21  1.更新 smali/baksmali 至 v...

    Apk 全面瘦身详解

    本文将详细讲解Apk瘦身的各种策略,从理解Apk的包结构开始,探讨如何进行有效的优化。 首先,了解Apk的包结构是优化的第一步。Apk主要包含以下几个部分: 1. **lib/** 目录:存放针对不同CPU架构的.so库文件,通常...

    thinApkFile,去除apk中无用文件以减小apk大小的gradle插件.zip

    "thinApkFile"是一个开源的Gradle插件,专门用于去除APK中的无用文件,从而实现APK的瘦身。这个插件利用先进的分析技术,识别并移除那些在运行时不必要的资源和库,有助于提高应用的分发效率。 首先,了解...

    王栋栋_周报_AndroidAPK相关总结_20190809.doc

    Apk瘦身是优化应用体积的过程,其主要目标是提高用户的下载体验,减少下载时间和数据消耗。瘦身主要包括以下几个方面: 1. **代码混淆**:正如前面提到的,启用代码混淆可以删除不必要的代码,同时用无意义的名称...

    安卓内置APK程序中英文对照表-方便大家给系统瘦身.pdf

    2. **ApkManager.apk**: APK 安装器 - 用于安装和管理应用程序,是系统中处理APK文件的核心工具。 3. **advancedsettings.apk**: 高级设置 - 提供对系统更深层次的设置选项,允许用户自定义设备行为。 4. **Alarm...

    Android群英传+Android群英传:神兵利器+Android开发艺术探索

    6. **性能优化**:《Android开发艺术探索》很可能包含性能优化技巧,如内存管理、CPU性能分析、电量优化、APK瘦身等。 7. **第三方库集成**:书籍可能会介绍如何集成和使用如Glide、ButterKnife、Dagger、RxJava、...

    《宅男的android开发指南》(翻译)--10完整版

    15. **性能优化**:涵盖内存管理、CPU优化、布局优化和APK瘦身等技巧,提高应用的运行效率和用户体验。 这份教程通过详实的例子和清晰的解释,帮助开发者全面了解Android开发的各个环节,无论是初学者还是有一定...

    Android应用源码之程序的安装、卸载和更新-IT计算机-毕业设计.zip

    - **APK瘦身**: 减少资源文件大小,优化代码结构,提高安装速度。 - **热更新**: 无需完整安装的更新方式,如插件化框架,降低用户等待时间。 这个毕业设计的源码示例提供了对Android应用生命周期管理的深入了解...

    Facebook 出品的 apk 包优化工具 redex.zip

    Redex是一款由Facebook开发并开源的Android应用优化框架,它通过对APK中的DEX(Dalvik字节码)文件进行一系列的优化操作,如代码混淆、资源压缩、删除无用代码等,来实现对APK的瘦身。这些优化步骤包括但不限于: -...

    AndroidApp包瘦身优化实践

    随着业务的快速迭代增长,美团App里不断引入新的业务逻辑代码、图片资源和第三方...比如,美团App7.8.6的线上版本的格式是这样的:可以看到APK由以下主要部分组成:当然还会有一些其它的文件,例如上图中的org/、src/、

    Android_DEX_文件格式详解

    Android DEX 文件是Dalvik虚拟机执行的字节码文件,它是Android应用的主要组成部分,包含了应用程序的类、方法和数据。下面将详细解释DEX文件...开发者可以通过修改DEX文件来实现APK的瘦身、性能提升或保护代码安全。

    Android导出Excel

    由于Android Studio的限制,你可能需要使用瘦身后的POI版本,例如`poi-ooxml-schemas`和`poi-ooxml-lite`。 2. **创建Excel工作簿**:使用`XSSFWorkbook`类创建一个新的Excel工作簿对象。 3. **创建工作表**:在...

    android 学习思维导图

    11. **性能优化**:内存优化、UI流畅性、APK瘦身、代码混淆。 12. **测试**:单元测试、集成测试、UI自动化测试。 13. **热修复与插件化**:Dex分包、插件化框架(如Dexposed、VirtualApk)。 14. **Android新特性**...

    android讲义第二版

    15. **性能优化**:内存管理、CPU优化、UI流畅性提升、APK瘦身等方法,提升应用的用户体验。 16. **Android最新特性和框架**:涵盖Android的新版本特性,如Android Jetpack组件库的使用,如Room、LiveData、...

    Android开发从入门到精通源码

    12. **性能优化**:讲解如何提高应用的性能,包括内存优化、绘制优化、APK瘦身等,以及使用Android Profiler工具进行性能分析。 每个章节都配套有扶松柏光盘源代码,这些源码是实际项目的实例,读者可以通过阅读和...

    Pragmatic Programmers - Hello, Android, 3rd Edition, 2010.zip

    书中会讨论内存管理、CPU使用率、绘制性能和APK瘦身等技巧。 十一、测试与调试 最后,书中会介绍单元测试、UI测试和模拟器/真机测试的方法,以及如何利用Android Studio的调试工具进行问题排查。 通过学习《你好,...

    人气专家】老罗的Android之旅.

    11. **性能优化**:包括内存管理、渲染优化、APK瘦身等,这些都是提高应用质量和用户体验的关键。 每个PPT文件可能分别深入讲解上述一个或多个知识点,通过逐步学习和实践,学习者可以逐步成长为一名熟练的Android...

Global site tag (gtag.js) - Google Analytics