在制作了自定义开机动画后,想要在真机上预览效果时,可以通过 Android 的 bootanimation 服务来实现。该服务会在系统启动时播放 /system/media/bootanimation.zip 等路径下的动画资源。由于源码中开机动画路径已写死,我们需要借助一些技巧来临时替换并启动动画服务进行预览。
修改当前开机动画
原生的 BootAnimation 并未提供直接播放自定义动画的参数。阅读 BootAnimation.cpp 源码可以发现,系统默认的开机动画路径是硬编码在代码里的,如下所示:
// BootAnimation.cpp
static const char OEM_BOOTANIMATION_FILE[] = "/oem/media/bootanimation.zip";
static const char PRODUCT_BOOTANIMATION_DIR[] = "/product/media/";
static const char PRODUCT_BOOTANIMATION_FILE[] = "bootanimation.zip";
static const char SYSTEM_BOOTANIMATION_FILE[] = "/system/media/bootanimation.zip";
static const char APEX_BOOTANIMATION_FILE[] = "/apex/com.android.bootanimation/etc/bootanimation.zip";
static const char OEM_SHUTDOWNANIMATION_FILE[] = "/oem/media/shutdownanimation.zip";
static const char PRODUCT_SHUTDOWNANIMATION_FILE[] = "/product/media/shutdownanimation.zip";
static const char SYSTEM_SHUTDOWNANIMATION_FILE[] = "/system/media/shutdownanimation.zip";上述代码来自 Android 14 的 BootAnimation 模块,可见系统会依次在 /oem/media/、/product/media/、/system/media/ 等路径下查找 bootanimation.zip。由于路径写死在二进制中,直接修改二进制并不现实;而各厂商定制的路径可能也略有不同,因此需要自行确定设备上的实际路径。
我们可以利用 Linux 的 挂载绑定(mount --bind) 技术,临时将设备存储(如 /sdcard)中的自定义动画包替换到系统路径。例如,假设系统默认动画路径为 /my_product/media/bootanimation/bootanimation.zip,而我们想预览的动画包放在 /sdcard/bootanimation.zip,可以执行
mount --bind /sdcard/bootanimation.zip /my_product/media/bootanimation/bootanimation.zip这样即可暂时用自定义的 bootanimation.zip 覆盖系统默认动画(该操作需要 root 权限)
启动 BootAnimation 预览
要启动开机动画预览,需要设置 SurfaceFlinger 中的启动属性。在 StartPropertySetThread.cpp 中可以看到如下代码
// StartPropertySetThread.cpp
bool StartPropertySetThread::threadLoop() {
// Set property service.sf.present_timestamp, consumer need check its readiness
property_set(kTimestampProperty, mTimestampPropertyValue ? "1" : "0");
// Clear BootAnimation exit flag
property_set("service.bootanim.exit", "0");
property_set("service.bootanim.progress", "0");
// Start BootAnimation if not started
property_set("ctl.start", "bootanim");
// Exit immediately
return false;
}或者参考文档中的说明:执行 property_set("ctl.start", "bootanim") 会启动 bootanim 进程,而 property_set("ctl.stop", "bootanim") 则会停止它;同时 BootAnimation 进程会周期检查系统属性 service.bootanim.exit,当其值为 1 时退出动画,为 0 时播放动画
因此,执行以下命令即可启动预览(需要在设备的 adb shell 或终端内执行,该操作需要 root 权限):
setprop service.bootanim.exit 0
setprop service.bootanim.progress 0
setprop ctl.start bootanim上述命令会清除退出标志、重置进度,并通过 ctl.start 向 init 进程发送启动 bootanim 服务的指令,从而播放我们刚才挂载的自定义开机动画
停止预览
预览完成后,可以通过以下命令停止 bootanim 服务(该操作需要 root 权限):
setprop ctl.stop bootanim
setprop service.bootanim.exit 1这样 bootanim 进程会被停止,并将退出属性置为 1,结束动画显示