1.? 制作bootanimation.zip
參考解壓的一個(gè)bootanimation.zip, 里面有兩個(gè)文件夾一個(gè)desc.txt描述文件
兩個(gè)文件夾都是開(kāi)機(jī)動(dòng)畫(huà)的圖片,desc.txt:
1080 1920 10
p 1 0 part1
p 0 0 part2
1080 1920 為分辨率, 10表示10幀每秒
p 1 0 part1 :p就是play。1是播放一次,0是無(wú)限次。0代表階段間隔幀數(shù)為0,也就是幀動(dòng)畫(huà)形式播放圖片。part1指定了要播放的第一個(gè)文件夾為part1(也可以取別的名稱(chēng),做相應(yīng)修改即可)
p? 0? 0? part2:第一個(gè)0表示循環(huán)播放。第二個(gè)0表示每張圖片間隔幀數(shù)為0(和上面指令一樣)。part2表示要循環(huán)播放的文件夾
將制作好的文件打包成bootanimation.zip即可,注意:必須是zip格式,且包的大小最好不要超過(guò)3M。然后放入/system/media/目錄下即可。
最近在制作開(kāi)機(jī)動(dòng)畫(huà)過(guò)程中發(fā)現(xiàn)添加開(kāi)機(jī)動(dòng)畫(huà)后其一直不能顯示,經(jīng)過(guò)千辛萬(wàn)苦的尋找最終得出如下結(jié)論:
開(kāi)機(jī)動(dòng)畫(huà)zip的壓縮盡量在linux環(huán)境下進(jìn)行,在windows或者ubuntu的UI界面下壓縮 bootanimation.zip可能會(huì)造成開(kāi)機(jī)動(dòng)畫(huà)不能顯示,在linux下,進(jìn)入素材目錄,執(zhí)行壓縮命令:
zip-Z store bootanimation.zip part0/*.pngpart1/*.pngdesc.txt
Windows下打包ZIP也需要進(jìn)入素材目錄。例如:選中part0,part1,desc.txt三個(gè)文件,右鍵選擇”添加到壓縮文件”,選擇”ZIP”壓縮,“存儲(chǔ)”模式即可。
2. 定制到系統(tǒng)
開(kāi)機(jī)動(dòng)畫(huà)一般放在系統(tǒng) device/xx/xx/media/bootanimation.zip,并且要在具體的項(xiàng)目mk文件中聲明:
PRODUCT_COPY_FILES += device/xxx/$(TARGET_PRODUCT)/media/bootanimation.zip:system/media/bootanimation.zip
我們可以看出這句配置的目的是把bootanimation.zip拷貝到系統(tǒng)system/meida目錄下.
3. 跟蹤源碼
surfaceflinger.rc 下啟動(dòng)surfaceflinger
service surfaceflinger /system/bin/surfaceflinger
-------------------------------------------------------------------------------------------------------------------
SurfaceFlinger.cpp啟動(dòng)動(dòng)畫(huà)
startBootAnim() -> mStartPropertySetThread->Start();
/frameworks/native/services/surfaceflinger/StartPropertySetThread.cpp
bool StartPropertySetThread::threadLoop() {
? ? // Set property service.sf.present_timestamp, consumer need check its readiness
? ? property_set(kTimestampProperty, mTimestampPropertyValue ? "1" : "0");
? ? // Clear BootAnimation exit flag
? ? property_set("service.bootanim.exit", "0");
? ? // Start BootAnimation if not started
? ? property_set("ctl.start", "bootanim");
? ? // Exit immediately
? ? return false;
}
其中先將”service.bootanim.exit”標(biāo)志為 0,這個(gè)標(biāo)志用于在bootanim進(jìn)程中檢測(cè)開(kāi)機(jī)動(dòng)畫(huà)是否結(jié)束,
然后通過(guò)發(fā)”ctl.start”請(qǐng)求給init進(jìn)程,啟動(dòng)”bootanim”服務(wù).
-------------------------------------------------------------------------------------------------------------------
frameworks/base/cmds/bootanimation/bootanimation_main.cpp 中的main函數(shù)啟動(dòng)BootAnimation.cpp
onFirstRef -> readyToRun
在readyToRun 中 會(huì)有獲取動(dòng)畫(huà)的判斷 getAnimationFileName
/** Get bootup Animation File
* Parameter:
* 1.defaultfile: system default media file
* 2.isShutdown : is shutdown or boot status
* Return Value : Animation File path
**/
const char *BootAnimation::getAnimationFileName(const char * defaultfile,bool isShutdown)
{
? ? // Load animations of Carrier through regionalization environment
? ? if (Environment::isSupported()) {
? ? ? ? Environment* environment = new Environment();
? ? ? ? int isShutdownState = Environment::BOOT_STATUS;
? ? ? ? if (isShutdown) {
? ? ? ? ? isShutdownState = Environment::SHUTDOWN_STATUS;
? ? ? ? }
? ? ? ? const char* animFile = environment->getMediaFile(
? ? ? ? ? ? ? ? Environment::ANIMATION_TYPE, isShutdownState);
? ? ? ? ALOGE("Get Carrier Animation type: %d,status:%d", Environment::ANIMATION_TYPE,isShutdown);
? ? ? ? if (animFile != NULL && strcmp(animFile, "") != 0) {
? ? ? ? ? return animFile;
? ? ? ? }else{
? ? ? ? ? ALOGD("Get Carrier Animation file: %s failed", animFile);
? ? ? ? }
? ? ? ? delete environment;
? ? }
? ? return defaultfile;
}
-------------------------------------------------------------------------------------------------------------------
繼續(xù)跟蹤 environment->getMediaFile
在frameworks/base/libs/regionalization/Environment.cpp 我們發(fā)現(xiàn) getMediaFile方法中的BOOT_SHUTDOWN_FILE 常量
static const char* BOOT_SHUTDOWN_FILE[2][2] = {
? ? ? ? {"/system/media/bootanimation.zip", "/system/media/shutdownanimation.zip"},
? ? ? ? {"/system/media/boot.wav", "/system/media/shutdown.wav"} };
就是我們對(duì)應(yīng)的配置。
-------------------------------------------------------------------------------------------------------------------
后續(xù)就是對(duì)動(dòng)畫(huà)的播放BootAnimation.threadLoop 當(dāng)mZipFileName
if(mZipFileName.isEmpty()) {
? ? ? r = android(); //播放Android系統(tǒng)默認(rèn)的開(kāi)機(jī)動(dòng)畫(huà)
? }
android() 播放的是系統(tǒng)原生動(dòng)畫(huà),“android”字樣加上不斷移動(dòng)的光影效果。
movie() 則是讀取bootanimation.zip 中的幀動(dòng)畫(huà),一張一張的輪播,形成動(dòng)畫(huà)效果。
檢測(cè)到 “service.bootanim.exit” 的值被修改成1 之后,就調(diào)用 requestExit() 結(jié)束動(dòng)畫(huà)
期間會(huì)走到wms的enableScreenAfterBoot() ,最后調(diào)用SurfaceFlinger::bootFinished()完成開(kāi)機(jī).
---------------------------------------------分割線--------------------------------------------------
最近又多了一些增加開(kāi)機(jī)鈴聲的需求。
這個(gè)有多種改法:1.自己添加播放 2直接使用bootAnimation
第二種比較簡(jiǎn)單:
首先我們要看下 frameworks/base/cmds/bootanimation這個(gè)目錄:

我們需要添加一個(gè)audio.wav 的開(kāi)機(jī)鈴聲.
把它放在bootanimation/part0/ 中, 然后在bootanimation/中執(zhí)行打包命令:
zip -0qry -i \*.txt \*.png \*.wav @ ../bootanimation.zip *.txt part*
會(huì)生成一個(gè)bootanimation.zip然后執(zhí)行
adb push bootanimation.zip /system/media
這些東西可以參考FORMAT.md 這個(gè)文件。
如果直接用的話,上述步驟已經(jīng)足夠,參考代碼給個(gè)傳送門(mén):
https://download.csdn.net/download/zghlezh/10474732