Android 4.4.2开机动画支持系统语言切换

来源:互联网 发布:网络攻击与防范论文 编辑:程序博客网 时间:2024/05/16 10:32

这里写图片描述

前言

一般情况下我们Android设备的开机动画是以图片动画的形式显示出来的,如果我们的动画里面有文字,而恰好我们设备的必须支持多语言。肿么办,原生系统的开机动画只有一个,怎么样才能做到支持多语言多动画呢?

项目思路

要想支持多语言多动画,我们肯定得知道当前设置的是什么语言?然后,再根据语言去加载对应的开机动画(准备对应语言的开机动画素材包,即bootanimation.zip)。这里没有介绍Android的开机动画原理,如果不懂的朋友,可以去网上搜索相关的知识,这里就不补充了。以后有可能会写一篇关于开机动画流程的文章。好,大概的思路有了,就是先获取当前系统语言,然后,加载对应的开机动画。

项目实战

这里先大概说下,开机动画的加载序列图,如下图:
这里写图片描述

源码路径:

frameworks/base/cmds/bootanimation/bootanimation_main.cppframeworks/base/cmds/bootanimation/BootAnimation.cppframeworks/base/cmds/bootanimation/BootAnimation.hsystem/core/libutils/Threads.cppsystem/core/include/utils/Thread.hsystem/core/include/utils/RefBase.hsystem/core/libutils/RefBase.cppsystem/core/include/utils/StrongPointer.h

从上面的序列图中,我们可以知道,开机动画加载绘制主要集中在readyToRun和threadLoop函数中处理。下面来看下这两个函数分别是怎么处理的。

BootAnimation.cpp

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    sp<SurfaceControl> control = session()->createSurface(String8("BootAnimation"),            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, dummy;    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;    mAndroidAnimation = true;    // 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);    //判断bootanimation.zip开机动画包是否存在,存在就绘制bootanimation.zip中的动画,否则绘制android原生动画    if ((encryptedAnimation &&            (access(SYSTEM_ENCRYPTED_BOOTANIMATION_FILE, R_OK) == 0) &&            (mZip.open(SYSTEM_ENCRYPTED_BOOTANIMATION_FILE) == NO_ERROR)) ||            ((access(USER_BOOTANIMATION_FILE, R_OK) == 0) &&            (mZip.open(USER_BOOTANIMATION_FILE) == NO_ERROR)) ||            ((access(SYSTEM_BOOTANIMATION_FILE, R_OK) == 0) &&            (mZip.open(SYSTEM_BOOTANIMATION_FILE) == NO_ERROR))) {        mAndroidAnimation = false;    }    return NO_ERROR;}

系统在readyToRun中主要是做一些绘制初始化工作和bootanimation.zip是否存在的事情,如果bootanimation.zip不存在就是使用系统默认的动画。接下来看下threadLoop()函数

bool BootAnimation::threadLoop(){    bool r;    if (mAndroidAnimation) { //绘制Andriod原生动画        r = android();    } else { //绘制bootanimation.zip中的自定义动画        r = movie();    }    // No need to force exit anymore    property_set(EXIT_PROP_NAME, "0");    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;}

至于android()和movie()里的具体内容这里就不详叙了。它们的目的都是绘制开机动画。不过,一个是framwork 中assets目录下png图片,一个是bootanimation.zip中的图片。

现在回到我们的问题点,根据不同语言显示对应语言的开机动画。从上面的开机动画加载流程中我们已经知道,我们只需要在readyToRun中获取当前系统语言,然后让其加载对应的bootanimation.zip即可。注:这里我们需要给不同语言的开机动画包设置对应的语言路径。例如:

/system/media/bootanimation.zip/system/media/zh/bootanimation.zip/system/media/en/bootanimation.zip

好,现在开始我们的修改步骤吧!

第一步:修改开机动画加载路径

BootAnimation.cpp

#define SYSTEM_PATH "/system/media"#define BOOTANIMAION_FILE "bootanimation.zip"status_t BootAnimation::readyToRun() {    ...    mAndroidAnimation = true;    // 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, "");    //---------------add by steven zhang  start---------------------    //zh en    //获取当前系统语言    char language[PROPERTY_VALUE_MAX];    property_get("persist.sys.language", language, "zh");    char systemBootAnimaPath[PROPERTY_VALUE_MAX];    //设置对应的开机动画路径,例如:/system/media/zh/bootanimation.zip    sprintf(systemBootAnimaPath, "%s/%s/%s", SYSTEM_PATH, language, BOOTANIMAION_FILE);    ALOGD("systemBootAnimaPath::%s-----",systemBootAnimaPath);    //---------------add by steven zhang  end---------------------    bool encryptedAnimation = atoi(decrypt) != 0 || !strcmp("trigger_restart_min_framework", decrypt);    //判断bootanimation.zip开机动画包是否存在,存在就绘制bootanimation.zip中的动画,否则绘制android原生动画    if ((encryptedAnimation &&            (access(SYSTEM_ENCRYPTED_BOOTANIMATION_FILE, R_OK) == 0) &&            (mZip.open(SYSTEM_ENCRYPTED_BOOTANIMATION_FILE) == NO_ERROR)) ||            //---------------add by steven zhang  start---------------------            ((access(systemBootAnimaPath, R_OK) == 0) &&            (mZip.open(systemBootAnimaPath) == NO_ERROR)) ||            //---------------add by steven zhang  end---------------------            ((access(USER_BOOTANIMATION_FILE, R_OK) == 0) &&            (mZip.open(USER_BOOTANIMATION_FILE) == NO_ERROR)) ||            ((access(SYSTEM_BOOTANIMATION_FILE, R_OK) == 0) &&            (mZip.open(SYSTEM_BOOTANIMATION_FILE) == NO_ERROR))) {        mAndroidAnimation = false;    }    return NO_ERROR;

通过上面这一步我们已经将加载开机动画的路径修改成对应语言的开机动画路径了。接下来我们要做的就是在对应的路径下放入开机动画包。

第二步:对应的语言路径下放入开机动画包

在device目录下找到对应项目的mk文件,在其中加入如下代码:
device/xxx/yyy.mk

PRODUCT_COPY_FILES += \        device/xxx/yyy/bootMedia/bootanimation.zip:system/media/bootanimation.zip \        device/xxx/yyy/bootMedia/zh/bootanimation.zip:system/media/zh/bootanimation.zip \        device/xxx/yyy/bootMedia/en/bootanimation.zip:system/media/en/bootanimation.zip \

这一步的操作就是将源码中的不同语言的开机动画包拷贝到系统中对应的位置。

第三步:编译系统验证效果

这里就不多说怎么编译系统和验证了。感兴趣的同学实现了上面两部后,基本上是可以实现开机动画跟着语言变化而变化的需求了。

总结

本来只是想写一下开机动画怎么支持多语言的问题,写着写着发现后面部分同学可能不知道开机动画的加载流程。所以后面准备好好讲下Android系统开机动画流程。

原创粉丝点击