开机关机动画工作流程
16lz
2021-01-24
开机关机动画工作流程
一,开机画面切换过程
(1) Linux 系统启动,出现Linux小企鹅画面(由内核实现)。 (2) Android平台启动初始化,出现"A N D R I O D"文字字样画面。 (3) Android平台上层图形系统启动,出现含闪动的ANDROID字样的动画图片(start)。二,(2)和(3)启动运行的过程
(1) Android 系统启动后,init.c中main()调用load_565rle_image()函数读取/initlogo.rle(一张565 rle压缩的位图),如果读取成功,则在/dev/graphics/fb0显示Logo图片;如果读取失败,则将/dev/tty0设为TEXT模式,并打开/dev/tty0,输出文本“A N D R I O D”字样。E8,E9已经将此部分会直接路过,E8直接注释此过程 相应代码如下:相关代码:
- staticintconsole_init_action(intnargs,char**args)
- {
- intfd;
- chartmp[PROP_VALUE_MAX];
- if(console[0]){
- snprintf(tmp,sizeof(tmp),"/dev/%s",console);
- console_name=strdup(tmp);
- }
- fd=open(console_name,O_RDWR);
- if(fd>=0)
- have_console=1;
- close(fd);
- /*
- //查看init.h文件
- //#defineINIT_IMAGE_FILE"/initlogo.rle"
- //ADBSHELL查看根目录没有此张图片
- //加载initlogo.rle文件
- if(load_rle_image(INIT_IMAGE_FILE)){
- //此时fd是/dev/tty0对应的是输出端口
- //tty1表示输入端口,tty2貌似表示错误信息
- fd=open("/dev/tty0",O_WRONLY);//将/dev/tty0设为text模式
- if(fd>=0){
- constchar*msg;
- msg="\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"//consoleis40colsx30lines
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "ANDROID";
- write(fd,msg,strlen(msg));
- close(fd);//关闭接口
- }
- }
- */
- return0;
- }
*.rle文件的制作步骤:
- system/core/init/init.c
- system/core/init/init.h
- system/core/init/init.rc
- system/core/init/logo.c
(2),开机动画(闪动的ANDROID字样的动画图片) 我们最主要经常要修改的这是这部内容,这里包含两种动画类型: 1,第一种类似于Windows系统的滚动条,是由前景和背景两张PNG图片组成,对应原文件位于frameworks/base/core/res/assets/images/。前景图片(android-logo-mask.png)上的Android文字部分镂空,背景图片(android-logo-shine.png)则是简单的纹理。系统登录时,前景图片在最上层显示,程序代码(BootAnimation.android())控制背景图片连续滚动,透过前景图片文字镂空部分滚动显示背景纹理,从而实现动画效果。 图片1: 前景图片 图片2: 背景图片 2,制件开机动画包,开机动画服务程序启动以后会先在系统指定目录检查此包是否存在,如果存在,系统将执行此包中的动画,如果检查系统不存在此包,此时系统才会去按第一方式播放动画,这里包中的内容是通过一张一张图片连续播放来实现动画效果的,最后要生成一个类似bootanimation.zip的包 3,执行过程,init.c解析init.rc(其中定义服务:“service bootanim /system/bin/bootanimation”),bootanim服务由SurfaceFlinger.readyToRun()(property_set("ctl.start", "bootanim");)执行开机动画、bootFinished()(property_set("ctl.stop", "bootanim");)执行停止开机动画。 BootAnimation.h和BootAnimation.cpp文件放在了/frameworks/base/cmds/bootanimation目录下了,增加了一个入口文件bootanimation_main.cpp。Android.mk文件中可以看到,将开机动画从原来的SurfaceFlinger里提取出来了,生成可执行文件:bootanimation。 Android.mk代码如下: //=============Android.mk====================== LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) LOCAL_SRC_FILES:= / bootanimation_main.cpp / BootAnimation.cpp # need "-lrt" on Linux simulator to pick up clock_gettime ifeq ($(TARGET_SIMULATOR),true) ifeq ($(HOST_OS),linux) LOCAL_LDLIBS += -lrt endif endif LOCAL_SHARED_LIBRARIES := / libcutils / libutils / libui / libcorecg / libsgl / libEGL / libGLESv1_CM / libmedia LOCAL_C_INCLUDES := / $(call include-path-for, corecg graphics) LOCAL_MODULE:= bootanimation include $(BUILD_EXECUTABLE) //========================================== 开机动画第一个入口:bootanimation_main.cpp int main(int argc, char** argv) { ….......... if (!noBootAnimation) { sp<ProcessState> proc(ProcessState::self()); ProcessState::self()->startThreadPool(); //初始化开机动画,开始播放开机动画.booted传下去的开机操作还是关机操作的参数 sp<BootAnimation> boot = new BootAnimation(booted); //初始化开机声音,开始播放开机声音.这个类是根据开机动画自定义的,可根据需求自行修改删除 sp<BootAnimationSound> bootsound = new BootAnimationSound(booted); IPCThreadState::self()->joinThreadPool(); } } 根据bootanimation_main.cpp将会初始化 BootAnimation类.下面我们来查看 BootAnimation.cpp文件.通过BootAnimation 构造函数来初始化 sbootanimation变量.根据sbootanimation来实现开关机播放不同的动画.判断开机还是关机可通过上面传过来的参数确定 BootAnimation::BootAnimation(bool shutdownAnimation) : Thread(false) { mSession = new SurfaceComposerClient(); mShutdownAnimation = shutdownAnimation; //权宜之计 if (mShutdownAnimation) { // 关机时播放的动画包 mSession->setOrientation(0, 0, 0); sprintf(sbootanimation, "/system/media/shutdownanimation.zip"); }else{ // 开机时播放的动画包 sprintf(sbootanimation, "/system/media/bootanimation.zip"); } } 此处可以看到 sbootanimation定义是一个zip包路径,通过这个我们可以知道,如果要通过第二种方法实现开关机动画可将制作的zip包放在/system/media/目录下文件名一致便可以了,后面会给出制作zip包的方法。如果是用第一种方法只需修改上面提到的两个图片即可。 mSession->setOrientation(0, 0, 0);此条语句是关机强制横屏,修改可通过第二个参数修改.值分别对应(0->0度,1->90度,2->180度,3->270度,)具体可修改查看效果 根据mAndroidAnimation的值来确定是播放第一种动画效果还是第二种动画效果 BootAnimation::threadLoop() if (mAndroidAnimation) { r = Android(); // 执行android字体闪动的图片 } else { r = movie(); // 执行bootanimation.zip中提供的动画图片 } ==> BootAnimation::Android()会加载"images/android-logo-mask.png"和"images/android-logo-shine.png" ==> BootAnimation::movie()会加载bootanimation.zip中的内容 这里是开机动画,下面是开机音乐的代码,流程跟开机动画类型 BootAnimationSound.cpp 和开机动画一样, 初始化bootsound变量,来实现开关机播放不同的音乐,判断开机还是关机可通过上面传过来的参数确定 BootAnimationSound::BootAnimationSound(bool booted) : Thread(false) { mShutdownAnimation = booted; if (mShutdownAnimation) { // 关机时播放的声音 sprintf(bootsound, "system/media/audio/ui/power_off.mp3"); }else{ // 开机时播放的声音 sprintf(bootsound, "system/media/audio/ui/power_on.mp3"); } } 通过bootsound我们知道要将你的音频文件放在system/media/audio/ui/目录即可播放声音了,具体实现播放声音的操作看下文,比较简单, playSound类实现播放声音的。 void BootAnimationSound::playSound() { MediaPlayer* mp = new MediaPlayer(); if (mp->setDataSource(bootsound, NULL) == NO_ERROR) { /*系统启动时声音从扬声器出来,而关机时如果插耳机则会从耳机出来,所以在 * 这里强制设定。但是,这个API 涉及许可,许可服务 PermissionController * 在 ActivityManagerService 启动,而ActivityManagerService 启动时间比 * SurfaceFlinger 和 Audio 都晚,从而导致开机时动画播放一段时间才有声 * 音。所以加了此判定。 * */ if(mShutdownAnimation) { mp->setAudioStreamType(AudioSystem::ENFORCED_AUDIBLE); }else{ sleep(2); } mp->prepare(); mp->start(); /* start 之后,设置音量才有效果。 start 之前设音量没有效果的。*/ mp->setVolume(0.4, 0.4); } else { LOGE("Failed to load CameraService sounds: system/media/audio/ui/power_on_off.ogg"); } } 代码比较简单,但还是一点要特别强调在设置开关机音量的时候,执行过mp->start();以后再执行mp->setVolume(0.4, 0.4);才会有效果,这是一个很神奇的一个问题,我们徐申龙徐工通过调试很久才找到这个很操蛋的问题,注意这点会给你节省不少时间, 最后别忘了在Android.mk文件还需要引入播放声音库 LOCAL_SHARED_LIBRARIES := \ libcutils \ libutils \ libbinder \ libui \ libskia \ libEGL \ libGLESv1_CM \ libgui \ libmedia 请注意,libmedia是新添加的; bootanimation.zip包的制做 第一步,我们将png图片转换成colormap:8bit 以缩小文件占用磁盘空间 (以下是ubuntu命令,不用linux,可以用windows下的做图工具来转换图片格式): convert -type palette boot_003.jpg boot_003.convert.png 做好了图片,就需要把图片打成bootanimation.zip包了。 这个包,除了图片目录,还有一个desc.txt的文件,这个文本文件是用来告诉系统,如何使用图片目录来实现动画的。 所以有一定的语法,不过很简单: 目标屏幕宽度(480) 目标屏幕高度(800) 每次帧间隔 p 重复次数 播放完成后停顿 图片文件夹名1 p 重复次数 播放完成后停顿 图片文件夹名2 以一个desc.txt为例: 480 800 15 图片宽度480,高度800,这是我们I9000屏幕参数,最后15是播放动画的每秒帧率。就是一秒钟播放多少张图片,动画的最原始实现。小时候大家都玩过吧 p 1 0 foldername // p 是一个分隔符,1 表示播放一遍,0表示播放完后停顿 0 帧,最后是图片所在的zip包里的目录名。比如你的zip包里最后是这么个结构 // folder0(里面包含很多图片) + desc.txt, 那么你可以在这里把foldername 替换成folder0 根据这个语法,我们也可以自定义各种动画形式,例如下面所示: p 2 30 folder0 将folder0里的图片,播放2遍,播放完一遍后停顿30帧,因为我们之前设置了帧率是15帧每秒,那么这里就等于停顿2秒。 p 0 0 folder1 将folder1里的图片无限循环播放,每次播放不停顿。 如果你设置的宽度和高度不充满屏幕也没关系,剩余区域,系统会填充黑色。如果你设置的宽度和高度大过屏幕,系统会自动裁剪显示居中部分的图片区域。 4. 将转换好的图片集打包在不同的目录下, 然后把图片目录和一个描述动画的desc.txt 无压缩率格式打包成bootanimation.zip, 下面是ubuntu命令,你可以用winrar等工具,但是注意要选择无压缩率,无损压缩。另外保持压缩包后的目录结构。 zip -0 -r bootanimation.zip part0 part1 desc.txt 5. 最后将这个zip文件 拷贝到你的机器里 /data/local/bootanimation.zip 需要注意的是 如果你使用winrar进行压缩打包的话,需要设置参数如下: 压缩格式选zip 压缩方式选:存储(即不压缩)
- a.使用GIMP或者AdvancedBatchConverter软件,将图象转换为RAW格式;
- b.使用android自带的rgb2565工具,将RAW格式文件转换为RLE格式(如:rgb2565-rle<initlogo.raw>initlogo.rle)。
- 注:修改这几个地方的代码编译过后要重新烧写recovery,boot
更多相关文章
- 常用Android开发组件之图像类组件
- android ListView 中getview学习总结
- 写一个没有Activity的 HelloWorld for android
- android图片涂鸦,具有设置画笔,撤销,缩放移动等功能(一)
- ym—— Android(安卓)5.0学习之Activity过渡动画
- Android(安卓)NDK JNI 的环境搭建以及简单的代码
- Android(安卓)App组件之Fragment说明和示例
- freescale Android(安卓)Camera 调试总结
- Android(安卓)网络图片加载