一、如何减少apk体积
1、将图片转换成webp
- 将图片资源转换为webp格式,Android studio自带转换功能,但是需要注意这个需要api的等级最低为Android 4.3(>=18)
- 现在Android建议的最低适配版本为5.1,api条件可以忽略
2、去除多语言
- 主要是v7包下会适配多国语言,其实业务场景可能根本用不上,所以可以在app的build.gradle中的defaultConfig中设置
resConfigs 'zh-rCN'
- 注意:若项目只有中文语言,这里去除的是引用的第三方库中的多语言
3、只保留armeabi-v7a
- 国内只保留armeabi-v7a
- 国外至少需要armeabi-v7a+arm64-v8a(必须要有的,不然就下架),这是因为从2019年8月1谷歌应用市场必须要支持arm64-v8a,但是可以采用谷歌提供的App Bundle方式去减少用户将要下载apk的体积
4、移除和压缩无用资源
(1)Link
- 通过Link检测移除掉无用的资源,(移除的时候一定要慎重移除,不然会导致错误)
// 不仅仅能检测到你静态引用到的R.drawable.xxx资源文件
// 还可以检查到如下动态获取的资源文件
int indetifier =getResources().getIdentifier("xxx", "drawable", getPackageName());
getResources().getDrawable(indetifier);
- 注意:并不能检索到所有无用资源(如drawable、xml在某个Activity中被使用,但该Activity无用),且检索到的不一定是无用的(如使用其他的方式使用)。所以检索到后,需要通过全局搜索确定是否真的无用
(2) shrinkResources
- 通过shrinkResources压缩无用资源,这主要是解决上述方式无法检测到的,例如在一个Activity中的setContext中使用了某个xml布局,但是这个Activity可能项目中没有任何一个地方去使用到它,这个时候可以通过该方式检测到并且自动压缩
buildTypes {
release {
// 必须配合minifyEnabled为true才能开启
minifyEnabled true
shrinkResources true
}
}
- 注意:xml压缩结果只剩下头标签,中间的内容全部被清除
(3)开启严格模式并自定义要保留的资源
// 在res/raw/keep.xml
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools"
tools:shrinkMode="strict"
tools:keep="@layout/base_*,@layout/test.xml"
tools:discard="@layout/unused2" />
5、开启混淆(上线应用都会去做的)
- 主要是利用ProGuard去进行压缩、优化和混淆。
- 压缩:移除未被使用的类、属性、方法等,并且会在优化动作执行之后再次执行(因为优化后可能会再次暴露一些未被使用的类和成员,循环下去,直至没有无用的类、属性、方法等)
- 优化:优化字节码,并删除未使用的结构
- 混淆:将类名、属性名、方法名混淆为难以读懂的字母
6、减少引入的第三方库体积
- 第三方库去掉库与库之间重复的引用或者只引用部分需要的代码
- 注意:
- 第三方库之间重复的引用:若A和B都引用的C,这种情况下可以去掉其中一个的引用。最后so库打包到一个地方,A、B是可以共用一个C的
- 只引用部分需要的代码:可以手动删去不需要的部分,缺点是无法自动更新,使用于在可预见的时间内,不会有大改动
7、AndResGuard微信资源压缩方案(只针对资源文件)
- AndResGuard是一个缩小APK大小的工具,它的原理类似Java Proguard,但是只针对资源。它会将原本冗长的资源路径变短,例如将res/drawable/wechat变为r/d/a
- 还可以解决在以往的开发中,我们通常只混淆了代码,资源文件却暴露在他人面前,res文件夹下所有文件名的可读性过强的问题
8、Aconfont
- 把多个纯颜色的webp图片,转成一个.ttf字体文件,能在webp的基础上再减少50-75%的集体。最终通过github上面的一个关于Aconfont实现的开源方案,完成字体文件中对应图片的加载
9、动态下发so库
二、App Bunlder(针对国外应用)
- 因为国外应用都是发布到Google应用市场的,谷歌应用市场有一个Android App Bundle,其实它是一个发布格式,其中包含你应用所以编译后的代码和资源,它将apk的生成和签名交给Google Play来完成。
- 然后用户在Goole Play下载apk的时候,可以使用App Bundle不同的手机组成不同的apk,从而达到减少apk体积的作用
三、如何动态下发so库
- 通过System#loadLibrary(libxxx.so)加载so库,Android Framework会遍历当前上下文的ClassLoader实例里的nativeLibraryDirectories数组,在数组里所有的文件路径下查找文件名为libxxx.so的文件,所以我们的解决思路就是在安装好so插件之后,将其所在的内部安全路径注入到这个nativeLibraryDirectories数组里,即可实现so库的动态下发
四、CPU 架构
- armeabi-v7a:第7代及以上的 ARM 处理器,2011年大部分设备使用
- arm64-v8a:第8代、64位 ARM 处理器,极少数设备,如三星 Galaxy S6
- armeabi:第5、6代 ARM 处理器,早期手机
- x86:平板、模拟器
- x86-64:64位的平板