ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Android 7 修改启动动画和开机声音

2021-03-05 15:02:43  阅读:260  来源: 互联网

标签:动画 BootAnimation TEXTURE EGL 开机 Android GL bootanimation


背景

在修改开机音量的时候,发现找不到对应的声音功能调用。

因此了解了一下安卓的开机声音是如何实现的。

安卓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,TEXTURE,EGL,开机,Android,GL,bootanimation
来源: https://www.cnblogs.com/schips/p/14486244.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有