android APK体积大小优化
让我们的apk文件尽可能更小,移除那些未使用的代码和资源文件,节省下载和提高效率。
apk目录和文件大小
拖拽APK到Android Studio的编辑窗口
切换到Project视图,并且双击APK文件
在菜单栏中选择Build > Analyzer APK,并且选择APK
分析项目中主要文件占用APK大小
文件夹(文件) | 具体含义 |
---|---|
assets目录 | 缓存静态数据文件 |
lib目录 | 程序依赖的native库 |
res目录 | 存放应用程序的资源 |
META-INF 目录 | 存放应用程序签名和证书 |
AndroidManifest.xml | 应用程序的配置文件 |
classes.dex文件 | 编译生成dex可执行文件 |
resource.arsc文件 | 资源配置文件 |
其他 | 其他的配置文件 |
分析原因
屏幕适配问题,增加多种资源文件和图片
各种开发框架,第三方lib引入
炫酷的UI、UE效果
冗余代码等
assets 优化
字体文件:可以使用字体资源文件编辑神器Glyphs进行压缩删除不需要的字符从而减少APK的大小。
WEB页面:可以考虑使用7zip压缩工具对该文件进行压缩,在正式使用的时候解压
某些图片:可以使用tinypng进行图片压缩, 目前tinypng已经支持png和jpg图片、.9图的压缩
将缓存文件放到服务端,通过网络下载
bg项目assets文件,里面的分类文件,多语言文件越来越多
res 优化
对于一些不必要的设备尺寸,不必要全部(主要看产品需求);
对资源文件,主要是图片资源进行压缩,压缩工具是 ImageOptim;
一些UI效果可以使用代码渲染替代图片资源;
资源文件的复用,比如两个页面的背景图片相同底色不同,就可以复用背景图片,设置不同的底色;
使用VectorDrawable和SVG图片来替换原有图片 ;
使用SVG不用考虑屏幕适配问题,体积非常小;
如果raw文件夹下有音频文件,尽量不要使用无损的音频格式,比如wav。可以考虑相比于mp3同等质量但文件更小的opus音频格式。
能不用图片的就不用图片,可以使用shape代码实现。
使用WEBP,谷歌的一种图片数据格式,支持有损压缩和无损压缩,支持到Android 4.0+;
- 利用AndResGuard资源压缩打包工具
lib目录优化
限制app支持的cpu架构的数目,app支持 armabi 和 x86 架构就够了;
尽可能的重用so库文件;
混淆代码
混淆—-ProGuard使用,添加minifyEnabled true在你的build.gradle文件中
android { buildTypes { release { shrinkResources true minifyEnabled true proguardFiles getDefaultProguardFile(‘proguard-android.txt'), 'proguard-rules.pro' } } ... }
混淆完成build后,删除和未删除那些资源和代码,ProGuard会输出以下文件在/build/outputs/mapping/release/:
dump.txt
描述.apk文件中所有类文件间的内部结构mapping.txt
列出了原始的类,方法和字段名与混淆后代码间的映射,当你从release版本中收到一个bug报告时,可以用它来翻译被混淆的代码。seeds.txt
列出了未被混淆的类和成员usage.txt
列出了从.apk中删除的代码resources.txt
列出resource被保留的资源
清除无用的资源文件
Resource shrinking 需要和Code shrinking 一起使用。在代码中删除所有未使用的代码后,Resource shrinking才可以知道哪些资源APK程序仍然使用,你必须先删除未使用的代码,Resource才会成为无用的,从而被清除掉。
指定要忽略的资源文件
如果我们希望保留或丢弃特定的资源,需要在项目中创建一个XML文件,并使用resources标签,并指定每个资源保存在工具中tools:keep和每个资源在工具中丢弃 tools:discard。两个属性都可以使用逗号(,)分隔符声明资源名称列表。也可以使用* 作为匹配符,匹配名称。对应代码块如下:
<?xml version="1.0" encoding="utf-8"?> <resources xmlns:tools="http://schemas.android.com/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里面。
启用严格的检测
通常情况下,resource shrinker可以准确地确定资源使用。如果你使用Resources.getIdentifier()动态获取指定资源的Id,在默认情况下,这样资源具有匹配名称的格式为潜在的使用,无法去除。例如,下面的代码将导致所有img_前缀的资源都无法去除。
String name = String.format("img_%1d", angle + 1); res = getResources().getIdentifier(name, "drawable", getPackageName());
resource shrinker 也通过搜索代码中是否包含资源名来判断是否在build的时候删除。
<?xml version="1.0" encoding="utf-8"?> <resources xmlns:tools="http://schemas.android.com/tools" tools:shrinkMode="strict" />
在 resource 文件中指定 shrinkMode,你可以指定 Gradle 在处理该资源文件时候的方式,默认的值为 safe,你也可以将它指定为 strict(只会保留有明确引用的资源,以及处理被 tools:keep 和 tools:discard 标注的资源)
清除未使用的替代资源
Gradle resource shrinker 只删除你在代码中未使用资源,这意味着它不会删除不同的设备配置的可替代资源。如果有必要,你可以使用Android Gradle plugin 的resconfigs属性删除替代资源文件。
例如:我们项目中适配10种国家语言,而项目依赖了v7、v4等其他support包里面包含20种国家语言,那么我们可以通过resconfigs 删除剩余的可替代资源文件,这对于我们APK大小可减少了不少,
以下代码说明了如何限制你的语言资源,只是英语和法语:
android { defaultConfig { ... resConfigs "en", "fr" } }
像上面那样通过resconfig属性指定的语言。未指定的语言的任何资源都被删除。
整理代码
减少一些无用代码库的引用,经常的一个场景就是可能一些代码库已经不需要了,但是还是在代码中引用着,这样做的后果就是无用的代码库也会被编译到apk文件中;
定期进行代码review,这是一个很重要的工作,可以是团队成员之间熟悉彼此代码同时也可以查找出一些自己看不出来的bug以及减小一些无用代码;
做一些代码lint之类的工作,Android studio已经提供了这样的功能,定期执行代码lint操作是一个比较不错的习惯;
如果能在服务端处理的逻辑,最后由服务端处理,这样减少代码和提高容错(服务端可以及时更新)
其他方式
使用ReDex优化(慎用)
ReDex是Facebook开源一个减小安卓app大小以提高性能的工具,内嵌以及清除僵尸代码这样的优化来减小字节码,主要是对Dex进行了优化,能让APK 运行更快,不过需要多测试是否会崩溃。支持插件化
未来对于一些独立业务模块,可以做成插件化动态加载,用户需要使用时,只需下载少部分插件。资源动态加载
我们可以在项目中使用资源动态加载形式,例如:表情,语言,离线库等资源动态加载,减小APK的大小
总结
以上减少apk文件的方式相对来说,你需要将app各方面进行整体考虑,而不是仅仅几个方面的斟酌,在减少apk大小的道路上,一定要掌握好度。