简介随着项目的不断迭代,代码量和资源文件量不断增加。那么打包后的APK文件会越来越大。如果有一天你的老板或领导让你优化APK大小,而你不知道如何优化,那就有点说不通了。本文我们一起来分析和优化。APK大小栏。APK资源使用分析注:在GitHub上找了一个比较火的开源项目。有需要的我可以点击下载自己试试。分析工具直接使用的ASBuild/AnalyzeAPK可以从上图获取,assets>classes.dex>res>lib,其中资源文件占比最大。让我们看看如何减小APK的大小。优化APK大小的八个步骤1.将图片转换为webp格式Webp概念WebP是一种同时提供有损和无损压缩的图片文件格式,源于视频编码格式VP8。WebP最初于2010年发布,目标是减小文件大小,但达到与JPEG格式相同的图像质量,希望减少图像文件在网络上的发送时间。2011年11月8日,谷歌开始启用WebP支持无损压缩和透明色功能。根据谷歌早先的测试,WebP的无损压缩比在网络上找到的PNG文件减少了45%的文件大小,即使这些PNG文件经过PNGCRUSH和PNGOUT处理,WebP仍然可以将文件大小减少28%。按照目前的情况,Webp可以将图像大小平均减少70%。WebP是未来图片格式的发展趋势。PNG/JPG转Webp右击图片或文件夹,选择转换为Webp格式,即可将png/jpg图片压缩成webp格式图片。最后,我们只减少了不到200kb的大小。有可能是项目的图片资源不是很大,而是小图片太多导致的。应用场景及优势客户端软件内嵌基于Chromium的webview。在此类浏览器中应用的网页完全可以使用WebP格式,在不考虑兼容性的情况下提高了加载和渲染速度。对于使用node-webkit开发的程序,使用WebP可以减小文件包的大小。对于手机应用或者网页游戏,界面需要大量图片,可以嵌入WebP的解码包,可以节省用户流量,提高访问速度。优点:对于PNG图片,WebP比PNG小45%。2.去掉multilingual在app/build.gradle中添加android{...defaultConfig{...//reserveonlyEnglishresConfigs"en"}}这里我们发现减少了大约200kb3。通过反编译去掉不需要的so库Android微信版了解到微信只适配了armeabi-v7a架构,所以我们去掉对其他库的支持。android{...defaultConfig{...ndk{//设置支持的SO库架构abiFilters"armeabi-v7a"}}}优化近600kb,继续。4、去除无用资源链接检查(小心删除)概念Lint是AndroidStudio提供的一个代码扫描分析工具,可以帮助我们发现代码结构/质量问题并提供一些解决方案,而且这个过程不需要我们编写测试用例.当代码迭代次数较多时,很容易留下一些无用的代码和资源文件。我们可以使用Lint来清理它们。如何使用LinkInspection打开AS工具,找到Analyze>RunInspectionByName>unusedresourcesoptimization,发现我们的链接优化了700kb左右,继续。注意,因为链接是检查是否有引用来判断资源是否被使用,如果是这种方式,删除时一定要慎重。//动态获取资源id,如果不直接使用R.xx.xx,这个id代表的资源会被认为是未使用的(类似不能混淆的反射类)intindetifier=getResources().getIdentifier("img_bubble_receive","drawable",getPackageName());getResources().getDrawable(indetifier);5.开启混淆,优化1.7M左右继续。6.去除无用资源proguard-rules.pro'}}此链接可能会删除无用资源,因此未进行优化。7、开启删除无用资源(严格模式和普通模式)——这个我这里没法测试,你下来测试一下效果。普通模式即自定义模式如果你有特定的资源想要保留或丢弃,在你的项目中创建一个包含标签的XML文件并在tools:keep属性中指定每个要保留的资源,在tools中指定每个要丢弃的资源在:discard属性中。这两个属性都接受以逗号分隔的资源名称列表。您可以使用星号字符作为通配符。例如:将此文件保存在项目资源中,例如res/raw/keep.xml。Build不会将此文件打包到APK中。指定要丢弃的资源可能看起来很愚蠢,因为您可以删除它们,但在使用构建变体时它会很有用。例如,如果您知道给定的资源表面上在您的代码中使用(因此不会被压缩器删除),但实际上并没有在给定的构建变体中使用,您可以将所有资源放入一个公共项目目录中,然后创建一个每个构建变体都有不同的keep.xml文件。构建工具也可能无法根据需要正确识别资源,因为编译器添加了内联资源ID,并且资源分析器可能不知道实际引用的资源与代码中恰好具有相同值的整数值之间的区别。严格模式正常情况下,资源压缩器可以准确判断系统是否使用资源。但是,如果您的代码调用Resources.getIdentifier()(或您的任何库进行该调用-AppCompat库进行调用),这意味着您的代码将根据动态生成的字符串查找资源名称。当您进行此调用时,默认情况下,资源压缩器将通过将具有匹配名称模式的所有资源标记为可能使用且无法删除来采取防御措施。例如,以下代码会将所有以img_为前缀的资源标记为已使用。Stringname=String.format("img_%1d",angle+1);res=getResources().getIdentifier(名称,"drawable",getPackageName());资源压缩器还会浏览代码和各种res/raw/资源中的所有字符串常量,寻找格式为file:///android_res/drawable//ic_plus_anim_016.png的资源url。如果它找到与其相似的字符串,或其他似乎对构建与其相似的URL有用的字符串,它们将不会被删除。这些是默认启用的安全压缩模式的示例。但是,您可以禁用此“安全”方法并指定ResourceCompressor仅保留它确定使用的资源。为此,请在keep.xml文件中将shrinkMode设置为strict,如下所示:如果你确实启用了严格压缩模式,并且你的代码还引用了包含动态生成字符串的资源(如上所示),你必须手动保留这些资源。8.AndResGuard微信资源压缩解决方案什么是AndResGuardAndResGuard是一个缩小APK体积的工具。它的原理类似于JavaProguard,只是针对资源。会缩短原来很长的资源路径,比如把res/drawable/wechat改成r/d/a。为什么要用AndResGuard在以往的开发中,我们通常只会混淆代码,但是资源文件是暴露给他人的,res文件夹下所有文件名的可读性太强了。使用AndResGuard配置项目根目录build.gradle后的效果,添加插件依赖:dependencies{classpath'com.tencent.mm:AndResGuard-gradle-plugin:1.2.16'}在app目录下,创建and_res_guard。渐变文件。applyplugin:'AndResGuard'andResGuard{mappingFile=nulluse7zip=trueuseSign=truekeepRoot=falsecompressFilePattern=["*.png","*.jpg","*.jpeg","*.gif","re??sources.arsc"]whiteList=[//youricon"R.drawable.icon",//forfabric"R.string.com.crashlytics.*",//forumengupdate"R.string.tb_*","R.layout.tb_*","R.drawable.tb_*","R.drawable.u1*","R.drawable.u2*","R.color.tb_*",//umengshareforsina"R.drawable.sina*",//forgoogle-services.json"R.string.google_app_id","R.string.gcm_defaultSenderId","R.string.default_web_client_id","R.string.ga_trackingId","R.string.firebase_database_url","R.string.google_api_key","R.string.google_crash_reporting_api_key",//友盟"R.string.umeng*","R.string.UM*","R.layout.umeng*","R.drawable.umeng*","R.id.umeng*","R.anim.umeng*","R.color.umeng*","R.style.*UM*","R.style.umeng*",//Fusion云"R.drawable.u*","R.drawable.rc_*","R.string.rc_*","R.layout.rc_*","R.color.rc_*","R.id.rc_*","R.style.rc_*","R.dimen.rc_*","R.array.rc_*"]sevenzip{artifact='com.tencent.mm:SevenZip:1.2.10'}}在app模块下的build.gradle文件中,添加:applyfrom:'and_res_guard.gradle'打包后渲染资源压缩到1M左右总结项目越大,资源越多,效果越明显。如果使用Link删除资源,一定要慎重,提前做好备份,因为项目本身只有22M,我们最后优化到4.5M,还是很不容易的。