part 9 App瘦身优化
Part 9 App瘦身优化
一 瘦身优化及APK分析方案
1、瘦身优势
最主要是转换率:下载转换率(提高用户搜索后的下载几率)
头部App都有Lite版
渠道合作商的要求
2、Apk组成
代码相关:classes.dex
资源相关:res、asserts、resources.arsc
So相关:lib
3、Apk分析
ApkTool,反编译工具
官网:https://ibotpeaches.github.io/Apktool/
命令:apktool d xxx.apk
Analyze APK:Android Studio 2.2之后
查看Apk组成、大小、占比
查看Dex文件组成
Apk对比
https://nimbledroid.com/ (app性能分析)
文件大小及排行
显示dex方法数、SDK方法数
启动时间、内存等信息
android-classyshark:二进制检查工具
https://github.com/google/android-classyshark
支持多种格式:Apk、Jar、Class、So等
使用简单,图形化显示
二 代码瘦身实战
1、代码混淆
花指令,功能等价但改变形式
代码中各个元素改写成无意义的名字
以更难理解的形式重写部分逻辑
打乱代码的格式
Proguard:java类文件处理工具,优化字节码
代码中的元素名称改短,移除冗余代码
增加代码反编译的难度
Proguard使用
配置minifyEnabled为true,debug下不要配置
proguard-rules中配置相应规则
buildTypes {
debug {
minifyEnabled false
shrinkResources false
debuggable true
}
release {
minifyEnabled true
signingConfig signingConfigs.release
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
2、三方库处理
基础库的统一(如:同一种功能的不同的库)
选择更小的库,Android Methods Count(插件,在build.gradle中显示引入的三方库的方法数)
仅引入需要的部分代码:Fresco的webp支持
3、移除无用代码
业务代码只加不减
代码太多不敢删除
AOP统计使用情况
//被使用Task输出log
@After("execution(com.optimize.performance.launchstarter.task.Task.new(..))")
public void newObject(JoinPoint point){
LogUtils.i( " new " + point.getTarget().getClass().getSimpleName());
}
三 资源瘦身实战
1、冗余资源
Android studio中右键、Refactor、Remove Unused Resource
2、图片压缩
快速发展期的App没有相关规范
https://tinypng.com/ 图片压缩网站
TingPngPlugin 插件
图片格式选择
3、资源混淆
https://github.com/shwenzhang/AndResGuard (Android资源混淆工具,使冗长的资源路径变短)
4、其他
图片只保留一份(只放在xhdpi下,其他dpi下会等比例的进行缩放)
资源在线化(将图片资源放在远端,结合预加载的手段)
四 So瘦身实战
1、So移除
So是Android上的动态链接库
七种不同类型的CPU架构
abiFilter:设置支持的So架构
一般选择armeabi(万金油,但是性能有所损耗)
ndk {
abiFilters 'armeabi'
}
2、更优方案
完美支持所有类型设备代价太大
都放在armeabi目录,根据CPU类型加载对应架构So
https://www.cnblogs.com/dongweiq/p/6824727.html (Android SO文件的兼容和适配)
https://blog.csdn.net/DJY1992/article/details/78890252 (Android 静态和动态的调用so库(JNI))
//伪代码演示逻辑
String abi = "";
//获取abi类型
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP){
abi = Build.CPU_ABI;
}else {
abi = Build.SUPPORTED_ABIS[0];
}
//根据abi类型进行相应的加载
if (TextUtils.equals(abi,"ARMv7")){
//加载特定平台的so
}else {
//正常加载
}
3、其他方案
So动态加载
插件化