码迷,mamicode.com
首页 > 其他好文 > 详细

缩小apk的大小

时间:2017-03-30 14:02:09      阅读:268      评论:0      收藏:0      [点我收藏+]

标签:ade   run   vector   ram   进制   内存   超出   网络   动态   

如果你的app看起来很大,用户通常避免下载,特别是在很多新兴的国家,人们使用2G和3G网络接入因特网,和按流量计费。这篇文章介绍如何减小app的体积,这会帮助更多的用户来下载你的app。

理解apk的结构


在讨论如何减小你的app的apk大小之前,理解一个apk的结构是很有帮助的。一个apk文件,是一个zip文件,包含java class文件,资源文件,和编译的文件资源。

一个apk包含下列文件:

  • META-INF/: 包含 CERT.SF 和CERT.RSA 签名文件, 也包括 MANIFEST.MF 配置文件.
  • assets/: 包含一个app的引用资源文件,用AssetManager 检索
  • res/: 包含那些没有被编译到 resources.arsc 的资源.
  • lib/: 编译好的代码。有子文件,代表平台类型,如armeabiarmeabi-v7aarm64-v8ax86x86_64, and mips.

一个apk也包含下面这些文件。 下面只有 AndroidManifest.xml 必须会有.

  • resources.arsc: 包含编译的资源文件,主要是res/values/下面的XML文件。打包工具从xml里面提炼内容,编译成二进制的形式。这些内容包括字符,样式,也包含那些不在resources.arsc里面的文件,如图片和布局文件的路径。
  • classes.dex: 包含被虚拟机Dalvik和ART识别的,以Dex格式存在的classes编译文件。
  • AndroidManifest.xml: android核心配置文件。配置文件列出了app的名称,版本,权利,和相关的包。xml格式。

减少资源的数量和体积


apk体积的大小,对app加载的速度,占用的内存,消耗的电力有很大的影响。让apk变小的,很常见很有效的一点是,减少资源的数量和体积。特别是,减少app不再使用的资源,使用放大的Drawable对象代替图片文件。这节讨论几种方法,较少app的资源,来减少app超出的体积。

减少无用的资源

lint工具, 一个android studio的静态代码分析器,删除你的res/文件中代码不再引用的资源.当lint工具 在工程中发现一部分未使用的资源,会打印下列信息.

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

Note: lint 工具不扫描assets/文件, assets that are referenced via reflection, or library files that you‘ve linked to your app. Also, it doesn‘t remove resources; it only alerts you to their presence.

Libraries 你添加的lib可能包含没有用的资源. 在 app的build.gradle 文件添加 shrinkResources == true 时, Gradle 会自动减少这些资源.

android {
    // Other settings

    buildTypes {
        release {
            minifyEnabled true
            shrinkResources true
            proguardFiles getDefaultProguardFile(‘proguard-android.txt‘), ‘proguard-rules.pro‘
        }
    }
}

用这个shrinkResources, 你必须确保你的代码shrinking. 在编译过程中,第一个 ProGuard 属性会删除无用的code , 但是会留下无用的资源。然后,Gradle 会删除这些无用的资源.

要了解 ProGuard 更多信息,和其他的android studio帮助减小apk大小的方法,请看Shrink Your Code and Resources.

在android gradle 0.7 及以上版本,你可以申明你app支持的配置。Gradle使用这些选项【resConfig and resConfigs flavors and the defaultConfig option】来通过编译系统。编译系统可以防止不受配置支持的资源出现在apk文件,以此来减小apk的大小。此功能的更多信息,请看Remove unused alternative resources.

使用最小化资源的库

当我们开发android app,通常会使用第三方的库来实现功能和效率. 例如,你可能用到Android Support Library来改善在旧设备上的用户体验, 或者你可以使用Google Play Services实现app里面的文字的自动翻译。

如果一个库是为了服务器,和电脑设计,它可能包含很多app不需要的对象。如果许可修改这个库,你应该编辑这个库,以仅仅包含app需要使用的部分。你还可以使用手机友好的库加入你的app,作为一种替换方法。

Note: ProGuard can clean up some unnecessary code imported with a library, but it can‘t remove a library‘s large internal dependencies.

只支持特定的密度

Android支持多种密度的设备。在Android 4.4 (api level 19)及以上版本, the framework 支持多种密度:ldpi,mdpi,tvdpi,hdpi,xhdpi,xxhdpi and xxxhdpi. 尽管Android支持所有这些密度,你没有必要为每种密度导出资源。

如果你知道某种密度的用户比较少,考虑是否需要这些密度打包到你的app。如果你不包含这种密度的资源,android会自动将现有的其他密度的资源通过缩放显示. 

如果你的app之需要缩放的图片,你会通过拥有一中drawable-nodpi/图片来节省更多的空间。我们确保每个app都只会扫包含xxhdpi这种。

更多屏幕密度,请看 Screen Sizes and Densities.

减少动画帧

逐帧动画,会非常明显的增加apk的大小。图1显示了一个逐帧动画的例子,在一个文件夹中包含多个不同的PNG。每张图片就是动画的一帧。

你添加一帧,就在apk里多一张图片。图1,这个图片动画大概每秒30张左右。如果用每秒15张代替,这个动画仅需要一般的帧数。


技术分享


Figure 1. Frame by frame animations stored as resources.

使用Drawable对象

有写图片,不需要一个静态的图片资源。framework可以在运行时,动态地画出图片。Drawable 对象(<shape> in XML) 会占用apk极少的空间. 另外, XML Drawable 对象 会生成如何 material design 原则的单色图片。

复用资源

通一张图片的多种形式,如着色,阴影,旋转等,你可以使用一张单独的资源.然而,我们建议你重用相同的一组资源,在运行时根据需要定制它们。

Androdi提供多种工具来改变组件的颜色,5.0或更高的通过 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的大小。程序渲染可以释放空间,因为i不需要在apk里面存储。

紧缩PNG文件

aapt工具可以在编译过程中,无损地优化res/drawable/的图片资源。例如,aapt 工具 通过一个调色板 可以把一个真彩色的PNG转变成一个8bit的PNG,不再需要256颜色。这意味同等质量,但更小的内存占用.

记住 aapt 有以下局限:

  • aapt 工具不能缩小asset/下面的 PNG
  • aapt工具缩小图片文件,需要它们use 256或更少颜色
  • aapt工具可能会加压已经压缩的PNG图片。为了避免这一点,你要是在Gradle中使用cruncherEnabled禁止PNG文件的这个过程。
aaptOptions {
    cruncherEnabled = false
}

压缩PNG and JPEG 文件

你可以使用pngcrushpngquant, or zopflipn等工具,在不损失图片质量的情况下,减少PNG的文件大小。所有这些工具都可以在保护图片质量的情况下,减少PNG文件的大小。


pngcrush工具尤其有效:这个工具遍历PNG过滤器和zlib(缩小)参数,使用过滤器和参数的组合压缩图像。然后选择配置收益率最小的压缩输出。


对于JPEG文件,您可以使用packJPG 工具,它可以压缩JPEG文件成一个紧凑的形式。


使用WebP文件格式

替换PNG和JPEG文件,你可以使用WebP文件格式。WebP 格式兼有 JPEG的有损压缩,和 PNG的透明度,但是比单独的JPEG或PNG更好的压缩。

使用WebP有一些明显的缺陷。第一,android 3.2 以下不支持。第二,和PNG相比,系统解码该格式的图片需要更多的时间。

Note: 谷歌市场只接收app启动图标为PNG的apk。不支持其他格式的图片作为启动icon。

你可以使用 Android Studio 将现有的 BMP, JPG, PNG or GIF 图片换成WebP格式.更多信息,请看 Create WebP Images Using Android Studio.

使用向量图片

你可以使用矢量图形 创建分辨率无关的图标和其他可伸缩的媒体。使用这些图形可以大大减少你的APK大小。矢量图在在Android 中用VectorDrawable对象表示VectorDrawable对象,一个100字节的文件可以生成一个锋利的屏幕图像的大小。


然而,系统呈现每个VectorDrawable对象需要大量的时间,显示到屏幕的图像更大,花费的时间更长因此,只有当显示小图像,考虑使用这些矢量图形

For more information on working with VectorDrawable objects, see Working with Drawables.

减少本地和java代码


有下面几种方法.

移除产生的不必要的代码

确保明白自动产生的任何代码的footprint。譬如,很多protocol buffer工具会产生过多的方法,会成倍,甚至三倍地增加代码大小。

移除枚举

一个单独的enum会增加app中calsses.dex文件大约1.0到1.4KB的大小。对于复杂系统或共享库,这些添加可以迅速积累。如果可能的话,可以考虑使用@IntDef注释和ProGuard 移除枚举,并将它们转换为整数。这类型转换将保存所有的枚举类型的安全的好处。

减少本地库的大小

如果你的app只用本地代码和android NDK, 你可以优化代码来减少apk的大小. 两种有用的技术:去除调试符号,和 避免提取本地库。

去除调试符号

如果你的程序还在开发中,仍然需要debug,请使用debug符号。使用Android NDK提供的 arm-eabi-strip工具从本地库中移除不需要的debug符号。然后,你编译release版本.

避免提取本地库

保存 apk中未压缩的so文件,和在app的manifest文件中的<application>下面设置android:extractNativeLibs为false.这可以避免 在安装的时候, PackageManager 从apk中拷贝so到文件系统 ,并且这样做的一个额外的好处是,增量更新的时候,增量包更小。

维护多个精品apk


你的apk会包含一些用户从下载apk之后永远不会使用的内容,如地区,语言信息。为你的用户创建一个精简的下载,你能够可以将app分为几个apk;由一些不同的因素如屏幕大小,是否支持GPU 纹理等区别.

当一个用户下载你的app时,他们的设备接收正确的apk,这个apk基于他们的设备特性和设置。这样,设备不需要接收哪些不需要的资源。譬如,如果一个用户有一个hdpi的设备,他们不需要xxxhdpi的资源,这个资源是更高密度的设备显示所需要的。

更多信息,请看 Configure APK Splits and Maintaining Multiple APKs.

缩小apk的大小

标签:ade   run   vector   ram   进制   内存   超出   网络   动态   

原文地址:http://blog.csdn.net/mybook1122/article/details/67639064

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!