Android 优化OTA包大小和开机启动时间

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/austindev/article/details/61194249

问题说明

在Android 升级到 5.0 (Lollipop/L)之后,虚拟机实例换成了ART,这加快了应用运行时的速度,但是在系统升级中却引入了一些不便之处:

  1. 在生成升级包时,因为ART采用了预编译优化功能,会把 APK 及JAR等通过dex2ota预编译成odex文件,这样极大的增加了升级包的大小,动辄上G的大小不方便用户的下载和网络的传播;
  2. 如果不进行预编译优化,则这部分操作会转移到刷机完成后第一次开机时间,十几分钟甚至更多的时间,让用户不确认是否升级出问题;

预编译配置-兼顾大小和时间

上述问题,Android系统设计者,早已考虑周全,尤其是针对存储空间有限的设备,提供了丰富的编译配置选项,方便开发者根据自己实际情况进行针对性的配置修改;

下面就针对这些配置选项进行说明和标记,方便后续开发人员参考;

打开odex编译优化

首先,可以完全关闭预编译优化功能,跟dalvik虚拟机时代的升级包相同:

product BoardConfig.mk 文件中,添加编译变量: WITH_DEXPREOPT := true

当然,这样的结果就是升级包小了,第一次开机时间极其慢;

预编译的包不进行优化

预编译的包是指那些在模块编译文件中指定为:include $(BUILD_PREBUILT) 的APK和JAR包等,这在升级包中占了一大部门;
DONT_DEXPREOPT_PREBUILTS 变量就可以配置这部门代码是否进行预编译优化;

DONT_DEXPREOPT_PREBUILTS := true 后,编译系统将会阻止 prebuild 包的odex优化;

只进行BOOT.img 优化

Android启动过程中,boot.img包含了大部分底层系统的启动和初始化,主要包含在boot.art文件中;
使用 WITH_DEXPREOPT_BOOT_IMG_ONLY 编译变量,可以控制编译系统只进行boot.img的优化;
使能该变量后,将会大量节省system分区的大小,但同时意味着所有的app都需要在第一次重启的时候进行odex优化;

所以最好是通过 DONT_DEXPREOPT_PREBUILTS 进行更精确的控制;

LOCAL_DEX_PREOPT 编译变量使用

每个app应用,可以通过该编译变量进行控制是否进行odex优化;
在 app’s Android.mk,进行变量赋值 LOCAL_DEX_PREOPT := false

PRODUCT_DEX_PREOPT_ 编译变量使用

在 post-L 发行版本之后,添加了这个系列的编译变量,进行更深入控制预编译的优化;

  1. PRODUCT_DEX_PREOPT_BOOT_FLAGS 传递参数给 dex2oat 命令,控制boot.img的编译
  2. PRODUCT_DEX_PREOPT_DEFAULT_FLAGS 传递默认参数给 dex2oat 命令,控制除了 boot.img的编译,即jar包和apk文件
 $(call add-product-dex-preopt-module-config,services,--compiler-filter=space) 

或者 直接关闭模块的预编译优化

$(call add-product-dex-preopt-module-config,Calculator,disable) 

Android 7.0 之后的优化

7.0后,系统可以分为A/B两个分区,OTA升级以及APK的优化不影响用户前台的正常使用,这样既减小了升级包的大小,又提升了第一次开机速度;

预加载类文件

预加载类会由zygote统一初始化,这样使后续使用到这些类的app开启速度加快;但是预加载类的使用在实际项目中要非常注意,需要仔细评估后确认权衡值,太多的预加载类会导致一些不常用的类消耗宝贵的内存资源,相反则会导致常用的类在不同应用中独立加载,各自有一个备份,既减慢应用开启速度,也是浪费内存;

预加载类的定义列表,默认放置在 frameworks/base/preloaded-classes ,也可以在产品的devic.mk中添加自行定义的预加载列表:

PRODUCT_COPY_FILES += <filename>:system/etc/preloaded-classes

编译类列表

结合 PRODUCT_DEX_PREOPT_BOOT_FLAGS 和 compiled-classes 可以控制编译系统是否在预编译优化中编译这些类;
不过上述列表只能定义启动类的一个子集,适合用于那些存储空间非常有限,不能全局优化编译整个boot.img 分区的设备,所以对我们来说并不适合;

猜你喜欢

转载自blog.csdn.net/austindev/article/details/61194249