1. Android 开机动画的基本机制
Android 的开机动画由 bootanimation
进程控制,它会读取 /system/media/bootanimation.zip
或 /product/media/bootanimation.zip
,然后按照配置播放开机动画。
动画格式
Android 的开机动画是一个 ZIP 压缩包,里面包含多个帧图片,以及一个 desc.txt
配置文件。
存放路径
/system/media/bootanimation.zip
/product/media/bootanimation.zip
/oem/media/bootanimation.zip
(某些设备)
系统会按照以上顺序查找,找到后即播放。
2. 制作开机动画
创建开机动画资源
开机动画是一组连续播放的帧动画,一般包含多个子文件夹,每个文件夹代表动画的一个阶段。
目录结构
makefile
bootanimation.zip
│── desc.txt
│── part0/
│ ├── 001.png
│ ├── 002.png
│ ├── ...
│── part1/
│ ├── 001.png
│ ├── 002.png
│ ├── ...
desc.txt
:定义动画播放规则part0/
、part1/
:存放帧图片,每个文件夹对应动画的不同阶段
desc.txt
配置
desc.txt
是动画的描述文件,定义了动画的播放规则。其格式如下:
第一行:定义动画的全局参数
makefile
WIDTH HEIGHT FPS
WIDTH
:动画的宽度(像素)。HEIGHT
:动画的高度(像素)。FPS
:帧率(每秒播放的帧数,例如 60)。
后续行:定义每个动画段的播放规则
makefile
TYPE COUNT PAUSE PATH [#RGBHEX CLOCK]
TYPE
:动画段的类型:p
:可被暂停的动画段。c
:必须播放完成的动画段(一般不会用这个,会影响开机速度)。
COUNT
:动画段的播放次数:0
:无限循环,直到开机完成。1
或其他正整数:播放指定次数。
PAUSE
:动画段结束后停留的帧数。PATH
:动画段对应的资源目录(如part0
)。#RGBHEX
(可选):背景颜色,格式为#RRGGBB
。CLOCK
(可选):显示当前时间的 Y 坐标(用于智能手表等设备)。
示例 desc.txt
文件
makefile
1080 360 60
c 1 0 part0 #ffee00
c 0 0 part1 #ffee00
c 1 0 part2 #ffee00
c 1 1 part3 #ffee00
c 1 0 part4 #ffee00
- 动画分辨率为 1080x360,帧率为 60 FPS。
part0
播放 1 次,不暂停。part1
无限循环,直到开机完成。part2
播放 1 次,不暂停。part3
播放 1 次,结束后停留 1 帧。part4
播放 1 次,不暂停。
3. 打包为 ZIP 文件
将 desc.txt
和所有动画资源目录(如 part0
, part1
等)打包为 bootanimation.zip
。
makefile
zip -r -X -Z store bootanimation part*/* desc.txt
当前目录下执行上面命令即可。
-r
:递归打包。-X
:不包含额外的文件属性。-Z store
:使用存储模式(不压缩,加快加载速度)。
4. 部署到 Android 设备
手动替换
将 bootanimation.zip
直接推送到设备(注意要用 userdebug 版本):
makefile
adb root
adb remount
adb push bootanimation.zip /system/media/bootanimation.zip
adb reboot
5. Framework 源码分析
bootanimation
的源码在frameworks/base/cmds/bootanimation/
,核心逻辑在BootAnimation.cpp
。
makefile
[BootAnimation.cpp] threadLoop() -> movie() -> playAnimation()
movie
中读取 zip 文件封装成animation
,然后初始化了一些变量和画布,并调用playAnimation
方法。playAnimation()
中递归读取part
,for
循环加载图片。
6. 定制厂商开机动画
在源码根目录创建 vendor
目录,用于存放厂商特定的东西。
== 如果是接手别人的项目,开机动画可能在源码中某个目录下创建的,一般也是自定义的文件夹 == 接着创建 bootanimation 文件夹,用于专门存放开机动画 将上面制作好的动画压缩包放到该文件夹下 在 vendor
目录下,创建 vendor_product.mk
文件,增加命令,拷贝动画 zip 到编译产物的 system/media
⽬录下:
bash
PRODUCT_COPY_FILES += \
vendor/bootanimation/bootanimation.zip:system/media/bootanimation.zip
此时在编译工程中该编译文件,不会执行,因为没有任何地方引用,如果需要让 vendor_product.mk
执行,就需要把它引入到另一个肯定会编译到的.mk
文件中 ,这时候就要用到:
bash
$(call inherit-product, <file-path>)
$(call inherit-product, <file-path>)
是 编译系统中的 Makefile 语法,它用于 在当前编译环境中引入另一个 .mk
文件,并执行其中的变量和命令。
这个肯定会编译到的文件,一般是配置设备属性的.mk
文件(不同版本系统 文件名可能不一样),将 $(call inherit-product, vendor/vendor_product.mk)
放入到该文件内就行了。 比如在上篇文章中 lunch 的是 sdk_phone_x86_64-eng
就可以找到build/target/product/sdk_phone_x86_64.mk
文件,在该文件中可以看到系统设置中显示的一些系统配置属性,然后将 vendor_product.mk
加进去即可,后面在编译的时候vendor_product.mk
就能被找到并编译了。
如果编译过程中出现类似以下内容报错:
bash
build/make/core/artifact_path_requirements.mk:26: warning:
build/make/target/product/sdk_phone_x86_64.mk produces files inside
build/make/target/product/generic_system.mks artifact path requirement.
Offending entries:
system/media/bootanimation.zip
In file included from build/make/core/main.mk:1342:
build/make/core/artifact_path_requirements.mk:26: error: Build failed.
是因为 违反了 make 规则,需要将以下内容增加到 vendor_product.mk
:
bash
PRODUCT_ARTIFACT_PATH_REQUIREMENT_ALLOWED_LIST += \
/system/media/bootanimation.zip
然后执行以下命令,编译镜像文件,注意先按上篇文章说的,在 out/target/product/emulator_x86_64/
目录下搜索 .img
文件,全部删除!
bash
source build/envsetup.sh
//选择上次编译过的机型
lunch sdk_phone_x86_64-eng
//启动模拟器
emulator -writable-system
就可以查看效果了:)