分析APK的大小古人云:工欲善其事,必先利其器,我们得先有利器,下面就是我们常用的分析APK大小工具的利器做一些简单的介绍和使用,帮助我们分析造成APK体积较大的元凶,以便于我们从那些方面入手优化。 使用Android Studio 2.2Android Studio 2.2 新功能直接能分析APK的大小,双击打开就能看到那些占用APK比例大,方法数等。
使用方法:Build -> Analyz APK 有了 NimbleDroidNimbleDroid 是美国哥伦比亚大学的博士创业团队研发出来的自动化分析Android app性能指标的系统,分析的方式有静态和动态两种方式,其中静态分析可以分析出APK安装包中大文件排行榜,各种知名SDK的大小以及占代码整体的比例,各种类型文件的大小以及占排行,各种知名SDK的方法数以及占所有dex中方法数的比例,针对缓慢的方法,缓慢的第三方SDK和内存泄漏。 查看详细的方法耗时 具体使用方法请看官网: 不过需要注意的是不要上传任何未发布的产品。 ClassSharkClassShark 是一款查看Android执行文件(apk)的浏览工具,目前有两个android App(Apk)和桌面(jar)的版本。 具体源码与使用方法详细在github中: 通过以上任一工具分析我们知道我们项目中主要是以下文件占用APK大小:
既然知道了那些数据导致我们APK体积大,那么我们就着手瘦身了。 对APK进行瘦身对资源进行极限压缩对资源进行极限压缩,主要是对如:res里面用到的图片资源文件和assets文件夹下的一些html,db等一些缓存预留在APK的数据文件
通过以上方法我们图片降低了79%的大小。 使用WEBP,SVG图片资源格式
这里提供方便转换的WEBP资源的工具:
利用AndResGuard资源压缩打包工具微信中的资源混淆工具主要为了混淆资源ID长度(例如将res/drawable/icon.png,png变成混淆为r/s/a.png),同时利用7z深度压缩、对png的存储方式做了改变占用内存更小,大大减少了安装包体积 具体源码与使用方法详细在github中: 清除你的代码和资源通过上面的图片资源极限压缩能对APK减小不少,但这往往这些还是不够的,项目里还有很多未使用的资源文件,重复的资源等,这里主要参考Google官方文档https://developer./studio/build/shrink-code.html#shrink-code 部分,利用Android Plugin开启gradle 的
该功能需要依赖于:
清除无用代码code shrinking需要结合ProGuard使用,添加
android { buildTypes { release { minifyEnabled true proguardFiles getDefaultProguardFile(‘proguard-android.txt'), 'proguard-rules.pro' } } ...}
其中
那么我们怎么知道每一次build,删除了和未删除那些资源和代码呢,ProGuard会输出以下文件在
自定义混淆规则在某些情况下,默认的混淆器配置文件
添加-keep来忽略一下防止被混淆的代码到proguard-rules.pro文件中,比如:
另外也可以使用@Keep 注解在你的需要忽略的代码中,需要Annotations Support Library的支持 有关自定义proguard-rules.pro文件的更多信息,可以参考ProGuard Manual.这里Troubleshooting列出了一些常见的问题。 清除无用的资源文件
添加 android { ... buildTypes { release { shrinkResources true minifyEnabled true proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } }}
指定要忽略的资源文件如果我们希望保留或丢弃特定的资源,需要在项目中创建一个XML文件,并使用 相应代码块如下: resourcesxmlns:tools='http://schemas./tools'tools:keep='@layout/l_used*_c,@layout/l_used_a,@layout/l_used_b*'tools:discard='@layout/unused2' />
需要在项目resources目录保存res/raw/keep.xml文件,build的时候该文件不会被打包到APK里面。 启用严格的检测通常情况下, 例如,下面的代码将导致所有img_前缀的资源都无法去除。 String name = String.format('img_%1d', angle + 1);res = getResources().getIdentifier(name, 'drawable', getPackageName());
resourcesxmlns:tools='http://schemas./tools'tools:shrinkMode='strict' />
在 resource 文件中指定 shrinkMode,你可以指定 Gradle 在处理该资源文件时候的方式,默认的值为 safe,你也可以将它指定为 strict(只会保留有明确引用的资源,以及处理被 在后面查看资源回收情况,我们会讲到,会遇到有些xml 无法被清除的问题,使用shrinkMode可以解决这个问题。 清除未使用的替代资源Gradle 例如:我们项目中适配10种国家语言,而项目依赖了v7、v4等其他support包里面包含20种国家语言,那么我们可以通过resconfigs 删除剩余的可替代资源文件,这对于我们APK大小可减少了不少, 以下代码说明了如何限制你的语言资源,只是英语和法语: android { defaultConfig { ... resConfigs 'en', 'fr' }}
像上面那样通过 同样的图片资源我们也可以这么做,例如:我们提供一套xxhdpi的图片资源,其他的都过滤清除掉,这样大量清除了support,其他第三方library的资源文件,关于这个待会我们在后面会说。 合并重复的资源默认情况下,Gradle也将同名的资源,比如相同的名字,可能是在不同的资源文件夹下,这样子不能通过shrinkResources属性来去除。 只有当两个或多个文件共享相同的资源名称、类型和限定符时才发生资源合并,关于资源的合并优先级如下: Gradle 主要从以下位置合并资源:
Gradle合并重复资源优先顺序为: Dependencies → Main → Build flavor → Build type 例如:如果一个重复的资源在你的mian res中和一个Build flavor指定 ,Gradle 会优先选择Build flavor 查看资源回收当你Gradle :android:shrinkDebugResourcesRemoved unused resources: Binary resource data reduced from 2570KB to 1711KB: Removed 33%:android:validateDebugSigning
APK构建完成后会Gradle会生成一个resource.txt 在 /build/outputs/mapping/release/ 中,这个文件包括详细信息,如资源参考其他资源和使用或删除资源的详细信息等。 例如:找出为什么 16:25:48.005[QUIET][system.out]@drawable/add_schedule_fab_icon_anim : reachable=true16:25:48.009 [QUIET] [system.out] @drawable/ic_plus_anim_016
现在需要知道为什么 如果你不使用严格的检查(就是上面讲的 10:32:50.590[QUIET][system.out]Markingdrawable:ic_plus_anim_016:2130837506usedbecauseitformat-stringmatchesstringpoolconstantic_plus_anim_%1$d.
那么这种情况我们如何解决呢,可以通过以下方法来清理:
到这里APK的大小又小了不少。 使用APK Splits构建APK虽然我们上面很好的使用了 例如:那些未使用的多套替代资源,或者是library内部隐患着引用着的资源而我们却没有使用到。或者是我们要根据用户的手机去提供不同版本的APK,如分辨率(xxhdpi,mhdpi等),so库等。那么我们可以使用
多 apk 只支持以下类型:
使用新的 按屏幕密度拆分android { ... splits { density { enable true exclude 'ldpi', 'tvdpi', 'xxxhdpi' compatibleScreens 'small', 'normal', 'large', 'xlarge' } }
构建完成后可以在out/apk/目录下看到多个版本的APK 按 ABI 拆分android { ... splits { abi { enable true reset() include 'x86', 'armeabi-v7a', 'mips' universalApk true } }}
例如:我们项目主要提供xxhdpi的图片资源,而项目中引用到了很多第三方库(v7、v4、google Service 等Libarry资源)我们无法使用到,那么我们可以通过这种方法来去除那些资源。这样我们的APK又减小了非常多。 使用多版本的APK
通过发布有多个APK,我们可以:
目前我们基于这个方案做了不同屏幕的APK。 资源动态加载我们可以在项目中使用资源动态加载形式,例如:表情,语言,离线库等资源动态加载,减小APK的大小。 依赖库优化
支持插件化未来对于一些独立业务模块,可以做成插件化动态加载,用户需要使用时,只需下载少部分插件。 使用ReDex优化ReDex是Facebook开源一个减小安卓app大小以提高性能的工具,内嵌以及清除僵尸代码这样的优化来减小字节码,主要是对Dex进行了优化,能让APK 运行更快,不过需要多测试是否会崩溃。 教程很简单具体更详细的内容请参考: github地址: 关于APK瘦身我们就总结到这了,应该还有很多更好的方案,若有错漏,欢迎补充。 更多Android 之美,请阅读《Android 之美 从0到1 – 高手之路》系列文章 水平有限,若有错漏,欢迎指正,批评,如需转载,请注明出处–http://blog.csdn.net/vfush,谢谢! 作者:fuchenxuan |
|