1. 程式人生 > >[Android]新增自定義開機動畫(視訊)並去黑屏

[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 左右。