.1 Android开机动画实现方式目前实现Android开机动画的方式主要是逐帧动画和OpenGL动画。

?逐帧动画

逐帧动画是一种常见的动画形式(Frame By Frame),其原理是在“连续的关键帧”中分解动画动作,也就是在时间轴的每帧上逐帧绘制不同的内容,使其连续播放而成动画。 因为逐帧动画的帧序列内容不一样,不但给制作增加了负担而且最终输出的文件量也很大,但它的优势也很明显:逐帧动画具有非常大的灵活性,几乎可以表现任何想表现的内容,而它类似与电影的播放模式,很适合于表演细腻的动画。
逐帧动画是网上广泛流传的一种实现方法。实现原理是将一系列图片打包成bootanimation.zip放入/system/media/目录,系统将图片一帧一帧循环播放形成一个动画效果。理论上讲这种方法应该是可以实现一切动画需求的,但是实践后你会发现当bootanimation.zip大于5M的时候,动画将有明显卡顿,文件越大动画越不流畅。所以细心的同学会发现手机上的开机动画大多都是只有中间一小部分在变化,而四周全是黑色,这样做是为了使得可以采用100*50(甚至更小)分辨率的图片,这样100帧也才几M的大小。

?OpenGL动画

OpenGL(英语:Open Graphics Library)是个定义了一个跨编程语言、跨平台的应用程序接口(API)的规范,它用于生成二维、三维图像。这个接口由近三百五十个不同的函数调用组成,用来从简单的图形比特绘制复杂的三维景象。

比较两种方式我们不难发现,电视平台上和手机有所不同,特别是开机广告,1920*1080分辨率的图片一张就几百KB,由于大小的限制导致动画帧数很少,所以电视平台采用“逐帧动画”方法无法做出复杂而流畅的动画,本文将主要讨论OpenGL的实现方式。

1.2 原生开机动画的源码分析

在制作自己的开机动画之前,我们先分析一下Android原生的开机动画源码。Android系统的开机动画源码位于framework/base/cmds/bootanimation(表1)。

Bootanimation程序目录:android-x.x/framework/base/cmds/bootanimation/

Android.mk

Android编译定义

bootanimation_main.cpp

入口文件

BootAnimation.h

BootAnimation类的声明

BootAnimation.cpp

BootAnimation类的定义和实现

先来看一下bootanimation_main.cpp,这个文件定义了main函数,代码如下:

[bootanimation_main.cpp]

int main(int argc, char** argv)
{
……
sp proc(ProcessState::self());
ProcessState::self()->startThreadPool(); // create the boot animation object
sp boot = new BootAnimation(); IPCThreadState::self()->joinThreadPool();
……
}

Main函数的代码很简单,首先启动Process的线程池,然后创建一个BootAnimation对象,最后将BootAnimation对象加入到刚才的线程池中, startThreadPool()和joinThreadPool()的用法可以参考android的binder机制。

下面就一起来看一下BootAnimation类:

[BootAnimation.h]

class BootAnimation : public Thread, public IBinder::DeathRecipient
{
……
private:
virtual bool threadLoop();
virtual status_t readyToRun();
virtual void onFirstRef();
virtual void binderDied(const wp& who);
……
status_t initTexture(Texture* texture, AssetManager& asset, const char* name);
status_t initTexture(void* buffer, size_t len);
bool android();
bool movie(); void checkExit();
……
}

BootAnimation类继承了Thread类和IBinder::DeathRecipient类,几个override函数的作用如下:
?onFirstRef()属于其父类RefBase,该函数在强引用sp新增引用计数時调用,就是当 有sp包装的类初始化的时候调用。
?binderDied(),当对象死掉时或者其他情况导致该Binder发生结束了,就会回调binderDied()方法;
?readyToRun()定义Thread执行前的初始化工作;
?threadLoop()是每个线程类都要实现的,在这里定义thread的执行内容,这个函数如果返回true,则函数会不停地执行threadloop中的内容,如果这个函数返回false,则threadloop中的内容仅仅执行一次线程就会退出;

[BootAnimation::onFirstRef()]
onFirstRef函数中执行了run BootAnimation线程。

void BootAnimation::onFirstRef()
{
status_t err = mSession->linkToComposerDeath(this);
ALOGE_IF(err, "linkToComposerDeath failed (%s) ", strerror(-err));
if (err == NO_ERROR) {
run("BootAnimation", PRIORITY_DISPLAY);
}
} void BootAnimation::binderDied(const wp& who)
{
kill( getpid(), SIGKILL );
requestExit();
}

[BootAnimation::readyToRun()]

status_t BootAnimation::readyToRun() {
......
// create the native surface
......
// initialize opengl and egl
......
EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
......
surface = eglCreateWindowSurface(display, config, s.get(), NULL);
......
mDisplay = display;
......
mSurface = surface;
......
}

readyToRun函数主要是为了得到EGLDisplay mDisplay和EGLDisplay mSurface对象,这两个对象后面再介绍,最后函数还会查询是否存在bootanimation.zip并初始化mAndroidAnimation的值。

#define USER_BOOTANIMATION_FILE "/data/local/bootanimation.zip"
#define SYSTEM_BOOTANIMATION_FILE "/system/media/bootanimation.zip"
#define SYSTEM_ENCRYPTED_BOOTANIMATION_FILE "/system/media/bootanimation-encrypted.zip"
......
bool BootAnimation::threadLoop()
{
bool r;
if (mAndroidAnimation) {
r = android();
} else {
r = movie();
}
......
}

[BootAnimation::threadLoop()]
BootAnimation::readyToRun中会检查是否存在bootanimation.zip,如果存在bootanimation.zip这里就执行movie(),否则执行android()。movie()为逐帧动画的实现,android()为opengl动画的实现,本文只考虑无bootanimation.zip的情况。

[BootAnimation::android()]

bool BootAnimation::android()
{
initTexture(&mAndroid[], mAssets, "images/android-logo-mask.png");
initTexture(&mAndroid[], mAssets, "images/android-logo-shine.png");
......
do {
......
glBindTexture(GL_TEXTURE_2D, mAndroid[].name);
glDrawTexiOES(xc, yc, , mAndroid[].w, mAndroid[].h); EGLBoolean res = eglSwapBuffers(mDisplay, mSurface);
......
checkExit();
} while (!exitPending());
......
}

终于到了绘图的步骤了,BootAnimation::android函数包含了整个opengl绘图的过程,因为android使用的是标准opengl es api,所以opengl的初始化和绘图过程这里就不详细介绍了,

这里需要注意的是eglSwapBuffers(mDisplay, mSurface),这个方法将mSruface投递到屏幕,这里用到了两个EGLDisplay对象,是由于使用了双缓冲机制,配合sleep实现稳定的刷新率。

最后当检测到系统初始化完成时退出程序。

OpenGL—Android 开机动画源码分析一的更多相关文章

  1. OpenGL—Android 开机动画源码分析二

    引自http://blog.csdn.net/luoshengyang/article/details/7691321/ BootAnimation类的成员函数的实现比较长,我们分段来阅读: 第三个开 ...

  2. Android 开机动画源码分析

    Android系统在启动SystemServer进程时,通过两个阶段来启动系统所有服务,在第一阶段启动本地服务,如SurfaceFlinger,SensorService等,在第二阶段则启动一系列的J ...

  3. Android 属性动画 源码解析 深入了解其内部实现

    转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/42056859,本文出自:[张鸿洋的博客] 我参加了博客之星评选,如果你喜欢我的博 ...

  4. Android网络框架源码分析一---Volley

    转载自 http://www.jianshu.com/p/9e17727f31a1?utm_campaign=maleskine&utm_content=note&utm_medium ...

  5. Android分包MultiDex源码分析

    转载请标明出处:http://blog.csdn.net/shensky711/article/details/52845661 本文出自: [HansChen的博客] 概述 Android开发者应该 ...

  6. Android消息机制源码分析

    本篇主要介绍Android中的消息机制,即Looper.Handler是如何协同工作的: Looper:主要用来管理当前线程的消息队列,每个线程只能有一个Looper Handler:用来将消息(Me ...

  7. Android开源框架源码分析:Okhttp

    一 请求与响应流程 1.1 请求的封装 1.2 请求的发送 1.3 请求的调度 二 拦截器 2.1 RetryAndFollowUpInterceptor 2.2 BridgeInterceptor ...

  8. android hardware.c 源码分析

    android的jni通过ID来找hal模块,使用了hw_get_module()函数,本文就通过这个函数的来分析一下hal层的模块是如何匹配的. 首先要了解三个结构体hw_module_t,hw_m ...

  9. Android -- 消息处理机制源码分析(Looper,Handler,Message)

    android的消息处理有三个核心类:Looper,Handler和Message.其实还有一个Message Queue(消息队列),但是MQ被封装到Looper里面了,我们不会直接与MQ打交道,因 ...

随机推荐

  1. 数学#素数判定Miller_Rabin+大数因数分解Pollard_rho算法 POJ 1811&2429

    素数判定Miller_Rabin算法详解: http://blog.csdn.net/maxichu/article/details/45458569 大数因数分解Pollard_rho算法详解: h ...

  2. More on wrapper types

    原文地址:http://fsharpforfunandprofit.com/posts/computation-expressions-wrapper-types-part2/ 上一篇中,我们说明了包 ...

  3. 二、WCF应用的通信过程

    注:本文为学习摘抄,原文地址:http://www.cnblogs.com/iamlilinfeng/archive/2012/09/26/2703759.html 一.概述 WCF能够建立一个跨平台 ...

  4. opkg

    opkg是个安装器,小乔,功能全. root@hbg:/# opkg files opkgPackage opkg (9c97d5ecd795709c8584e972bfdf3aee3a5b846d- ...

  5. MVC3+EF4.1学习系列(六)-----导航属性数据更新的处理

    通过上一篇的学习 我们已经知道怎么查询关系 这篇就来说说怎么导航属性数据更新时的处理 以及EF又会为我们生成哪些SQL~ 老规矩 先看下今天的图 添加和修改页面基本就是这样 这节的内容相对简单~~ 主 ...

  6. Hihocoder 2月29日

      时间限制:2000ms 单点时限:1000ms 内存限制:256MB 描述 给定两个日期,计算这两个日期之间有多少个2月29日(包括起始日期). 只有闰年有2月29日,满足以下一个条件的年份为闰年 ...

  7. java邮件发送(以163邮箱为例)

    1.首先应该开通163邮箱的smtp和pop3,得到授权码 2.其次建立一个web项目,否则需要倒jar包mail.jar 3.创建一个类 4.注意:邮件内容必须为正式话语,否则系统会认为是垃圾邮件而 ...

  8. Sublime Text学习笔记

    1.快捷键(Key Bindings)   Preferences -> Key Bindings ->Default   会打开一个配置文件,里面全是配置信息 2.代码片段(Snippe ...

  9. vs中的各种快捷键

    1. VS注释与取消注释快捷键 CTRL + K , CTRL + C(注释) CTRL + K , CTRL + U(取消注释)

  10. 神经网络工具箱nntool的使用方法

    关于如何使用nntool神经网络工具箱进行“数据训练”的方法: 1. 在命令窗口键入nntool命令打开神经网络工具箱: 2. 点击Import按钮两次,分别把输入向量和目标输出加入到对应的窗口([I ...