Android开发——减小APK大小

Posted SEU_Calvin

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android开发——减小APK大小相关的知识,希望对你有一定的参考价值。

0. 前言

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

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

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

 

1. APK的组成结构

META-INF包含CERT.SFCERT.RSA签名信息

assets存放不需要被编译处理的文件,代码中可以通过AssetManager对象访问。

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

lib包含各个CPU架构下的so文件。子文件目录有armeabiarmeabi-v7a,arm64-v8a,x86,x86_64mips

resources.arsc编译后的二进制资源文件。包括图片、布局文件等。

classes.dex包含Java源码编译后生成的字节码文件,以DalvikART虚拟机能理解的dex文件格式。

AndroidManifest.xml核心的Android描述清单文件。这个文件罗列了APP名称,版本,访问权限,和APP引用的库文件等等。

 

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

2.1 Lint工具

使用Android Lint工具,检测res目录下没有被引用的资源(并没有扫描assets目录下的资源)。

lint工具在你的项目中发现一个潜在的未使用的资源,它会打印一条如下示例的消息。只提醒,不主动移除。 

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


2.2 使用Gradle的ShrinkResources

在Gradle中将shrinkResources和minifyEnabled设置为true。这样在构建的过程中,首先ProGuard会移除没有使用的代码,接着Gradle会移除没有使用的资源

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

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

-keepattributes SourceFile,LineNumberTable

2.3 使用一套资源

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


2.4 只保留中文的语言资源

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

android {
    defaultConfig {
        resConfigs "zh"
    }
}


2.5 关于PNG图片和JPG图片

Android打包本身会对png进行无损压缩,Android的界面能用png最好是用png,因为32位的png颜色过渡平滑且支持透明。在res下这些icon用的都是png格式,就是说Google推荐使用的是png格式的图片 

【拓展】TinyPNG使用智能有损压缩技术,在尽量少的损失下来减少PNG文件的大小。具体TinyPNG的信息请访问https://tinypng.com/

jpg是像素化压缩过的图片,如果对于非透明的大图,jpg将会比png的大小有显著的优势,虽然不是绝对的,但是通常会减小到一半都不止。jpg质量已经下降了,再拿来做9path的按钮和平铺拉伸的控件必然惨不忍睹,要尽量避免。


2.6 关于WEBP图片

相对于jpgpngwebp作为一种新的图片格式,压缩比比jpg更高但显示效果却不输于jpgAndroid 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×39patch图替换。

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


2.8 删除armable-v7x86包下的so

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

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

建议实际工作的配置是只保留armablearmable-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 移除枚举

一个枚举会增加你的appclass.dex文件大约1.01.4K的大小。对于复杂的系统或者共享库这种情况会更加明显。如果可能的话,考虑使用@IntDefProGuard剥离枚举,并转换成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



以上是关于Android开发——减小APK大小的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Android 中减小 APK 大小?

如何在 Android 中减小 APK 大小?

如何在 Android 中减小 APK 大小?

IONIC Android Apk 文件大小太大了!如何减小安卓应用程序的大小?

如何在 android studio 中减小 Apk (.apk) 的大小

使用矢量可绘制减小 apk 大小