system/media/bootanimation.zip,要修改开机动画就是修改bootanimation这个压缩文件。如果不存在该压缩包,使用原生自带的资源,其路径在system/framework/framework-res.apk/assets/images(android-logo-mask.png,android-logo-shine.png),但是比较难看,比较常见的就是“android”。所以要定制自己的开关机动画一般都是在system/media/目录下放置bootanimation.zip和shutanimation.zip.这里以开机动画为例,关机动画和开机动画其原理一样。
bootanimation里面主要包含一个desc.txt以及N个文件夹。而文件夹里面放着的就是开机动画的图片资源。decs.txt的作用就是指导系统如何去执行开机动画。
desc.txt编写规范,例如开机动画需要用到2个文件夹,分别是folder1和folder2,开机的时候,先把folder1里面的图片都播放一遍,然后再循环播放folder2里面的文件,直到进入系统,decs.txt文档的内容如下:
320 480 12
p 1 0 folder1
p 0 0 folder2
320 480是代表屏幕的分辨率,12表示12帧每秒,简单地说12代表一秒钟播放12张图片;
把需要用到的folder文件夹跟decs.txt打包成zip格式,必须是zip,不能是rar,且打包的时压缩方式选择“存储”模式。然后改名成为bootanimation.zip,最后将制作好的zip包push到/system/media目录下。
注意:bootanimation不能太大,一般最好不要超过3M。
1.4 查看动画
在终端中输入命令:
adb shell---> cd /system/bin--->bootanimation 或者bootanimation shut
这样不用重启即可查看定制的动画,方便。
通过上面的准备开机资源已经制作好了,那android是怎么来实现播放的。首先对于开关机动画的播放,android专门使用了一个 native service来实现播放(/system/bin/bootanimation),包括开机铃声的实现也是用该service来实现的。
Android系统在init.rc中定义了很多Service,具体定义格式可以参考《Android Platform Developer’s Guide》中的“Android Init Language”。Init.rc中定义的Service将会被Init进程创建,其中已经定义的服务就包含bootanimation。
每一项服务必须在/init.rc中定义.Android系统启动时,init守护进程将解析init.rc和启动属性服务,属性“ ctl.start ”和“ctl.stop ”是用来启动和停止服务的。一旦收到设置“ ctrl.start ”属性的请求,属性服务将使用该属性值作为服务名找到该服务,启动该服务。这项服务的启动结果将会放入“ init.svc.<服务名>“属性中 。
service bootanim /system/bin/bootanimation
user graphics
group graphics system audio qcom_oncrpc
disabled
oneshot
定义了一个bootanim的服务,对应执行/system/bin/bootanimation
disabled 表示init进程创建只是创建它,但不立刻执行;
oneshot 表示该服务只执行一次;
通过上面可知,bootanimation的调用同故宫clt.start 和ctl.stop来实现的,当我们开机启动时,系统内核起来后,启动android,这时就会启动开机动画具体是在
SurfaceFlinger.cpp的readyToRun方法中调用,为什么会在这调用,请回顾一下开机流程。
status_t SurfaceFlinger::readyToRun()
{
// start boot animation service
property_set("ctl.start", "bootanim");//
}
当android启动完成后,关闭掉开机动画
void SurfaceFlinger::bootFinished()
{
//stop bootanim service
property_set("ctl.stop", "bootanim");
}
BootAnimation_main.cpp
BootAnimation.h
bootAnimation.cpp
该文件是主入口文件;
int main(int argc, char** argv)
{
#if defined(HAVE_PTHREADS)
setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_DISPLAY);
#endif
char value[PROPERTY_VALUE_MAX];
property_get("debug.sf.nobootanimation", value, "0");
int noBootAnimation = atoi(value);
LOGI_IF(noBootAnimation, "boot animation disabled");
if (!noBootAnimation) {
sp proc(ProcessState::self());
ProcessState::self()->startThreadPool();
// create the boot animation object
bool setBoot = true;
bool setRotated = false;
bool sePaly = true;
if(argc > 1){
if(!strcmp(argv[1],"shut"))
setBoot = false;
}
if(argc > 2){
if(!strcmp(argv[2],"nomp3"))
sePaly = false;
}
if(argc > 3){
if(!strcmp(argv[3],"rotate"))
setRotated = true;
}
char volume[PROPERTY_VALUE_MAX];
property_get("persist.sys.mute.state", volume, "-1");
int nVolume = -1;
nVolume = atoi(volume);
if(nVolume == 0 || nVolume == 1 ){
sePaly = false;
}
sp boot = new BootAnimation(setBoot,sePaly,setRotated);
IPCThreadState::self()->joinThreadPool();
}
return 0;
}
其主要的功能是根据传进来的参数决定是是要播放开机还是关机动画/铃音,并且启动BootAnimation;
BootAnimation.cpp集成自Thread,在创建时会调用readyToRun()->threadLoop()。
status_tBootAnimation::readyToRun() {
……………省略………………………
mAndroidAnimation = false;
if(bBootOrShutDown){
status_t err = mZip.open("/data/local/bootanimation.zip");
if (err != NO_ERROR) {
err =mZip.open("/system/media/bootanimation.zip");
if (err != NO_ERROR) {
mAndroidAnimation = true;
}
}
}else {
if(!bShutRotate){
status_terr = mZip.open("/data/local/shutanimation.zip");
if (err != NO_ERROR) {
err =mZip.open("/system/media/shutanimation.zip");
if (err != NO_ERROR) {
mAndroidAnimation = true;
}
}
}
}
return NO_ERROR;
}
readyToRun() 方法判断/system/media/bootanimation.zip(shutanimaion.zip)是否存在,如果存在,则将 mAndroidAnimation 设置false,这个变量决定threadLoop中调用android()还是movie()来具体实现动画的播放。
boolBootAnimation::threadLoop()
{
........省略........
if(!bBootOrShutDown){
pSoundFileName="/data/local/shutaudio.mp3";
pBackupSoundFileName="/system/media/shutaudio.mp3";
} else {
pSoundFileName="/data/local/bootaudio.mp3";
pBackupSoundFileName="/system/media/bootaudio.mp3";
}
if (mAndroidAnimation)
r = android();
} else {
r = movie();
}
}
threadLoop()方法根据 mAndroidAnimation 变量调用android()/movie(). 如果system/media/shutanimation.zip/bootanimation.zip存在的话,调用movie(),该接口会解析zip文件中的desc.txt文件,根据txt文件中的配置来播放动画。否则就调用android来播放原生自带的资源。