Android 7 修改啟動動畫和開機聲音


背景

在修改開機音量的時候,發現找不到對應的聲音功能調用。

因此了解了一下安卓的開機聲音是如何實現的。

安卓4~安卓7 都可以這么做。

參考:

前言

關於安卓的開機效果(動畫、logo、聲音),有下面幾個階段:

  • 老的方案1:Linux 系統啟動,出現Linux小企鵝畫面(reboot)(Android 1.5及以上版本已經取消加載圖片);
  • 沿用至今的方案2:Lndroid平台圖形系統啟動,出現含閃動的ANDROID字樣的動畫圖片(start)並加載Android系統。

我們這里說的是沿用至今的方案2。

源碼分析

android開機動畫叫源碼位於frameworks/base/cmds/bootanimation/BootAnimation.cpp中,會將/data/local/bootanimation.zip/system/media/bootanimation.zip里面的圖片(支持png、jpeg、bmp)以動畫的形式播放出來:

在源碼樹中搜索bootanimation.zip即可找到可供修改的開機動畫。

static const char OEM_BOOTANIMATION_FILE[] = "/oem/media/bootanimation.zip";
static const char SYSTEM_BOOTANIMATION_FILE[] = "/system/media/bootanimation.zip";
static const char SYSTEM_ENCRYPTED_BOOTANIMATION_FILE[] = "/system/media/bootanimation-encrypted.zip";

status_t BootAnimation::readyToRun() {
    mAssets.addDefaultAssets();

    sp<IBinder> dtoken(SurfaceComposerClient::getBuiltInDisplay(
            ISurfaceComposer::eDisplayIdMain));
    DisplayInfo dinfo;
    status_t status = SurfaceComposerClient::getDisplayInfo(dtoken, &dinfo);
    if (status)
        return -1;

    // create the native surface andrew.hu modify
    sp<SurfaceControl> control = session()->createSurface(String8("BootAnimation"),
            dinfo.orientation == 1 ? dinfo.h : dinfo.w,
            dinfo.orientation == 1 ? dinfo.w : dinfo.h, PIXEL_FORMAT_RGB_565);

    SurfaceComposerClient::openGlobalTransaction();
    control->setLayer(0x40000000);
    SurfaceComposerClient::closeGlobalTransaction();

    sp<Surface> s = control->getSurface();

    // initialize opengl and egl
    const EGLint attribs[] = {
            EGL_RED_SIZE,   8,
            EGL_GREEN_SIZE, 8,
            EGL_BLUE_SIZE,  8,
            EGL_DEPTH_SIZE, 0,
            EGL_NONE
    };
    EGLint w, h;
    EGLint numConfigs;
    EGLConfig config;
    EGLSurface surface;
    EGLContext context;

    EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);

    eglInitialize(display, 0, 0);
    eglChooseConfig(display, attribs, &config, 1, &numConfigs);
    surface = eglCreateWindowSurface(display, config, s.get(), NULL);
    context = eglCreateContext(display, config, NULL, NULL);
    eglQuerySurface(display, surface, EGL_WIDTH, &w);
    eglQuerySurface(display, surface, EGL_HEIGHT, &h);

    if (eglMakeCurrent(display, surface, surface, context) == EGL_FALSE)
        return NO_INIT;

    mDisplay = display;
    mContext = context;
    mSurface = surface;
    mWidth = w;
    mHeight = h;
    mFlingerSurfaceControl = control;
    mFlingerSurface = s;

    // 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];
    property_get("vold.decrypt", decrypt, "");

    bool encryptedAnimation = atoi(decrypt) != 0 || !strcmp("trigger_restart_min_framework", decrypt);
	// 讀取 對應 儲存了開機動畫的包
    if (encryptedAnimation && (access(getAnimationFileName(IMG_ENC), R_OK) == 0)) {
        mZipFileName = getAnimationFileName(IMG_ENC);
    }
    else if (access(getAnimationFileName(IMG_OEM), R_OK) == 0) {
        mZipFileName = getAnimationFileName(IMG_OEM);
    }
    else if (access(getAnimationFileName(IMG_SYS), R_OK) == 0) {
        mZipFileName = getAnimationFileName(IMG_SYS);
    }
    return NO_ERROR;
}

循環:

bool BootAnimation::threadLoop()
{
    bool r;
    // We have no bootanimation file, so we use the stock android logo
    // animation.
    if (mZipFileName.isEmpty()) {
        r = android(); //   執行android字體閃動的圖片 會加載"images/android-logo-mask.png"和"images/android-logo-shine.png"
    } else {
        r = movie();   //   執行bootanimation.zip中提供的動畫圖片 
    }

    eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
    eglDestroyContext(mDisplay, mContext);
    eglDestroySurface(mDisplay, mSurface);
    mFlingerSurface.clear();
    mFlingerSurfaceControl.clear();
    eglTerminate(mDisplay);
    IPCThreadState::self()->stopProcess();
    return r;
}

所以如果你想修改動畫,那么把你做好的動畫拷貝到編譯好對應的目錄下即可,然后編譯刷入整合進system鏡像包就可以看到效果了

如果你想修改android閃動的那兩張圖片的話,最簡單的方法是直接替換圖片,如果你懂openGL的話也可以自己做酷炫的動畫

另外如果需要修改開機logo動畫,可以這么做(參考BootAnimation.cpp中的android函數):

1、將圖片文件xx.png放置到 frameworks/base/core/res/assets/images中。

2、再在函數中完成對應的調用:

  • 聲明對應的類型:Texture mTexture
  • 加載initTexture(&mTexture, mAssets, "images/xx.png");
  • 使用openGL來繪制界面(略)

添加開機聲音

既然我們已經知道了關於開機效果顯示的大致流程。

那么添加開機聲音也很簡單,我們可以使用MediaPlayer這個類來完成我們的需求。

聲明與實現

首先在BootAnimation.h添加方法的聲明和頭文件的引用

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

添加: void bootMusic();的聲明以及對應的實現

// frameworks/base/cmds/bootanimation/BootAnimation.h
class BootAnimation : public Thread, public IBinder::DeathRecipient
{
    //...
private:
    void bootMusic();
}


// frameworks/base/cmds/bootanimation/BootAnimation.cpp
void BootAnimation::bootMusic()
{
    int index;
    const char *fileName = "/system/media/boot.wav";
    MediaPlayer* mp = new MediaPlayer();
    audio_devices_t device = AudioSystem::getDevicesForStream(AUDIO_STREAM_ENFORCED_AUDIBLE);
    if (mp->setDataSource(NULL, fileName, NULL) == NO_ERROR)
    {
        mp->setAudioStreamType(AUDIO_STREAM_ENFORCED_AUDIBLE/*AudioSystem: :ENFORCED_AUDIBLE*/);
        mp->prepare();
    }
    LOGE ("bootMusic\n");
    AudioSystem::initStreamVolume(AUDIO_STREAM_ENFORCED_AUDIBLE, 0,7);
    AudioSystem::setStreamVolumeIndex(AUDIO_STREAM_ENFORCED_AUDIBLE, 7, device);
    AudioSystem::getStreamVolumeIndex(AUDIO_STREAM_ENFORCED_AUDIBLE/*AudioSystem::ENFORCED_AUDIBLE*/, &index, device);
    LOGE ("index %d",index);
    if (index != 0)
    {
        LOGD("playing %s", fileName);
        mp->setVolume(0.4f, 0.4f);
        mp->seekTo(0);
        mp->start();
    }
}

只要fileName對應的聲音文件存在而且有權限訪問到,那么無所謂放在哪里。

此后,在合適的地方(android ()或者movie ())調用即可,例如:

bool BootAnimation::movie()
{
    Animation* animation = loadAnimation(mZipFileName);
    // ...
    glEnable(GL_TEXTURE_2D);
    glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	// ...
    
    bootMusic(); // 播放聲音 (只要在播放動畫之前播放即可)
    
    playAnimation(*animation); // 播放動畫

    // ...

    return false;
}

Android.mk

光有頭文件還不夠,播放聲音還需要引入對應的庫:

# frameworks/base/cmds/bootanimation/Android.mk

# ...

LOCAL_SHARED_LIBRARIES := \
    libcutils \
    liblog \
    libandroidfw \
    libutils \
    libbinder \
    libui \
    libskia \
    libEGL \
    libGLESv1_CM \
    libgui \
    libOpenSLES \
    libtinyalsa \
    libregionalization \
    libmedia # 注意,libmedia是新添加的;
    
# ...

大功告成,這樣就成功的添加了開機音樂。

修改鈴聲

也許有人會問,那android系統自帶的那些音樂和鈴聲在什么地方呢?

系統默認了很多的聲音,如果有需要,可以修改frameworks/base/data/sounds下面文檔及文檔夾中的聲音文檔。

至於編譯完成后放到什么分區那是由AllAudio.mk決定的。

AllAudio.mk的作用:是將這些音樂文檔全部打包到系統system/media/audio下面各個模塊的文檔,然后在系統開機的時候,掃描這些文檔,將其加入到數據庫中,之后在設置中更換聲音時,則直接從數據庫中查詢這些音樂文檔,然后供用戶選擇。

如果需要添加某個鈴聲,可以這么做:

1、在AllAudio.mk添加一列類似這樣的內容:$(LOCAL_PATH)/aaa.ogg:system/media/audio/bbb/xxx.ogg

2、再將aaa.ogg拷貝到frameworks/base/data/sounds

修改也是類似的原理。

當然,也可以通過修改mk文件中指定的音樂文檔名來實現靜音等目的。

例如,ro.config.notification_sound(通知默認的音樂文檔文檔名)在build/target/product/full_base.mk 中定義,如果我們不想有聲音那么我們可以將默認值改為不存在的文檔,則不會播放通知聲音了。當然我們也可以在客戶定義的mk中使用PRODUCT_PROPERTY_OVERRIDES 去復寫此屬性,將其指定為不存在文檔或者為空,這樣就不會有通知聲音響了。

修改開機動畫

這里介紹bootanimation.zip如何制作。

開機動畫包內容

先看看bootanimation.zip的內容:解壓.zip文件后,會有n個存放圖片的文件夾(partn)+1個desc.txt文件。

開機動畫壓縮包不能包含bootanimation文件夾,必現是如下格式

├── desc.txt
├── part0
│   ├── 00013.png
│   ├── 00014.png
│   ├── 00052.png
└── part1
    ├── 00013.png
    ├── 00015.png
    ├── 00019.png
    └── 00069.png

上圖中的文件夾名字可隨便命名(對應desc.txt即可),里面存放的就是開機要顯示的圖片。

desc.txt解析

打開以后可以看到是類似這樣的內容。

240 320 1
p 2 0 part0
p 0 0 part1

第一行代表幀率以及動畫大小:

240 320 1
每秒1幀

此后的每一行代表每一段動畫具體的效果:

p 2 0 part0
代表一段動畫 代表文件夾播放的次數,0代表永遠循環 表示這部分播完后下部分開始的間隔 代表從哪個文件夾中尋找動畫

一般來說,將最后的那段動畫設置成循環播放,就可以在進入系統界面之前一直有畫面,不會出現黑屏的情況(所有動畫都做完了,但是還沒進入到系統界面就會出現黑屏)。

最后一行是空行,代表文件結束;很多人在改動時候會把這一行刪掉,如果制作以后失敗了,那么可以將這一行加上去試試。

圖片替換

圖片需要統一格式為png,且各圖片的大小需要相同。

圖片的命名可以隨意,但是最后的數字要有順序。

zip制作

開機動畫壓縮格式必須為存儲方式。

在Windows中可以在壓縮時,指定壓縮級別為不壓縮/存檔。由於Windows下壓縮軟件良莠不齊,因此建議在Linux中 制作。

Linux下可以使用下列命令:

cd bootanimation
zip -0 -r ../bootanimation.zip ./*


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM