兑现关机动画

实现关机动画

实现关机动画

关机动画和开机动画功能是大体一致的,只是播放的动画不一样而已。

既然关机动画和开机动画如此相似,所以,先了解一下开机动画的流程是怎样的。

. 开机动画的图片存放位置:

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类型变量mShutdownmShutdown为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.cppmain函数中对变量进行赋值,以控制BootAnimation.cpp文件中读取的动画文件的不同。那么在bootanimation_main.cppmain函数中我们该根据什么来对变量进行相应的赋值呢?很自然的想到,只能根据main函数的参数来判断了。那么我们该如何给main函数添加参数呢?本文开始处,曾提到,init.rc文件中开机动画的服务。它会生成一个bootanimationshell的命令。实际上,当你adb shell进入系统之后,执行bootanimation时,它会从bootanimation_main.cppmain函数开始执行,进而播放动画。所以,我们只要系统能执行命令bootanimation 参数名即可,当系统关机时,会执行到frameworks/base/core/java/com/android/internal/app/ShutdownThread.java文件中的beginShutdownSequence函数。默认情况下,会弹出ProgressDialog对话框,提示正在关机操作,先将该段代码注释掉,需要在这里添加实现让系统执行命令bootanimation 参数名的功能即可。那么我们该如何让系统执行该命令呢?有两种方法:

第一种:直接调用系统shell的命令

需要使用ProcessBuilder类,该类可以直接操作shell命令。除此之外,还有一些方法,可以上网查询下。将以下代码添加到ShutdownThread.javabeginShutdownSequence函数的注释后面即可。

        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命令,然后执行它。

至此,就完成了关机动画的所有功能.(希望此文对大家有帮助,谢谢!)