[Android]新增自定義開機動畫(視訊)並去黑屏
補丁如下
原始碼分析及修改方式
關於開機動畫的流程主要程式碼在
framebuffer/base/cmds/bootanimation/bootAnimation.cpp
從 BootAnimation::threadLoop() 中的我們可以看到
if(mZip == NULL) {
r = android();
} else {
r = movie();
}
根據 mZip(這是一個叫做 bootanimation.zip 的檔案)是否存在,決定呼叫 android() 介面還是 movie() 介面。
android()
如果沒有 zip 檔案進入的就是這種方式。
會載入”images/android-logo-mask.png”和”images/android-logo-shine.png” 這兩張圖片,前者是鏤空的 ANDROID 字樣,後者是一副很長的銀白黑漸進的背景圖,通過固定前者,移動後者,實現 ANDROID 字樣的反光效果。
想修改android閃動的那兩張圖片的話,最簡單的方法是直接替換圖片(圖片在 /frameworks/base/core/res/assets/images),如果懂 openGL 的話也可以自己做酷炫的動畫。
movie()
如果有 bootanimation.zip 檔案進入的就是這種方式。
#define SYSTEM_BOOTANIMATION_FILE "/system/media/bootanimation.zip"
會載入 bootanimation.zip 中的內容。zip 檔案中實際是很多幀圖片的組合,通過多幀圖片的逐步播放實現動畫的效果。
所以把做好的動畫拷貝到編譯好對應的目錄下即可,然後執行make snod整合進 img 包就可以看到效果了。
具體制作 bootanimation.zip 的文章參考這兩篇:
http://blog.csdn.net/mlbcday/article/details/7410509
http://luq1985428.blog.163.com/blog/static/12243116220131198011812/
但這樣預設是沒有音樂的,還需要實現一個 playMusic() 的介面,來同步的播放音樂。
具體實現 playMusic() 介面的方式參考這一篇的 “1.播放音樂”:
http://www.voidcn.com/blog/longtian635241/article/p-2095371.html
從 mp4 中提取音訊為 ogg 或者 wav 格式的網站有
http://media.io/
缺點是
1. 多幀圖片由於畫面色彩豐富、動畫較長,這樣做出來的 zip 會比較大,播放效果會出現明顯、嚴重卡頓
2. 播放時music時可能出現動畫和聲音不同步
所以我們可以呼叫 mediaPlayer 的介面來實現播放視訊(mp4)
自行新增 video 介面
修改 ThreadLoop 中的判斷
// We have no bootanimation file, so we use the stock android logo
// animation.
- if (mZip == NULL) {
+ if (mVideo) {//這裡的 mVideo 是一個標誌位,表示是否有開機視訊
+ r = video();
+ }else if (mZip == NULL) {
r = android();
} else {
r = movie();
我們在 ReadyToRun 中實現 mVideo 的判斷。
@@ -359,6 +362,7 @@ status_t BootAnimation::readyToRun() {
mFlingerSurfaceControl = control;
mFlingerSurface = s;
+ mVideo = false;
// If the device has encryption turned on or is in process
// of being encrypted we show the encrypted boot animation.
char decrypt[PROPERTY_VALUE_MAX];
@@ -366,6 +370,9 @@ status_t BootAnimation::readyToRun() {
bool encryptedAnimation = atoi(decrypt) != 0 || !strcmp("trigger_restart_min_framework", decrypt);
+ if (access(BOOTANIMATION_VIDEO, R_OK) == 0)
+ mVideo = true;
+
ZipFileRO* zipFile = NULL;
if ((encryptedAnimation
&& (access(SYSTEM_ENCRYPTED_BOOTANIMATION_FILE, R_OK) == 0)
下面可以開始新增 video 介面了
+bool BootAnimation::video()
+{
+ const float MAX_FPS = 60.0f;
+ const bool LOOP = true;
+ const float CHECK_DELAY = ns2us(s2ns(1) / MAX_FPS);
+ sp<IMediaHTTPService> httpService;
+ eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+ eglDestroySurface(mDisplay, mSurface);
+ /*
+ float asp = 1.0f * mWidth / mHeight;
+ SurfaceComposerClient::openGlobalTransaction();
+ mFlingerSurfaceControl->setPosition(mWidth, 0);
+ mFlingerSurfaceControl->setMatrix(0, 1 / asp, -asp, 0);
+ SurfaceComposerClient::closeGlobalTransaction();
+ */
+
+ sp<MediaPlayer> mp = new MediaPlayer();
+ mp->setDataSource(httpService, BOOTANIMATION_VIDEO, NULL);//設定播放資源
+ mp->setLooping(true);//確定是否播放迴圈
+ mp->setVideoSurfaceTexture(mFlingerSurface->getIGraphicBufferProducer());
+ mp->prepare();
+ mp->start();
+ while(true) {
+ if(exitPending())
+ break;
+ usleep(CHECK_DELAY);
+ checkExit();
+ }
+ mp->stop();
+ return false;
+}
如果要實現開關機動畫不同也可以增加一個判斷。
這裡的 BOOTANIMATION_VIDEO 為 mp4 的路徑,setDataSource 介面有多種過載方式,這裡採用 url 的方式。
+#define BOOTANIMATION_VIDEO "/system/media/bootanimation.mp4"
+#include <media/IMediaHTTPService.h>
最後修改標頭檔案,新增增加的兩個成員變數
/cmds/bootanimation/BootAnimation.h
@@ -106,6 +106,8 @@ private:
EGLDisplay mSurface;
sp<SurfaceControl> mFlingerSurfaceControl;
sp<Surface> mFlingerSurface;
+ bool mVideo;
+ bool video();
ZipFileRO *mZip;
int mHardwareRotation;
GLfloat mTexCoords[8];
至此已經完成 video() 介面的編寫了。
(具體 MediaPlayer 的用法參考的 http://blog.csdn.net/ddna/article/details/5176233 )
後面可以在 /system/media/ 中新增 bootanimation.mp4 嘗試能否播放 mp4。
開機視訊前黑屏 5s
是由於等待電池的後臺服務啟動導致的,遮蔽如下程式碼。
frameworks/av/media/libmediaplayerservice/MediaPlayerService.cpp
遮蔽後黑屏時間減為 1s 左右。