首页 > 代码库 > Android4.2.2启动动画前播放视频

Android4.2.2启动动画前播放视频

首先声明測试平台为瑞芯微的rk3168,Android4.2.2,Android版本号非常重要,由于Android4.0和Android4.2.2的代码有些地方就有差别,并不通用!


首先接到任务不知怎样下手,由于我了解中Android启动时没有出现过播放视频的,特别是在启动动画之前,Linux企鹅之后,而动画也是一幅幅的图片,根本不是啥视频如mp4,3gp等!

由于启动动画时能够播放声音,并且上层应用的mediaplayer也能够播放声音,结合surface能够播放视频!这就是入口点~

动画播放的关键文件在:Z:\Backup\rk3168_v4.2\frameworks\base\cmds\bootanimation下!

1、了解Android显示开机画面的原理!

1. Linux 系统启动,出现Linux小企鹅画面(reboot)(Android 1.5及以上版本号已经取消载入图片);
2. Android平台启动初始化,出现"A N D R I O D"文字字样画面;
3. Android平台图形系统启动,出现含闪动的ANDROID字样的动绘图片(start)。

4、原理參考资料:

http://blog.csdn.net/luoshengyang/article/details/7691321

http://blog.csdn.net/conowen/article/details/7884009

http://www.cnblogs.com/jqyp/archive/2012/03/07/2383973.html

http://blog.csdn.net/backgarden_straw/article/details/8571992

http://www.eoeandroid.com/thread-114742-1-1.html


1、播放音乐:

在瑞芯微提供的源代码中事实上能够支持播放音乐了,仅仅是没有提供音乐文件!声音移植

a、首先在BootAnimation.h加入方法的声明和头文件的引用

1
2
#include <media/AudioSystem.h>
#include <media/mediaplayer.h>

b、在 class BootAnimation : public Thread, public IBinder::DeathRecipient中

加入方法 voidplayMusic();

c、然后在BootAnimation.cpp中实现这种方法:

#define BOOTMUSIC_FILE "/system/media/audio/alarms/gx.mp4"

void BootAnimation::playMusic()
{
    sp<MediaPlayer> mp = new MediaPlayer();
    if ((0 == access(BOOTMUSIC_FILE, F_OK)) && mp != NULL) {
        mp->setDataSource(BOOTMUSIC_FILE, NULL) //设置资源
        mp->prepare();                                                                 //准备,同步
        mp->start();                                                                      //播放
    }                                                                                           //事实上mediaplayer还有

非常多方法,能够查看mediaplayer类
}

d、调用并启动声音

bool BootAnimation::threadLoop()

{
    bool r;

playMusic()
    if (mAndroidAnimation) {
        r = android();
    } else {
        r = movie();
    }

.......

}

e、Android.mk的改动

由于播放声音还须要引入库

LOCAL_SHARED_LIBRARIES := \
libcutils \
libandroidfw \
libutils \
libbinder \
    libui \
libskia \
    libEGL \
    libGLESv1_CM \
    libmedia \
    libgui

请注意,libmedia是新加入的;

f、声音文件的加入

源代码文件夹在声音在:

Z:\source\rk3168_v4.2\frameworks\base\data\sounds

视频在:

Z:\source\rk3168_v4.2\frameworks\base\data\videos

至于编译完毕后放到什么地方了那是AllAudio.mk文件上配置的

$(LOCAL_PATH)/XXXX.mp3:system/etc/xxxx.mp3 \

g、将音频放到此文件夹编译,就有开机声音了!


2、视频移植

a、事实上看了前面的资料了解动画的启动过程和对上层应用播放视频的方法事实上非常easy了!

事实上动画的播放也是用surface来展示的,然后用OpenGL将图片绘制上去的!

联系上层应用播放视频的步骤(mediaplayer+surfaceview):

player=new MediaPlayer();
player.setAudioStreamType(AudioManager.STREAM_MUSIC);
player.setDisplay(surfaceHolder);
player.setDataSource("/sdcard/gx.mp4");
player.prepare();
player.start();
。。。。。。。
所以假设你做了声音播放后是不是非常自然想到,就差player.setDisplay(surfaceHolder);

既然如此就倒推这方法做了什么:

由于setdisplay是mediaplayer的方法

base\media\java\android\media\mediaplayer.Java--->

 public void setDisplay(SurfaceHolder sh) {
        mSurfaceHolder = sh;
        Surface surface;
        if (sh != null) {
            surface = sh.getSurface();
        } else {
            surface = null;
        }
        _setVideoSurface(surface);//重点设置一个surface
        updateSurfaceScreenOn();
    }

private native void _setVideoSurface(Surface surface); //本地方法


base\media\jni\android_media_MediaPlayer.cpp ----->
{"_setVideoSurface",    "(Landroid/view/Surface;)V",        (void *)android_media_MediaPlayer_setVideoSurface},
---->android_media_MediaPlayer_setVideoSurface(JNIEnv *env, jobject thiz, jobject jsurface){    setVideoSurface(env, thiz, jsurface, true /* mediaPlayerMustBeAlive */);}
------------>
static voidsetVideoSurface(JNIEnv *env, jobject thiz, jobject jsurface, jboolean mediaPlayerMustBeAlive){    sp<MediaPlayer> mp = getMediaPlayer(env, thiz);    if (mp == NULL) {        if (mediaPlayerMustBeAlive) {            jniThrowException(env, "java/lang/IllegalStateException", NULL);        }        return;    }    decVideoSurfaceRef(env, thiz);    sp<ISurfaceTexture> new_st;    if (jsurface) {        sp<Surface> surface(android_view_Surface_getSurface(env, jsurface));        if (surface != NULL) {            new_st = surface->getSurfaceTexture();            if (new_st == NULL) {                jniThrowException(env, "java/lang/IllegalArgumentException",                    "The surface does not have a binding SurfaceTexture!");                return;            }            new_st->incStrong(thiz);        } else {            jniThrowException(env, "java/lang/IllegalArgumentException",                    "The surface has been released");            return;        }    }    env->SetIntField(thiz, fields.surface_texture, (int)new_st.get());    // This will fail if the media player has not been initialized yet. This    // can be the case if setDisplay() on MediaPlayer.java has been called    // before setDataSource(). The redundant call to setVideoSurfaceTexture()    // in prepare/prepareAsync covers for this case.    mp->setVideoSurfaceTexture(new_st);                //重点}
分析到这里我们心里基本有数了,就是要活的一个surface就可以!
b、分析动画中surface 的构建过程:
在base\cmds\bootanimation\BootAnimation.cpp的status_t BootAnimation::readyToRun()中有对surface的初始化,到了就完毕了大半获取这个surface在调用上面的方法就大功告成!