.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. ESFramework 通信框架安全机制的设计与实现

    在分布式通信系统中,安全无疑是非常重要的.ESFramework通信框架提供了哪些安全保障了?由于ESFramework通信框架是应用层的开发框架,那么本文我们只讨论ESFramework通信框架在应 ...

  2. 新浪 股票 API

    新浪期货数据接口 [例子]http://hq.sinajs.cn/list=M0豆粕连续 M0 返回值如下:var hq_str_M0="豆粕连续,145958,3170,3190,3145 ...

  3. Chapter 16_4 私密性

    在Lua面向对象编程的基础设计当中,没有提供私密性机制.但是可以用其他方法实现,从而获得对象的访问控制. 这种实现不常用,作为兴趣爱好,只做基本了解. 基本做法是:通过两个table来表示一个对象.一 ...

  4. freemarker之list和map

    第一次使用freemarker很不习惯,之前都是用velocity的. @RequestMapping("/free.htm") public ModelAndView hello ...

  5. window.showModalDialog()的简单用法

    //创建一个显示html内容的模态对话框: vReturnValue = window.showModalDialog(sURL [, vArguments] [,sFeatures]) //创建一个 ...

  6. 转载-ACPI的知识

    ACPI – the Advanced Configuration & Power Interface. ACPI是OS,BIOS和硬件之间的抽象层.它允许OS和平台独立的发展,比如新的OS可 ...

  7. Student s = new Student();在内存中做了哪些事情?

    [Student s = new Student();在内存中做了哪些事情?] 1加载Student.class文件进内存 2在栈内存为s开辟空间 3在堆内存为学生对象开辟空间 4对学生对象的成员变量 ...

  8. IOS 导出ipa文件方法

    1.首先打开项目,Device选项栏选择“Generic iOS Device”.如下图所示: 2.选择屏幕上方的“product”并点击打开,选择“Archive”并点击打开,程序就会自动运行,运行 ...

  9. HOSTS文件修改后不起作用的原因

    如果是通过记事本修改,其实是没有问题的,如果有问题,网上搜到的是ipconfig /flushdns之类的 如果是批量程序写的,那就要小心了, 一定要ANSI(美标格式的,忘了英文是什么来着) 保存后 ...

  10. javascript 如何正确使用getElementById,getElementsByName(), and getElementsByTagName()

    WEB标准下可以通过getElementById(), getElementsByName(), and getElementsByTagName()访问DOCUMENT中的任一个标签. (1)get ...