关机动画和开机动画功能是大体一致的,只是播放的动画不一样而已。
既然关机动画和开机动画如此相似,所以,先了解一下开机动画的流程是怎样的。
一. 开机动画的图片存放位置:
1. 默认位置
/development/data/etc/bootanimation.zip
2. 不同的项目存放的位置
/device/qcom/项目名称/bootanimation.zip
二. 开机动画的服务
1. 文件位置
/system/core/rootdir/init.rc
该文件定义了许多的服务,其中就定义了开机动画的服务,代码如下:
service bootanim /system/bin/bootanimation
user graphics
group graphics
disabled
oneshot
以上代码我所理解的含义是这样了,这是个服务。解析之后,会生成一个bootanimation的shell命令, 以后通过adb shell进入系统,执行bootanimation命令之后会启动该服务。至于字符串bootanim,它是唯一标识,用来表示该shell命令。
三. 播放动画
1. 文件位置
/frameworks/base/cmds/bootanimation/BootAnimation.cpp
/frameworks/base/cmds/bootanimation/BootAnimation.h 头文件
/frameworks/base/cmds/bootanimation/bootanimation_main.cpp 入口文件
BootAnimation.cpp主要用来读取bootanimation.zip文件,然后播放动画。函数readToRun用来读取动画文件,如下代码:
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;
}
}
以上便是开机动画的主要文件,那么,我们该如何实现关机动画呢?
显然,开机动画和关机动画只是读取的动画文件不同而已,那么,在BootAnimation.cpp的函数readToRun中读取动画文件时,需要加入一个标志来判断,如果是开机,则读取开机动画,如果是关机,则读取关机动画。因此,我们我们加入一个bool类型变量mShutdown,mShutdown为true表示关机。修改BootAnimation.h头文件,增加变量mShutdown,考虑到外界需要对这个变量进行设值来控制,提供一个函数isShutdown,添加如下申明:
void BootAnimation::isShutdown(bool shutdown);
修改BootAnimation.cpp文件,实现函数isShutdown。实现代码如下:
void BootAnimation::isShutdown(bool shutdown){
mShutdown = shutdown;
}
另外,修改函数readToRun读取动画文件的部分,实现代码如下:
if(!mShutdown){
LOGD("boot strap");
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 {
LOGD("shutdown");
status_t err = mZip.open("/data/local/shutdownanimation.zip");
if (err != NO_ERROR) {
err = mZip.open("/system/media/shutdownanimation.zip");
if (err != NO_ERROR) {
mAndroidAnimation = true;
}
}
mShutdown = false;
}
代码中可以看出,程序会从/system/media/下读取bootanimation.zip和shutdownanimation.zip文件,因此,先制作一个shutdownanimation.zip文件,参考bootanimation.zip文件,放在路径/development/data/etc/或者/device/qcom/项目名称/目录下。并且修改mk文件。增加如下代码:
device/qcom/xxx/shutdownanimation.zip:system/media/shutdownanimation.zip。
这样才能通过mk命令将此文件shutdownanimation.zip复制到system/media/下,所以代码中是到/system/media/下找相关文件。
另外,尽管变量mShutdown的默认值是false的,但为了保险起见,最好在BootAnimation.cpp的构造函数中人为添加mShutdown = false。
至此,播放动画的逻辑完成。接下来,我们该如何做呢?既然,播放动画的逻辑是根据变量mShutdown来控制的。那么,我们该在哪里给变量赋值来达到控制的要求呢?
肯定是在bootanimation_main.cpp文件中,因为它是入口文件,会在BootAnimation.cpp文件之前执行。在bootanimation_main.cpp的main函数中对变量进行赋值,以控制BootAnimation.cpp文件中读取的动画文件的不同。那么在bootanimation_main.cpp的main函数中我们该根据什么来对变量进行相应的赋值呢?很自然的想到,只能根据main函数的参数来判断了。那么我们该如何给main函数添加参数呢?本文开始处,曾提到,init.rc文件中开机动画的服务。它会生成一个bootanimation的shell的命令。实际上,当你adb shell进入系统之后,执行bootanimation时,它会从bootanimation_main.cpp的main函数开始执行,进而播放动画。所以,我们只要系统能执行命令bootanimation 参数名即可,当系统关机时,会执行到frameworks/base/core/java/com/android/internal/app/ShutdownThread.java文件中的beginShutdownSequence函数。默认情况下,会弹出ProgressDialog对话框,提示正在关机操作,先将该段代码注释掉,需要在这里添加实现让系统执行命令bootanimation 参数名的功能即可。那么我们该如何让系统执行该命令呢?有两种方法:
第一种:直接调用系统shell的命令
需要使用ProcessBuilder类,该类可以直接操作shell命令。除此之外,还有一些方法,可以上网查询下。将以下代码添加到ShutdownThread.java的beginShutdownSequence函数的注释后面即可。
String[] cmds = {"bootanimation","-shutdown"};
try{
ProcessBuilder builder = new ProcessBuilder(cmds);
builder.directory(new File("/")) ;
builder.redirectErrorStream (true) ;
builder.start();
} catch(Exception e) {
e.printStackTrace();
}
通过以上代码,系统会执行bootanimation -shutdown的shell命令。在bootanimation_main.cpp文件中main函数需要判断参数名是否是-shutdown,判断是否是关机。修改bootanimation_main.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");
argc--;
argv++;
if (!noBootAnimation) {
sp<ProcessState> proc(ProcessState::self());
ProcessState::self()->startThreadPool();
// create the boot animation object
sp<BootAnimation> boot = new BootAnimation();
if (argc > 0) {
LOGD(argv[0]);
if (!strcmp(argv[0],"-shutdown")) {
boot->isShutdown(true);
}
}
IPCThreadState::self()->joinThreadPool();
}
return 0;
}
第二种:在init.rc文件中添加一个类似于开机动画service
代码如下:
service shutdownanim /system/bin/bootanimation -shutdown
user graphics
group graphics
Disabled
通过以上代码,shutdownanim代表了bootanimation -shutdown的shell命令。
在ShutdownThread.java文件的beginShutdownSequence函数的注释后面添加如下代码:
SystemProperties.set("ctl.start","shutdownanim");
通过该段代码,系统会寻找标识符为shutdownanim的shell命令,然后执行它。
至此,就完成了关机动画的所有功能.(希望此文对大家有帮助,谢谢!)