Android开发——减小APK大小

0. 前言

APK的大小对APP的加载速度,使用内存大小和消耗功率多少有一定影响。如何减小APK的大小对于Android开发者是一个永恒的话题。

查阅了很多相关资料,并将其做了删减以及总结。本文原创,转载请注明出处:http://blog.csdn.net/seu_calvin/article/details/52199151

首先就来了解一下APK的组成结构。

 

1. APK的组成结构

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

assets:包含APP的assets资源,代码中可以通过AssetManager对象访问。

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

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

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

classes.dex:包含被编译的类,以DalvikART虚拟机能理解的dex文件格式。

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

2.  减小APK的大小的方式汇总

2.1 Lint工具

在Android Studio中的一个静态代码工具lint,检测在你的res目录下代码没有引用的资源,并没有扫描assets目录下的资源。当lint工具在你的项目中发现一个潜在的未使用的资源,它会打印一条如下示例的消息。只提醒,不主动移除。

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


2.2 ShrinkResourcesGradle以及MinifyEnabled

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

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

为了使用shrinkResources,你必须启动代码压缩,将minifyEnabled设置为true。在构建的过程中,首先ProGuard会移除没有使用的代码,接着Gradle会移除没有使用的资源。

在Proguard中,是否保留符号表对APP的大小是有显著的影响的,可酌情注释下面这行代码,但是建议尽量保留,它可以用于保留调试信息。

-keepattributes SourceFile,LineNumberTable

2.3 使用一套资源

对于绝大对数APP来说,只需要取一套设计图就足够了。鉴于现在分辨率的趋势,建议取720p的资源,放到xhdpi目录。在视觉上差别不大,很多大公司的产品也是如此,但却能显著的减少资源占用大小,这里不是说把非xhdpi的目录都删除,而是强调保留一套设计资源就够了。

2.4 只保留中文的语言资源

大部分应用其实并不需要支持几十种语言的国际化支持。强大的gradle支持语言的配置,比如国内应用只支持中文:

android {
    defaultConfig {
        resConfigs "zh"
    }
}

2.5 关于PNG图片和JPG图片

Android打包本身会对png进行无损压缩, TinyPNG使用智能有损压缩技术,在尽量少的损失下来减少PNG文件的大小。具体TinyPNG的信息请访问https://tinypng.com/

如果对于非透明的大图,jpg将会比png的大小有显著的优势,虽然不是绝对的,但是通常会减小到一半都不止。

在启动页,活动页等之类的大图展示区采用jpg将是非常明智的选择。

当然大图适当缩小对视觉的影响也不大,适当缩小大图也是可行的。

但是Android的界面能用png最好是用png,因为32位的png颜色过渡平滑且支持透明。jpg是像素化压缩过的图片,质量已经下降了,再拿来做9path的按钮和平铺拉伸的控件必然惨不忍睹,要尽量避免。

在res下这些icon用的都是png格式,就是说Google推荐使用的是png格式的图片。

2.6 关于WEBP图片

相对于jpg、png,webp作为一种新的图片格式,压缩比比jpg更高但显示效果却不输于jpg,Android 4.0+才原生支持webp, 但是我们的app是兼容2.3+,所以4.0以下的设备将无法看到图片但不会崩溃。限于Android的支持情况暂时还没用在手机端广泛应用起来。并且直到Android 4.2.1+才支持显示含透明度的webp,官方评测quality参数等于75均衡最佳。

官方介绍: https://developers.google.com/speed/webp/docs/precompiled

2.7 覆盖某些图片

一些aar库里面包含根本就没有用的图。最典型的是support-v4兼容库中包含一些“可能”用到的图片,实际上在你的app中不会用到。可以考虑把几张大一些的图用1×1的图片替换,如果9patch图的话,要做成3×3的9patch图替换。

同理可用于覆盖第三方库中我们用不到的大图,可以在/build/intermediates/exploded-aar/下的各个aar库的res目录查找检验。

2.8 删除armable-v7和x86包下的so

基本上armable的so也是兼容armable-v7的,armable-v7a的库会对图形渲染方面有很大的改进,如果没有这方面的要求,可以精简。这里不排除有极少数设备会Crash,请务必测试周全后再发布。

x86包下的so在x86型号的手机是需要的,如果产品没用这方面的要求也可以精简。

建议实际工作的配置是只保留armable、armable-x86下的so文件,算是一个折中的方案。

我们可以构建一个 APK,它支持所有的 CPU 类型。但是反过来,我们可以为每个 CPU 类型都单独构建一个 APK,然后不同 CPU 类型的设备安装对应的 APK 即可,当然前提是应用市场得提供用户设备 CPU 类型设别的支持,就目前来说,至少 PLAY 市场是支持的。
Gradle 可以通过以下配置生成不同 ABI 支持的 APK(引用自别的文章,没实际使用过):

android {
    ...
    splits {
        abi {
            enable true
            reset()
            include ‘x86‘, ‘x86_64‘, ‘armeabi-v7a‘, ‘arm64-v8a‘ //select ABIs to build APKs for
            universalApk true //generate an additional APK that contains all the ABIs
        }
    }
    // map for the version code
    project.ext.versionCodes = [‘armeabi‘: 1, ‘armeabi-v7a‘: 2, ‘arm64-v8a‘: 3, ‘mips‘: 5, ‘mips64‘: 6, ‘x86‘: 8, ‘x86_64‘: 9]
    android.applicationVariants.all { variant ->
        // assign different version code for each output
        variant.outputs.each { output ->
            output.versionCodeOverride =
                    project.ext.versionCodes.get(output.getFilter(com.android.build.OutputFile.ABI), 0) * 1000000 + android.defaultConfig.versionCode
        }
    }
 }


2.9微信资源压缩打包

微信中的资源混淆工具主要为了混淆资源ID长度(例如将res/drawable/welcome.png混淆为r/s/a.png),同时利用7zip深度压缩,大大减少了安装包体积,同时也增加了逼格,提升了反破解难度。效果非常的好,强烈推荐。

具体实现原理请查看:http://www.iteye.com/topic/1141990

具体使用请查看:https://github.com/shwenzhang/AndResGuard

2.10 着色方案以及使用shape背景

相信你的工程里也有很多selector文件,也有很多相似的图片只是颜色不同,通过着色方案我们能大大减轻这样的工作量,减少这样的文件。借助于androidsupport库可实现一个全版本兼容的着色方案。

具体实现原理请查看:http://www.race604.com/tint-drawable/

在扁平化盛行的当下,很多纯色的渐变的圆角的图片都可以用shape实现,代码灵活可控,省去了大量的背景图片。

2.11 插件化

插件化技术支持动态的加载代码和动态的加载资源,把APP的一部分分离出来了,对于业务庞大的项目来说非常有用,极大的分解了APP大小。因为插件化技术需要一定的技术保障和服务端系统支持,有一定的风险,如无必要(比如一些小型项目,也没什么扩展业务)就不需要了,建议酌情选择。

2.12 资源的重用

同一个图片的着色,阴影,或者旋转版本等等,可以重用同一个资源集合和定制它们。

比如避免帧动画的使用就是一个很好的例子(因为帧动画每一帧都必须是一张明确的图片文件)。

2.13 矢量图的使用

矢量图在Android中以VectorDrawable对象代表(Android L版本引入)。使用VectorDrawable对象,允许开发人员以纯代码方式生成类似绘制的效果。一个100-byte文件可以生成一个屏幕大小清晰图像。

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

具体使用请查看:http://mobile.51cto.com/news-478709.htm

2.14 移除枚举

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

参考资料地址:

http://blog.csdn.net/omnispace/article/details/50991454

http://www.iteye.com/topic/1141990

http://my.oschina.net/u/1244156/blog/196116

http://blog.csdn.net/qq_21445563/article/details/50765300

http://blog.csdn.net/p106786860/article/details/52184847

http://mobile.51cto.com/news-478709.htm

时间: 2024-11-03 13:58:44

Android开发——减小APK大小的相关文章

android产品研发(四)-->减小Apk大小

随着移动技术的深入发展,各种炫酷效果的更新,在我们追求UI与UE的同时一个不如忽视的问题逐渐暴露出来,那就是apk文件越来越大,可能有的童鞋会说现在都是wifi环境,apk文件增大几M不是什么大不了的问题,这其实也是有一定道理的,但是作为开发人员的我们这绝不是我们认为可以忽略这个问题的理由.优化Apk大小也是优化我们App体验的一个重要方面,虽然可能它不是那么的重要. 那么到底是那些原因让我们的Apk文件变得越来越大呢? 多屏幕是适配问题,移动设备的多样化导致了一个app需要N钟不同尺寸的设置,

Android开发---------- 获取apk 软件的资源

APK 是一种 压缩文件. 我们可以直接使用 压缩工具打开:例如 winrar 点击你需要 解压的APK 文件,选择打开方式,使用压缩工具解压: 如图: 2 点击解压到: 解压之后 你就获取到需要的资源文件: 总结: 这样 我们就可以不需要美工的工作,模仿一个 apk   出来了! 简单实用.

Xamarin开发Android应用打包apk

Visual Studio中用Xamarin开发Android应用,生成apk文件有3种方法 1.debug时,代码目录下bin\Debug中会自动生成调试用***-Signed.apk文件,但是文件Size非常大,不建议使用. 2.Release时,“部署”勾选√,生成--部署解决方案后,代码目录下bin\Release中会自动生成部署用***-Signed.apk文件,文件Size比较小. 3.自己打包,工具--Publish Android Application,一步一步设置打包,文件S

Android减包 - 减少APK大小

本文是对Google官方文档 Reduce APK Size 的翻译,点击"阅读原文"可以查看英文原文. 译者简介:damonxia(夏正冬),天天P图Android工程师 用户经常会避免下载看起来体积较大的应用,特别是在不稳定的2G.3G网络或者在以字节付费的网络.这篇文章描述了怎样减少你的APK大小,这会让更多的用户愿意下载你的应用. 理解APK的结构 在讨论怎样减少应用大小之前,先了解APK的结构是有用的.一个APK文件就是ZIP包,其中包含了组成你的应用的所有文件,比如Java

Android开发把项目打包成apk,安卓到手机上,或者提交到app应用商店

#1.用Eclipse的话导出app其实还是很容易的.大家看我的步骤.有图有真相哦 选择一个项目 创建一个新的,位置随便,下面是密码 这里都是一些名字,地区,组织,国家.看你们自己的了 选择你要存放apk的位置 打完收工 Android开发把项目打包成apk,安卓到手机上,或者提交到app应用商店,布布扣,bubuko.com

Android开发学习总结(六)—— APK反编译(转)

学习和开发Android应用有一段时间了,今天写一篇博客总结一下Android的apk文件反编译.我们知道,Android应用开发完成之后,我们最终都会将应用打包成一个apk文件,然后让用户通过手机或者平板电脑下载下来进行安装.正常情况下,Android应用打包成apk之后,就无法再看到开发这个应用时使用的资源文件以及代码了.但是我们通过网上提供了一些工具,还是可以将apk进行反编译的,apk反编译之后,我们就可以看到开发这个应用使用的资源文件(图片).layout.样式.相关的实现代码等,ap

android怎么获取自身apk大小?

很久没更新博客了,前不久看到看到公司的项目中获取app自身大小还是从服务器端反回回来的,还不能用.这么xxx不说了.下面就看看怎么获取自身app的大小的. 注:此处只是获取自己的apk的大小. 首先我们需要的是权限: <uses-permission android:name="android.permission.GET_PACKAGE_SIZE"/> 接下来当然是获取PackageManager了啊: PackageManager mPackageManager=get

Android开发记录20-获取缓存大小和清除缓存功能

Android开发记录20-获取缓存大小和清除缓存功能 转载请注明:IT_xiao小巫 博客地址:http://blog.csdn.net/wwj_748 前言 本篇博客要给大家分享的如何获取应用缓存的大小和清除缓存的功能,我们知道我们应用当中经常会产生一些数据,比如图片的缓存,数据库文件,配置文件等等.我们开发产品的时候,可能会有这样的一个需求清除应用内缓存的数据,可以让用户选择删除应用内产生的数据,这也是比较人性化的设计点.例如笔者参与开发的一款产品的设置界面就提供了清除缓存的功能,如下图所

Android开发学习总结(六)—— APK反编译

学习和开发Android应用有一段时间了,今天写一篇博客总结一下Android的apk文件反编译.我们知道,Android应用开发完成之后,我们最终都会将应用打包成一个apk文件,然后让用户通过手机或者平板电脑下载下来进行安装.正常情况下,Android应用打包成apk之后,就无法再看到开发这个应用时使用的资源文件以及代码了.但是我们通过网上提供了一些工具,还是可以将apk进行反编译的,apk反编译之后,我们就可以看到开发这个应用使用的资源文件(图片).layout.样式.相关的实现代码等,ap