Android 原生开机动画是以.zip图片格式,保存在system/media目录下,开关机分别对应bootanimation.zip和shutdownanimation.zip。压缩包中包含,part0、part1两个图片文件夹和一个描述文件desc.txt。txt格式如下:
1080 2280 6 (表示分辨率、帧率)
p 1 0 part0 (1表示播放1次,0表示到下一部分间隔)
p 0 0 part1 (0表示播放次数,0表示不循环)
正常的我们替换掉这个资源包就可以达到替换动画的目的。如果需要播放视频的话(视频不能太长,优点是保证音画严格同步效果),那需要一点小改动。
开机动画相关代码路径:frameworks\base\cmds\bootanimation
主要的处理逻辑都在bootanimation.cpp中,代码片段如下:·
#include
#include
#include
//视频文件名
static const char SYSTEM_BOOT_VIDEO_FILE[] = "/system/media/boot.ts";
static const char SYSTEM_SHUTDOWN_VIDEO_FILE[] = "/system/media/shutdown.ts";
//播放状态
static bool playComplete;
......
bool BootAnimation::threadLoop()
{
bool r;
// We have no bootanimation file, so we use the stock android logo
// If the device is in ffbm mode, then start fastmmi service
char odm_fastmmi[PROPERTY_VALUE_MAX];
property_get("ro.bootmode", odm_fastmmi, "");
if(!strncmp("ffbm-01", odm_fastmmi,7))
{
property_set("ctl.start", "fastmmi");
}
//这里开始判断是否播放视频文件,条件随便加了,其实应该两个路径都判断下
if (access(SYSTEM_BOOT_VIDEO_FILE, R_OK) == 0) {
mVideo = true;
} else {
mVideo = false;
}
__android_log_print(ANDROID_LOG_INFO , "BootAnimation", "mVideo = %d", mVideo);
// animation.
if (mVideo) {
r = video(); //这个使我们加的播放视频的
} else if (!mZipFileName.isEmpty()) {
r = movie(); //这个是播放zip图片的
} else {
r = android(); //这个是android默认的
}
//END
......
}
//添加MediaPlayerListener子类,监听播放状态
class MPListener: public MediaPlayerListener
{
public:
void notify(int msg, int ext1, int ext2, const Parcel *obj){
__android_log_print(ANDROID_LOG_INFO , "BootAnimation", "MediaPlayer::notify :%d, %d, %d, %p", msg, ext1, ext2, obj);
if (msg == MEDIA_PLAYBACK_COMPLETE) {
playComplete = true;
} else {
playComplete = false;
}
}
};
//获取属性值
int getProperty(const char *str) {
char buf[PROP_VALUE_MAX];
property_get(str, buf, "0");
return atoi(buf);
}
// 添加video函数
bool BootAnimation::video()
{
int duration = getProperty("ro.shutdown_animation.duration") / 1000; //这个是为了关机动画效果,避免出现播放完了release资源后显示桌面,加一个延迟
const float MAX_FPS = 60.0f;
const float CHECK_DELAY = ns2us(s2ns(1) / MAX_FPS);
sp httpService;
eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
eglDestroySurface(mDisplay, mSurface);
playComplete = false;
sp mp = new MediaPlayer();
sp mpl = new MPListener();
mp->reset();
__android_log_print(ANDROID_LOG_INFO , "BootAnimation", "mp->start() : %s", android::base::GetProperty("sys.powerctl", "").c_str());
//判断是播放开机动画还是关机动画
bool shutting = !android::base::GetProperty("sys.powerctl", "").empty();
if (shutting) {
mp->setDataSource(httpService, SYSTEM_SHUTDOWN_VIDEO_FILE, NULL);
} else {
mp->setDataSource(httpService, SYSTEM_BOOT_VIDEO_FILE, NULL);
}
mp->setLooping(false);
mp->setListener(mpl);
mp->setVideoSurfaceTexture(mFlingerSurface->getIGraphicBufferProducer());
mp->prepare();
mp->start();
__android_log_print(ANDROID_LOG_INFO , "BootAnimation", "mp->start() : %d", shutting);
bool stop = false;
while(true) {
if(exitPending()) //checkExit()确定可以结束,我们可以跳出循环
break;
if (stop) {
checkExit(); //这个是check是否可以退出boot动画,当系统已经完成开机了
continue;
}
if (playComplete) { //保证视频播放完毕
mp->pause();
stop = true;
}
}
if (shutting) sleep(duration);
__android_log_print(ANDROID_LOG_INFO , "BootAnimation", "mp->stop() : %f", CHECK_DELAY);
mp->stop();
mp->disconnect();
mp.clear();
return false;
}
在frameworks/base/cmds/bootanimation/BootAnimation.h头文件中加下
bool android();
bool movie();
//新加两个声明
bool video();
bool mVideo;
frameworks/base/cmds/bootanimation/Android.mk中需要加libmedia
LOCAL_SHARED_LIBRARIES := \
...
libmedia
frameworks/base/cmds/bootanimation/bootanim.rc这里修改很重要
service bootanim /system/bin/bootanimation
class core animation
(user graphics改成下面,使用media服务播放才能保证音画同步)
user media
group graphics audio
disabled
oneshot
writepid /dev/stune/top-app/tasks
(添加关机启动动画)
on property:persist.sys.boot_start=1
start bootanim
可能关机是默认的进度条样式,没有动画,那还需要修改frameworks/base/services/core/java/com/android/server/power/ShutdownThread.java文件,去掉进度条dialog,添加关机动画时长之类的,修改比较简单,不多赘述