Android 开机动画分析
本篇文档分为以下三个部分:一、基础知识二、bootanimation.zip
三、开机动画流程源码分析
注:Android 开机画面由三部分组成,第一部分在bootloader 启动时显
示, 第二部分在启动kernel 时显示, 第三部分在系统启动时
(bootanimation)显示(动画)。此篇文档主要分析第三部分。
一、基础知识
 何时启动Android 开机动画?
SystemServers 进程通过两个阶段来启动系统所有服务。一、本地服务,如
SurfaceFlinger,SensorService 等,二、启动一系列的Java 服务。
android 开机动画是在启动SurfaceFlinger 服务时启动的。
 开机动画资源的来源?(这也是修改开机动画两种方式的依据)
1、path1: /frameworks/base/core/res/assets/images
一张镂空的android 图android-logo-mask.png , 一张发光效果
android-logo-shine.png.
2、Path2: system/media/bootanimation.zip
如果不存在该压缩包,则默认使用原生自带的资源(即path1 下)。所以要
定制自己的开机动画一般都是在system/media/目录下放置bootanimation.zip。
( 注: 为了使开机动画生效, 最终bootanimation.zip 一般要拷贝到
out/target/product/.../system/media 目录下。这个拷贝的过程假设由Android.mk
文件进行处理,如需改动bootanimation.zip,需要找到拷贝前的目录下改动压缩
包才会生效。)
 常见的开机动画形式?
开机动画大多都是只有中间一小部分在变化,而四周全是黑色,这样做是为
了使得可以采用100*50(甚至更小)分辨率的图片,这样100 帧也才几M 的大
小。(因此当bootanimation.zip 大于5M 的时候,动画将有明显卡顿,文件越大
动画越不流畅。)
 开机动画原理?
图片android-logo-mask.png 用作动画前景,它是一个镂空的“ANDROID”图
像。图片android-logo-shine.png 用作动画背景,它的中间包含有一个高亮的呈
45 度角的条纹。在每一次循环中,图片android-logo-shine.png 被划分成左右两
部分内容来显示。左右两个部分的图像宽度随着时间的推移而此消彼长,这样就
可以使得图片android-logo-shine.png 中间高亮的条纹好像在移动一样。另一方
面,在每一次循环中,图片android-logo-shine.png 都作为一个整体来渲染,而且
它的位置是恒定不变的。由于它是一个镂空的“ANDROID”图像,因此,可以通
过它的镂空来看到它背后的图片android-logo-shine.png 的条纹一闪一闪地划过。
 如何修改开机动画?
#源码分析#
在BootAnimation::threadLoop()中:
bool BootAnimation::threadLoop()
{
bool r;
// We have no bootanimation file, so we use the stock android logo
// animation.
if (mZipFileName.isEmpty()) {
r = android();//执行Android 字体闪动的图片
} else {
r = movie();//执行bootanimation.zip 中的动画图片
}
......
return r;
}
因此,BootAnimation::Android()会加载"images/android-logo-mask.png"
和"images/android-logo-shine.png";
BootAnimation::movie()会加载bootanimation.zip 中的内容
1、方式一:直接修改/frameworks/base/core/res/assets/images 目录下
的图片即可(android-logo-mask.png 和android-logo-shine.png)
2、方式二:android 2.0 及之后,使用bootanimation 程序显示开机画
面, 如需修改开机画面, 不用修改代码, 只需按格式要求做
bootanimation.zip 包,放在系统的/system/media 目录中,或/data/local
目录中即可,两个目录下都存在时,优先使用/data/local 下的。android
2.0 之前,则需要修改源码。(例如在8916 项目中:out 目录是编译
之后生成的,改动开机动画需要找到压缩包拷贝前的目录,需要在拷
贝前的目录下进行改动bootanimation.zip 压缩包才会生效)
二、bootanimation.zip
1、bootanimation.zip 压缩包里面包含数张png 格式的图片,还有
一个desc.txt 的文本文档,开机时按desc.txt 里面的指令,屏幕上会
按文件名称顺序连续的播放一张张的图片,就像播放原始的胶带影片
一样,形成动画。desc.txt 是一个保存形式为ANSI 格式的文件,用于
设置这个动画像素(大小),帧数,闪烁次数,文件夹名称等。
2、说明文件desc.txt
480 427 30
p 1 0 part0
p 0 10 part1
480 为宽度,427 为高度,30 为帧数,即每秒播放动画30 帧;
第一项p 为标志符,第二项为循环次数1 为只播放1 次,0为无限循
环,第三项为两次循环之间间隔的帧数,第四项为对应的目录名。
#小技巧#
在终端中输入命令:
adb shell---> cd /system/bin--->bootanimation 或者bootanimation shut
这样不用重启即可查看定制的动画。
三、开机动画流程源码分析
当开机启动时,系统内核起来后,启动android,这时就会启动开机动画。
具体是在SurfaceFlinger.cpp 的readyToRun 方法中调用,当android 启动完成后,
关闭掉开机动画。代码所在位置:/frameworks/base/cmds/bootanimation,其主
要包含以下三个文件
BootAnimation_main.cpp
BootAnimation.h
bootAnimation.cpp
BootAnimation.cpp 继承自Thread, 在创建的时候会调用
readyToRun()->threadLoop() 。readyToRun() 方法判断
/system/media/bootanimation.zip(shutanimaion.zip)是否存在,如果存在,
则将mAndroidAnimation 设置false,这个变量决定threadLoop 中调用android
( ) 还是movie ( ) 来具体实现动画的播放。threadLoop() 方法根据
mAndroidAnimation 变量调用android()/movie ( ) 。如果
system/media/shutanimation.zip/bootanimation.zip 存在的话,调用movie
(),该接口会解析zip 文件中的desc.txt 文件,根据txt 文件中的配置来播放
动画。否则就调用android 来播放原生自带的资源。
#源码片段#
if (mZipFileName.isEmpty()) {
r = android();//执行Android 字体闪动的图片
} else {
r = movie();//执行bootanimation.zip 中的动画图片
}
......
***流程大致如下五点阐述***
1、Android 系统在启动SystemServer 进程时,通过两个阶段来启动系统所有
服务,在第一阶段启动本地服务,SurfaceFlinger,SensorService 等,在第二
阶段则启动一系列的Java 服务。
android 开机动画是在启动SurfaceFlinger 服务时启动的。
SystemServer 的main 函数首先调用**init1**来启动本地服务,init1 函数
通过JNI 调用C 语言中的system_init()函数来实现服务启动。viceManager 进
程。
2、通过调用SurfaceFlinger::instantiate()函数来启动SurfaceFlinger 服
务,SurfaceFlinger 类继承于BinderService 模板类,BinderService 类的
instantiate()函数就是构造对应类型的服务对象,并注册到ServiceManager。
3、SurfaceFlinger 对象实例的构造过程很简单,就是初始化一些成员变量值,
然后调用init()函数来完成初始化工作。init 函数中,也并没有做任何复杂工
作,只是简单读取系统属性得到开机模式,来相应设置一些变量而已,比如是否
显示开机动画变量sBootanimEnable。
4、创建的SurfaceFlinger 线程在执行前会调用SurfaceFlinger 的
readyToRun() 函数完成初始化任务, 然后反复执行SurfaceFlinger 的
threadLoop()函数。readyToRun 该函数首先是初始化Android 的图形显示系统,
启动SurfaceFlinger 事件线程。当显示系统初始化完毕后,调用startBootAnim()
函数来显示开机动画。
源码如下所示:
void SurfaceFlinger::startBootAnim() {
// start boot animation
if(SurfaceFlinger::sBootanimEnable){
property_set("service.bootanim.exit", "0");
property_set("ctl.start", "bootanim");
}
}
注:判断开机动画的变量值决定是否显示开机动画。启动开机动画进程也是通
过Android 属性系统来实现的。在Android 系统启动脚本init.rc 中配置了开
机动画服务进程。
5、property_set("ctl.start","bootanim")就是启动bootanim 进程来显示
开机动画, 该进程对应的源码位于
frameworks\base\cmds\bootanimation\bootanimation_main.cpp
int main()
{
setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_DISPLAY);
char value[PROPERTY_VALUE_MAX];
property_get("debug.sf.nobootanimation", value, "0");
int noBootAnimation = atoi(value);
ALOGI_IF(noBootAnimation, "boot animation disabled");
if (!noBootAnimation) {
sp proc(ProcessState::self());
ProcessState::self()->startThreadPool();
// create the boot animation object
sp boot = new BootAnimation();
//将当前线程注册到Binder 线程池中
IPCThreadState::self()->joinThreadPool();
}
return 0;
}
该函数构造了一个BootAnimation 对象,并且为该对象设置了开关机动画及
声音文件路径,同时创建了Binder 线程池,并将bootanim 进程的主线程注册到
Binder 线程池中,Binder 通信用于接收客户进程的请求。
在构造BootAnimation 对象时,实例化SurfaceComposerClient 对象,用于
请求SurfaceFlinger 显示开关机动画
在readyToRun 函数中创建SurfaceControl 对象,通过SurfaceControl 对象
得到Surface 对象,并初始化好OpenGL,同时判断动画文件是否存在,如果不存
在,则设置标志位mAndroidAnimation 为true,表示显示Android 滚动字样。
当初始化完这些必需资源后,线程进入循环执行体threadLoop()。
#总结#
开机动画的启动流程大致如下:

更多相关文章

  1. Android 开源动画框架:NineOldAndroids
  2. Android动画TimeInterpolator(插值器)和TypeEvaluator(估值器)分析
  3. android直接用v4l2采集图片数据
  4. android 定时器,每秒变换一次图片!
  5. Android : RadioBotton—— 图片浏览器
  6. Android静态图片人脸识别的完整demo(附完整源码)
  7. android 获取http网络图片保存png
  8. Android中调用C++函数的一个简单Demo
  9. Android――动画专题研究

随机推荐

  1. android studio混淆打包
  2. 技术|Android安装包优化
  3. android字符串处理(Mms模块短信内容解析)
  4. Android开发实践 带你理解使用WebView
  5. Android——继承SimpleAdapter重写自己的
  6. android -> 修改自动转为大写 的textAllC
  7. android XML文件序列化
  8. android 中RecyclerView 嵌套了 GridView
  9. Android jni调用,实现自己的JNI_OnLoad函
  10. adnroid(10)(android下的单元测试)