Android开机动画启动流程

Android 系统启动系列文章:

首语

在Android设备开机启动时,会展示Android开机动画,用于增加用户体验和展示设备品牌等信息。它也是Android系统启动的一部分。开机动画是由bootanimation负责的,因此首先先了解下bootanimation是如何启动的。

bootanimation 启动脚本分析

init进程中第二阶段(SecondStageMain)的主要工作有初始化属性服务,加载启动脚本,解析init.rc文件等。

源码路径:system/core/init/init.cpp

int SecondStageMain(int argc, char** argv) {
    ...
    LoadBootScripts(am, sm);
    ...
}
static void LoadBootScripts(ActionManager& action_manager, ServiceList& service_list) {
    Parser parser = CreateParser(action_manager, service_list);

    std::string bootscript = GetProperty("ro.boot.init_rc", "");
    if (bootscript.empty()) {
        parser.ParseConfig("/system/etc/init/hw/init.rc");
        if (!parser.ParseConfig("/system/etc/init")) {
            late_import_paths.emplace_back("/system/etc/init");
        }
        // late_import is available only in Q and earlier release. As we don't
        // have system_ext in those versions, skip late_import for system_ext.
        parser.ParseConfig("/system_ext/etc/init");
        if (!parser.ParseConfig("/vendor/etc/init")) {
            late_import_paths.emplace_back("/vendor/etc/init");
        }
        if (!parser.ParseConfig("/odm/etc/init")) {
            late_import_paths.emplace_back("/odm/etc/init");
        }
        if (!parser.ParseConfig("/product/etc/init")) {
            late_import_paths.emplace_back("/product/etc/init");
        }
    } else {
        parser.ParseConfig(bootscript);
    }
}

在init.rc文件中,可以看到通过class_start来启动 classname 为 core 的 Service。在bootanimation.rc文件中,可以清楚看到Service name为bootanim,执行程序路径为:/system/bin/bootanimation,类名:core。disabled表示系统启动时,不会自动启动bootanimation。那是谁启动bootanimation呢?

SurfaceFlinger它负责管理图形内容的渲染,并将多个图层(包括应用程序窗口、系统UI元素和硬件覆盖层)合成到设备的屏幕上。所以首先需要启动SurfaceFlinger,开机动画的渲染和合成是它完成的,继续分析SurfaceFlinger启动流程。

源码路径:system/core/rootdir/init.rc

...
    # Start standard binderized HAL daemons
    class_start hal

    class_start core
...

源码路径:frameworks/base/cmds/bootanimation/bootanim.rc

service bootanim /system/bin/bootanimation
    class core animation
    user graphics
    group graphics audio
    disabled
    oneshot
    ioprio rt 0
    task_profiles MaxPerformance

SurfaceFlinger启动流程

而surfaceflinger.rc文件中,可以清楚看到Service name为surfaceflinger,执行程序路径为:/system/bin/surfaceflinger,类名:core。

因此,可以知道SurfaceFlinger是在init进程启动第二阶段进行启动的。

源码路径:frameworks/native/services/surfaceflinger/surfaceflinger.rc

service surfaceflinger /system/bin/surfaceflinger
    class core animation
    user system
    group graphics drmrpc readproc
    capabilities SYS_NICE
    onrestart restart --only-if-running zygote
    task_profiles HighPerformance
    socket pdx/system/vr/display/client     stream 0666 system graphics u:object_r:pdx_display_client_endpoint_socket:s0
    socket pdx/system/vr/display/manager    stream 0666 system graphics u:object_r:pdx_display_manager_endpoint_socket:s0
    socket pdx/system/vr/display/vsync      stream 0666 system graphics u:object_r:pdx_display_vsync_endpoint_socket:s0

看下SurfaceFlinger的main函数,创建了SurfaceFlinger并且初始化,调用StartPropertySetThread的Start函数。

源码路径:frameworks/native/services/surfaceflinger/main_surfaceflinger.cpp

int main(int, char**) {
    ...
    // instantiate surfaceflinger
    sp<SurfaceFlinger> flinger = surfaceflinger::createSurfaceFlinger();
    ...
    // initialize before clients can connect
    flinger->init();
    ...
}

源码路径:frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp

void SurfaceFlinger::init() {
    ...
    mStartPropertySetThread = getFactory().createStartPropertySetThread(presentFenceReliable);

    if (mStartPropertySetThread->Start() != NO_ERROR) {
        ALOGE("Run StartPropertySetThread failed!");
    }
    ...
}

可以看到将系统属性service.bootanim.exit/service.bootanim.progress设置为0,并将ctl.start设置为bootanim,当系统属性发生改变时,init进程就会接收到一个系统属性变化通知,这个通知最终是由在init进程中的函数handle_property_set_fd来处理的。设置ctl.start表示启动一个服务,这样bootanimation就被启动了。

源码路径:frameworks/native/services/surfaceflinger/StartPropertySetThread.cpp

status_t StartPropertySetThread::Start() {
    return run("SurfaceFlinger::StartPropertySetThread", PRIORITY_NORMAL);
}

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");
    property_set("service.bootanim.progress", "0");
    // Start BootAnimation if not started
    property_set("ctl.start", "bootanim");
    // Exit immediately
    return false;
}

bootanimation启动流程

分析bootanimation的main函数,首先判断是否禁用了启动动画,没有则创建一个binder线程池,再创建BootAnimation,等待SurfaceFlinger启动完成。

源码路径:frameworks/base/cmds/bootanimation/bootanimation_main.cpp

int main()
{
    setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_DISPLAY);
	//是否禁用了启动动画
    bool noBootAnimation = bootAnimationDisabled();
    ALOGI_IF(noBootAnimation,  "boot animation disabled");
    if (!noBootAnimation) {
		//创建binder线程池
        sp<ProcessState> proc(ProcessState::self());
        ProcessState::self()->startThreadPool();

        // create the boot animation object (may take up to 200ms for 2MB zip)
        sp<BootAnimation> boot = new BootAnimation(audioplay::createAnimationCallbacks());

        waitForSurfaceFlinger();

        boot->run("BootAnimation", PRIORITY_DISPLAY);

        ALOGV("Boot animation set up. Joining pool.");

        IPCThreadState::self()->joinThreadPool();
    }
    return 0;
}

源码路径:frameworks/base/cmds/bootanimation/BootAnimationUtil.cpp

bool bootAnimationDisabled() {
    char value[PROPERTY_VALUE_MAX];
    //启动动画调试模式
    property_get("debug.sf.nobootanimation", value, "0");
    if (atoi(value) > 0) {
        return true;
    }

    property_get("ro.boot.quiescent", value, "0");
    if (atoi(value) > 0) {
        // Only show the bootanimation for quiescent boots if this system property is set to enabled
        //禁用启动动画
        if (!property_get_bool("ro.bootanim.quiescent.enabled", false)) {
            return true;
        }
    }

    return false;
}

void waitForSurfaceFlinger() {
    // TODO: replace this with better waiting logic in future, b/35253872
    int64_t waitStartTime = elapsedRealtime();
    sp<IServiceManager> sm = defaultServiceManager();
    const String16 name("SurfaceFlinger");
    const int SERVICE_WAIT_SLEEP_MS = 100;
    const int LOG_PER_RETRIES = 10;
    int retry = 0;
    while (sm->checkService(name) == nullptr) {
        retry++;
        if ((retry % LOG_PER_RETRIES) == 0) {
            ALOGW("Waiting for SurfaceFlinger, waited for %" PRId64 " ms",
                  elapsedRealtime() - waitStartTime);
        }
        usleep(SERVICE_WAIT_SLEEP_MS * 1000);
    };
    int64_t totalWaited = elapsedRealtime() - waitStartTime;
    if (totalWaited > SERVICE_WAIT_SLEEP_MS) {
        ALOGI("Waiting for SurfaceFlinger took %" PRId64 " ms", totalWaited);
    }
}

BootAnimation类有几个重要函数

  • onFirstRef(),属于父类RefBase,它用于实现引用计数的对象管理,新增引用计数时调用。
  • binderDied() ,Binder结束时,就会回调binderDied()方法。
  • readyToRun() ,Thread执行前的初始化工作。
  • threadLoop() ,线程根据逻辑是否循环执行。
  • android(),显示系统默认的开机画面。
  • movie(),显示用户自定义的开机动画。
  • loadAnimation(),加载动画。
  • playAnimation(),播放动画。
  • checkExit(),检查是否退出动画。

源码路径:frameworks/base/cmds/bootanimation/BootAnimation.h

private:
    virtual bool        threadLoop();
    virtual status_t    readyToRun();
    virtual void        onFirstRef();
    virtual void        binderDied(const wp<IBinder>& who);
	...
	//系统默认的开机画面
	bool android();
	//用户自定义的开机动画
    bool movie();
	...
    //加载动画
	Animation* loadAnimation(const String8&);
	//播放动画
    bool playAnimation(const Animation&);
    void releaseAnimation(Animation*) const;
    bool parseAnimationDesc(Animation&);
    bool preloadZip(Animation &animation);
    void findBootAnimationFile();
    bool findBootAnimationFileInternal(const std::vector<std::string>& files);
    bool preloadAnimation();
    EGLConfig getEglConfig(const EGLDisplay&);
    ui::Size limitSurfaceSize(int width, int height) const;
    void resizeSurface(int newWidth, int newHeight);
    void projectSceneToWindow();

    bool shouldStopPlayingPart(const Animation::Part& part, int fadedFramesCount,
                               int lastDisplayedProgress);
	//检查是否退出动画
    void checkExit();

BootAnimation构造函数中,创建了SurfaceComposerClient,mSession用来和SurfaceFlinger执行Binder进程间通信,执行linkToComposerDeath方法用于获取SurfaceFlinger死亡通知,preloadAnimation方法开始加载动画,首先去查询动画文件,动画文件的存放位置如代码中定义所示。动画文件是按照指定位置顺序读取,如果读取到当前位置动画文件,则不读取后续动画文件。

源码路径:frameworks/base/cmds/bootanimation/BootAnimation.cpp

static const char OEM_BOOTANIMATION_FILE[] = "/oem/media/bootanimation.zip";
static const char PRODUCT_BOOTANIMATION_DARK_FILE[] = "/product/media/bootanimation-dark.zip";
static const char PRODUCT_BOOTANIMATION_FILE[] = "/product/media/bootanimation.zip";
static const char SYSTEM_BOOTANIMATION_FILE[] = "/system/media/bootanimation.zip";
static const char APEX_BOOTANIMATION_FILE[] = "/apex/com.android.bootanimation/etc/bootanimation.zip";
static const char PRODUCT_ENCRYPTED_BOOTANIMATION_FILE[] = "/product/media/bootanimation-encrypted.zip";
static const char SYSTEM_ENCRYPTED_BOOTANIMATION_FILE[] = "/system/media/bootanimation-encrypted.zip";
static const char OEM_SHUTDOWNANIMATION_FILE[] = "/oem/media/shutdownanimation.zip";
static const char PRODUCT_SHUTDOWNANIMATION_FILE[] = "/product/media/shutdownanimation.zip";
static const char SYSTEM_SHUTDOWNANIMATION_FILE[] = "/system/media/shutdownanimation.zip";

static constexpr const char* PRODUCT_USERSPACE_REBOOT_ANIMATION_FILE = "/product/media/userspace-reboot.zip";
static constexpr const char* OEM_USERSPACE_REBOOT_ANIMATION_FILE = "/oem/media/userspace-reboot.zip";
static constexpr const char* SYSTEM_USERSPACE_REBOOT_ANIMATION_FILE = "/system/media/userspace-reboot.zip";

BootAnimation::BootAnimation(sp<Callbacks> callbacks)
        : Thread(false), mLooper(new Looper(false)), mClockEnabled(true), mTimeIsAccurate(false),
        mTimeFormat12Hour(false), mTimeCheckThread(nullptr), mCallbacks(callbacks) {
    mSession = new SurfaceComposerClient();

    std::string powerCtl = android::base::GetProperty("sys.powerctl", "");
    if (powerCtl.empty()) {
        mShuttingDown = false;
    } else {
        mShuttingDown = true;
    }
    ALOGD("%sAnimationStartTiming start time: %" PRId64 "ms", mShuttingDown ? "Shutdown" : "Boot",
            elapsedRealtime());
}
void BootAnimation::onFirstRef() {
    //接收SurfaceFlinger死亡通知
    status_t err = mSession->linkToComposerDeath(this);
    SLOGE_IF(err, "linkToComposerDeath failed (%s) ", strerror(-err));
    if (err == NO_ERROR) {
        // Load the animation content -- this can be slow (eg 200ms)
        // called before waitForSurfaceFlinger() in main() to avoid wait
        ALOGD("%sAnimationPreloadTiming start time: %" PRId64 "ms",
                mShuttingDown ? "Shutdown" : "Boot", elapsedRealtime());
        preloadAnimation();
        ALOGD("%sAnimationPreloadStopTiming start time: %" PRId64 "ms",
                mShuttingDown ? "Shutdown" : "Boot", elapsedRealtime());
    }
}
bool BootAnimation::preloadAnimation() {
    findBootAnimationFile();
    if (!mZipFileName.isEmpty()) {
        //加载动画
        mAnimation = loadAnimation(mZipFileName);
        return (mAnimation != nullptr);
    }

    return false;
}
void BootAnimation::findBootAnimationFile() {
    // 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 (!mShuttingDown && encryptedAnimation) {
        static const std::vector<std::string> encryptedBootFiles = {
            PRODUCT_ENCRYPTED_BOOTANIMATION_FILE, SYSTEM_ENCRYPTED_BOOTANIMATION_FILE,
        };
        if (findBootAnimationFileInternal(encryptedBootFiles)) {
            return;
        }
    }

    const bool playDarkAnim = android::base::GetIntProperty("ro.boot.theme", 0) == 1;
    static const std::vector<std::string> bootFiles = {
        APEX_BOOTANIMATION_FILE, playDarkAnim ? PRODUCT_BOOTANIMATION_DARK_FILE : PRODUCT_BOOTANIMATION_FILE,
        OEM_BOOTANIMATION_FILE, SYSTEM_BOOTANIMATION_FILE
    };
    static const std::vector<std::string> shutdownFiles = {
        PRODUCT_SHUTDOWNANIMATION_FILE, OEM_SHUTDOWNANIMATION_FILE, SYSTEM_SHUTDOWNANIMATION_FILE, ""
    };
    static const std::vector<std::string> userspaceRebootFiles = {
        PRODUCT_USERSPACE_REBOOT_ANIMATION_FILE, OEM_USERSPACE_REBOOT_ANIMATION_FILE,
        SYSTEM_USERSPACE_REBOOT_ANIMATION_FILE,
    };

    if (android::base::GetBoolProperty("sys.init.userspace_reboot.in_progress", false)) {
        findBootAnimationFileInternal(userspaceRebootFiles);
    } else if (mShuttingDown) {
        findBootAnimationFileInternal(shutdownFiles);
    } else {
        findBootAnimationFileInternal(bootFiles);
    }
}
bool BootAnimation::findBootAnimationFileInternal(const std::vector<std::string> &files) {
    for (const std::string& f : files) {
        if (access(f.c_str(), R_OK) == 0) {
            mZipFileName = f.c_str();
            return true;
        }
    }
    return false;
}
BootAnimation::Animation* BootAnimation::loadAnimation(const String8& fn) {
    if (mLoadedFiles.indexOf(fn) >= 0) {
        SLOGE("File \"%s\" is already loaded. Cyclic ref is not allowed",
            fn.string());
        return nullptr;
    }
    ZipFileRO *zip = ZipFileRO::open(fn);
    if (zip == nullptr) {
        SLOGE("Failed to open animation zip \"%s\": %s",
            fn.string(), strerror(errno));
        return nullptr;
    }

    ALOGD("%s is loaded successfully", fn.string());

    Animation *animation =  new Animation;
    animation->fileName = fn;
    animation->zip = zip;
    animation->clockFont.map = nullptr;
    mLoadedFiles.add(animation->fileName);
	//解析动画文件
    parseAnimationDesc(*animation);
    if (!preloadZip(*animation)) {
        releaseAnimation(animation);
        return nullptr;
    }

    mLoadedFiles.remove(fn);
    return animation;
}
bool BootAnimation::parseAnimationDesc(Animation& animation)  {
    String8 desString;

    if (!readFile(animation.zip, "desc.txt", desString)) {
        return false;
    }
    char const* s = desString.string();
    std::string dynamicColoringPartName = "";
    bool postDynamicColoring = false;

    // Parse the description file
    ...
}
bootanimation.zip

动画文件的压缩包里都存在一个动画配置文件desc.txt,它是描述开机动画是如何显示的。我们以device/google/atv/products/bootanimations/bootanimation.zip动画压缩包为例进行分析,它是AndroidTV存储动画文件的路径。desc.txt内容如下:

第1行用来描述开机动画在屏幕显示的大小及帧率。这个定义指示 bootanimation 的播放分辨率为 512x416 像素,帧率为 60 帧/秒。分辨率定义了动画的宽度和高度,而帧率定义了动画播放的流畅程度,即每秒播放的帧数。

第2行c:表示清除命令。1:表示清除的起始帧。0:表示清除的结束帧。part0:表示需要清除的动画帧所在的文件夹路径。这个定义指示在播放动画时,从指定的文件夹 part0 中清除第 1 帧。这样可以控制在播放过程中是否清除特定的帧,以实现动画效果的变化或平滑的过渡效果。3-5行同理。

最后一行f:表示循环命令。0:表示循环的起始帧。0:表示循环的结束帧。part4:表示需要循环的动画帧所在的文件夹路径。10:表示循环次数。该行指示在播放动画时,从指定的文件夹中的起始帧到结束帧之间的帧进行循环播放,重复播放 10 次。

512 416 60
c 1 0 part0
c 1 15 part1
c 1 0 part2
c 1 0 part3
f 0 0 part4 10

动画配置文件还有指定播放顺序的,例如如下的配置,p:表示播放顺序命令。1:表示播放的顺序。0:表示播放的循环次数。0 表示无限循环。folder1:表示动画帧所在的文件夹路径。根据这个定义,folder1 是一个目录,包含了一组 bootanimation 动画帧文件。该行指示在播放动画时,按照顺序从 folder1 目录中加载帧并进行播放。

p 1 0 folder1 

加载动画执行完成后,接下来会执行主体函数threadLoop,首先判断自定义开机动画文件是否存在,如果不存在则执行Android方法,否则执行自定义动画Movie方法。Android和Movie方法最后都返回false。因此threadloop也返回false,代表代码只执行一次。最后获取service.bootanim.exit属性,如果值为1,循环就会退出,开机动画就会结束。service.bootanim.exit属性是在Activity Manager Service(AMS)中被修改为1的,在后面AMS中会讲到。

static const char EXIT_PROP_NAME[] = "service.bootanim.exit";
bool BootAnimation::threadLoop() {
    bool result;
    initShaders();

    // We have no bootanimation file, so we use the stock android logo
    // animation.
    if (mZipFileName.isEmpty()) {
        ALOGD("No animation file");
        //系统默认开机画面
        result = android();
    } else {
        //自定义开机动画显示
        result = movie();
    }

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

bool BootAnimation::android() {
    glActiveTexture(GL_TEXTURE0);

    SLOGD("%sAnimationShownTiming start time: %" PRId64 "ms", mShuttingDown ? "Shutdown" : "Boot",
            elapsedRealtime());
    //android-logo-mask.png和android-logo-shine.png保存在frameworks/base/core/res/assets/images/路径下
    initTexture(&mAndroid[0], mAssets, "images/android-logo-mask.png");
    initTexture(&mAndroid[1], mAssets, "images/android-logo-shine.png");

    mCallbacks->init({});
   	...
    return false;
}
bool BootAnimation::movie() {
    if (mAnimation == nullptr) {
        mAnimation = loadAnimation(mZipFileName);
    }

    if (mAnimation == nullptr)
        return false;
	...
    playAnimation(*mAnimation);
    releaseAnimation(mAnimation);
    mAnimation = nullptr;

    return false;
}
bool BootAnimation::playAnimation(const Animation& animation) {
    ...
    checkExit();
}
void BootAnimation::checkExit() {
    // Allow surface flinger to gracefully request shutdown
    char value[PROPERTY_VALUE_MAX];
    property_get(EXIT_PROP_NAME, value, "0");
    int exitnow = atoi(value);
    if (exitnow) {
        requestExit();
    }
}

总结

init进程是Android系统中的第一个用户空间进程。它负责启动各个系统服务和应用程序。在init进程启动过程中,SurfaceFlinger也被启动,SurfaceFlinger是Android中的显示系统服务,负责管理屏幕显示和图形渲染。开机动画需要使用SurfaceFlinger来显示。然后bootanimation也启动,进行开机动画的播放。bootanimation.zip中包含动画文件和动画配置文件。最终,当所有系统服务和应用程序启动完毕,开机动画结束,进入系统主界面。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
由于源文件大小为99.3MB,所以采用分卷压缩的方式进行上传   《Google Android SDK开发范例大全(第3版)》在上一版的基础上,以Android手机应用程序开发(采用Android SDK 2.3.3)为主题,超过200多个范例全面且深度地整合了手机、网络及服务等多个开发领域,为读者提高程序设计能力提供了很大的帮助。   全书共分11章,主要以范例集的方式来讲述Android的知识点,详细介绍了开发Android的人机交互界面、Android常用的开发控件、Android手机收发短信等通信服务、开发Android手机的自动服务功能和娱乐多媒体功能以及整合Android与Google强大的网络服务等内容。随书光盘中包括了所有范例的程序代码。   《Google Android SDK开发范例大全(第3版)》继承前两版由浅入深的方式,范例总数由原先的160多个增加到了200多个,在用户交互界面、手机控件、交互式通信服务、手机自助服务、娱乐多媒体等方面均增加了相应的范例来介绍新的开发技术,特别是新增加了第11章来专门介绍HTML5技术在Android移动设备里的应用,相信当下两个热门技术的交汇会碰撞出不一样的火花。   《Google Android SDK开发范例大全(第3版)》内容由Android的基础知识到实际开发应用,结构清晰、语言简洁,非常适合Android的初学者和Android的进阶程序开发者阅读参考。 目录   第1章 了解、深入、动手做   1.1 红透半边天的Android   1.2 本书目的及范例涵盖范围   1.3 如何阅读本书   1.4 使用本书范例   1.5 参考网站   第2章 Android初体验   2.1 安装Android SDK与ADT/DDMS   2.2 创建第一个Android项目(Hello Android!)   2.3 Android应用程序架构——从此开始   2.4 可视化的界面开发工具   2.5 部署应用程序到Android手机   第3章 用户人机界面   3.1 更改与显示文字标签   3.2 更改手机窗口画面底色   3.3 更改TextView文字颜色   3.4 置换TextView文字   3.5 取得手机屏幕大小   3.6 样式化的定型对象   3.7 简易的按钮事件   3.8 手机页面的转换   3.9 调用另一个Activity   3.10 不同Activity之间的数据传递   3.11 返回数据到前一个Activity   3.12 具有交互功能的对话框   3.13 置换文字颜色的机关   3.14 控制不同的文字字体   3.15 如iPhone拖动相片特效   3.16 自制计算器   3.17 关于(About)程序信息   3.18 程序加载中,请稍候   3.19 全屏幕以按钮重写   3.20 今晚到哪儿打牙祭   3.21 Android变脸   3.22 打勾显示输入的密码   3.23 Android多语系支持   3.24 判断手机操作系统版本是否允许运行程序   3.25 两个不同的程序彼此调用   3.26 指定安装应用程序迁移至SD卡   3.27 手机动态Layout主题随手势物换迁移   第4章 史上超豪华的手机控件   4.1 EditText与TextView共舞   4.2 设计具有背景图的按钮   4.3 给圣诞老人的信息   4.4 我同意条款   4.5 消费券采购列表   4.6 向左或向右   4.7 专业相框设计   4.8 自定义下拉菜单模式   4.9 动态添加/删除的Spinner菜单   4.10 心爱小宝贝相片集   4.11 快速地搜索手机文件引擎   4.12 按钮也能随单击变换   4.13 具自动提示功能的菜单   4.14 数字及模拟小时钟设计   4.15 动态输入日期与时间   4.16 猜猜红桃A在哪儿   4.17 后台程序运行进度提示   4.18 动态文字排版   4.19 在Activity里显示列表   4.20 以动态列表配置选项   4.21 查找程序根目录下所有文件   4.22 加载手机磁盘里的图片文件   4.23 动态放大缩小ImageView里的图片   4.24 动态旋转图片   4.25 猜猜我在想什么   4.26 离开与关闭程序的弹出窗口   4.27 隐藏式抽屉   4.28 手机桌面上的小玩意   4.29 手机图片搜索管理器   4.30 实时配置桌面上的AppWidget UI Layout   4.31 识别输入装置ID与InputDevice装置   4.32 选取文字的聪明文字联想   4.33 设计与Launcher相同的三页滑动Layout   第5章 交互式通信服务与手机控制   5.1 具有正则表达式的TextView   5.2 ACTION!CALL!拨打电话   5.3 自制发送短信程序   5.4 自制发送E-mail程序   5.5 自制日历手机数据库   5.6 手机振动的节奏   5.7 图文可视化提醒   5.8 状态栏的图标与文字提醒   5.9 搜索手机通讯录自动完成   5.10 取得联系人资料   5.11 制作有图标的文件资源管理器   5.12 还原手机默认桌面   5.13 置换手机后台图   5.14 获取手机现存桌面   5.15 文件资源管理器再进化   5.16 取得目前File与Cache的路径   5.17 打开/关闭WiFi服务   5.18 取得SIM卡内的信息   5.19 调用拨号按钮   5.20 DPAD按键处理   5.21 任务管理器正在运行的程序   5.22 动态更改屏幕方向   5.23 系统设置更改事件   5.24 取得电信网络与手机的相关信息   5.25 建立自己的手写笔画图案   5.26 判断手持设备的WiFi与GPS状态   5.27 手机安全设置管理器   5.28 Shell Script运行Cmmand   5.29 模拟文件下载Notification进度变化与关闭   5.30 取得已安装应用程序列表与安装日期信息   5.31 造假的Toast画面   5.32 剪贴簿管理器   第6章 手机自动服务纪实   6.1 您有一条短信pop up提醒   6.2 手机电池计量还剩多少   6.3 群发拜年短信给联系人   6.4 开始与停止系统服务   6.5 通过短信发送E-mail通知   6.6 手机拨接状态   6.7 有来电,发送邮件通知   6.8 存储卡剩余多少容量   6.9 访问本机内存与存储卡   6.10 实现可定时响起的闹钟   6.11 黑名单来电自动静音   6.12 手机翻背面即静音振动   6.13 指定时间置换桌面背景   6.14 判断发送短信后的状态   6.15 后台服务送出广播信息   6.16 开机程序设计   6.17 双向短信常驻服务   6.18 测量电池温度   6.19 电池电量显示Widget小工具   6.20 取出通讯录数据及多组电话号码   6.21 电子Sensor精确罗盘   6.22 屏幕手写事件判断   6.23 画一颗心,打电话给HONEY   6.24 开启内置闹钟与已安装的应用程序设置   6.25 在SDK开发环境中访问JNI接口   第7章 娱乐多媒体   7.1 访问Drawable资源的宽和高   7.2 绘制几何图形   7.3 手机屏幕保护程序   7.4 用手指移动画面里的照片   7.5 加载存储卡的Gallery相簿   7.6 取得手机内置媒体中的图片文件   7.7 相片导航向导与设置背景桌面   7.8 调整音量大小   7.9 播放mp3资源文件   7.10 播放存储卡里的mp3音乐   7.11 自制录音/播放录音程序   7.12 通过收到短信开始秘密录音   7.13 内置影片播放器载入3gp电影   7.14 自制3gp影片播放器   7.15 相机预览及拍照临时文件   7.16 拍照瞬间启动相机自动对焦   7.17 制作开场动画   7.18 我的手机会说话   7.19 手势触控屏幕控制   7.20 多点触控屏幕事件捕捉   7.21 电流急急棒   7.22 自定义动画按钮事件   7.23 设置录音取样频率与显示录音时间   7.24 EXIF照片信息编辑及读取   7.25 声音音效均衡器、重低音与音场控制   7.26 在自定义的SurfaceView上绘制动画   第8章 当Android与Internet接轨   8.1 HTTP GET/POST传递参数   8.2 在程序里浏览网页   8.3 嵌入HTML标记的程序   8.4 设计前往打开网页功能   8.5 将网络图像网址放入Gallery中显示   8.6 即时访问网络图片文件展示   8.7 手机气象局,实时卫星云图   8.8 通过网络播放mp3   8.9 设置远程下载音乐为手机铃声   8.10 远程下载桌面背景图案   8.11 将手机文件上传至网站服务器   8.12 移动博客发布器   8.13 移动RSS阅读器   8.14 远程下载安装Android程序   8.15 手机下载看3gp影片   8.16 访问网站Login API   8.17 地震速报   8.18 通过Web API动态更改手机Spinner控件   8.19 网络语音搜索   8.20 网络下载过程中显示加载中   8.21 快照WebView加载的网页画面   8.22 网页的放大与缩小   8.23 WebView网页载入中、载入完成样版   8.24 通过内嵌Flash Player播放FLV电影   8.25 WebView网站Session Cookie判断与访问   8.26 文件下载管理器   8.27 手机Socket联机拨号服务器   第9章 Google服务与Android完美整合   9.1 Google账号验证Token   9.2 Google搜索   9.3 前端产生QR Code二维条形码   9.4 以经纬度查找目的地位置   9.5 GPS Google地图   9.6 移动版Google Map   9.7 规划导航路径   9.8 移动设备上的Picasa相册   9.9 随身翻译机   9.10 通过YouTube ID调用YouTube播放影片   9.11 Google Analytics分析手机用户行为   第10章 创意Android程序设计   10.1 手机手电筒   10.2 GPS轨迹记录器   10.3 女性贴身看护   10.4 手机QR Code二维条形码生成器   10.5 Android QR Code二维条形码扫描仪   10.6 上班族今天中午要吃什么   10.7 掷杯筊   10.8 电蚊香   10.9 转转轮盘——Lucky!   10.10 任务管理器   10.11 免费的云端发音字典   10.12 动起来!手机桌面上会动的动态桌布   10.13 正妹墙相簿浏览器   10.14 YouTube影片FLV文件下载器   第11章 HTML5 Mobile应用程序开发   11.1 HTML5 INPUT输入框控制手机输入键盘   11.2 HTML5利用CSS3排版的墙贴相册   11.3 HTML5网页离线数据库   11.4 可拨打电话的HTML连接   11.5 HTML5取回所在经纬度坐标并反查地址   附录A 如何发布程序到Android Market   A.1 支付Google Android Market注册费   A.2 生成签署凭证.keystore金钥档案   A.3 上传*.apk程序到Android Market上   附录B 升级项目至新版SDK 与Honeycomb平板程序部署   B.1 Android SDK版本与项目最低运行版本设置   B.2 升级程序至Honeycomb平板运行
基本信息 Google Android SDK开发范例大全(第3版) 作者:王世江(改编), 佘志龙(作者), 陈昱勋(作者), 郑名杰(作者), 等(作者) 出版社: 人民邮电出版社; 第3版 (2011年11月1日) 丛书名: 移动开发系列丛书 平装: 818页 正文语种: 简体中文 开本: 16 ISBN: 9787115264305 条形码: 9787115264305 商品尺寸: 26 x 18.4 x 3.8 cm 商品重量: 1.3 Kg 编辑本段 内容简介 《Google Android SDK开发范例大全(第3版)》在上一版的基础上,以Android手机应用程序开发(采用Android SDK 2.3.3)为主题,超过200多个范例全面且深度地整合了手机、网络及服务等多个开发领域,为读者提高程序设计能力提供了很大的帮助。 全书共分11章,主要以范例集的方式来讲述Android的知识点,详细介绍了开发Android的人机交互界面、Android常用的开发控件、Android手机收发短信等通信服务、开发Android手机的自动服务功能和娱乐多媒体功能以及整合Android与Google强大的网络服务等内容。随书光盘中包括了所有范例的程序代码。 《Google Android SDK开发范例大全(第3版)》继承前两版由浅入深的方式,范例总数由原先的160多个增加到了200多个,在用户交互界面、手机控件、交互式通信服务、手机自助服务、娱乐多媒体等方面均增加了相应的范例来介绍新的开发技术,特别是新增加了第11章来专门介绍HTML5技术在Android移动设备里的应用,相信当下两个热门技术的交汇会碰撞出不一样的火花。 《Google Android SDK开发范例大全(第3版)》内容由Android的基础知识到实际开发应用,结构清晰、语言简洁,非常适合Android的初学者和Android的进阶程序开发者阅读参考。 编辑本段 编辑推荐 《Google Android SDK开发范例大全(第3版)》:全新2.3以上版本精彩范例。新增HTML5手机应用程序范例。影音功能大突破,领先业界的影音播放功能详解。易于阅读的架构设计,边看边学,每个范例均搭配步骤及完成画面。每个范例后面均有扩展学习,在学习范例应用的同时延伸思考。汲取专家经验,指引入门捷径。 移动网络设备(MID,Mobile Internet Device)的发展趋势锐不可当,其中以智能手机最受瞩目。 《Google Android SDK开发范例大全(第3版)》采用范例集的形式,由浅入深地带领Google Android SDK初学者,以及具备Java基础的程序设计人员逐步掌握开发MID的能力。同时,书中200多个范例均可作为开发样板,以此抛砖引玉,进而拓展程序设计人员开发MID的无限可能。精彩范例,原创展现。 更炫的移动设备人机界面配置:豪华Widget、Home Screen App Widgets、隐藏式抽屉-Sliding Drawer等闪亮登场! 完整的手机数据存取功能:铃声模式设置、震动控制、WiFi服务、屏幕旋转、电池计量、温度测量、电信网络信息、SIM卡信息、拨打电话、短信解析、通讯录联系人、电子罗盘、屏幕手写等手机控制功能。 系统服务及研发的整合:网络搜索、联系人、音乐、应用程序、定制手机文件管理、记忆卡I/O存取、双向短信、闹钟服务、开机程序、来电通信互动、拜年短信、信息提醒、电池电量显示、进度显示、取得应用程序信息等。 超酷的娱乐多媒体设计:触控移动事件、建立手势、手势判断控制、屏幕保护程序、启动动画、mp3播放器、3gp影片播放、相机预览拍照、自动对焦、调整音量、信息指令遥控手机、录音控制、自定义动画按钮等 Web Service存取服务:内嵌网页浏览器、Ajax网页特效、手机气象局、网络播放mp3、网络安装apk程序、远程下载手机铃声、XML-RPC移动博客发布器、手机RSS阅读器、地震速报、网页快照等。 完备的Google网络服务:Google语音搜寻、Google远程账号登录、Google Search API、Google Chart API、Google Picasa手机相册、Google Translate API整合等。 Google Map应用:GPS定位、规划导航路径、GPS Google地图、地址反查地理坐标等卫星全球定位实例。 创意程序设计:即时动态桌面、电蚊香、转转轮盘、任务管理器、中英发音字典、手机手电筒、GPS轨迹记录器、女性贴身计时、QR Code二维条码生成器、手机OR Code扫描仪、热量骰子、掷杯筊、正妹墙相簿浏览器、You Tube影片FLV文件下载器等。 HTML5结合Mobile:控制手机
|--Activity不允许横竖屏切换 |--Activity常用小技巧 |--Activity按返回直接回到桌面 |--aidl之结合反射获取应用缓存大小等空间占用 |--aidl调用系统service未公开的方法挂电话 |--aidl调用系统未公开的方法代码示例2 |--android dp和px之间转换 |--android INSTALL_PARSE_FAILED_MANIFEST_MALFORMED |--android root下禁用组件 |--android 判断网络状态 |--android 对话框样式 |--android 开机启动 |--android 挪动dialog的位置 |--android 控制对话框位置 |--android 根据uri获取路径 |--android 模拟器错误 |--android 横竖屏切换 |--android 获取mac地址 |--android 获取sd卡状态 |--android 设置apn |--android 调节屏幕亮度 |--android 资源uri |--android 还原短信 |--android 重启 |--android中anim文件特效 |--app信息menifest获取(如版本号) |--AsyncQueryHandler之异步查询Cursor处理 |--AutoCompleteTextView自动提示的用法 |--BitMap、Drawable、inputStream及byte[] 互转 |--ContentProvider内容提供者定义 |--DatePicker日期控件 |--desktop |--Dialog之位置的挪动与控制 |--Dialog实现无标提栏及自定义风格 |--Dialog风格Activity的作法 |--ExpandableListView(下拉伸缩ListView) |--GridView表格布局的用法 |--httpclient超时 |--info体系 |--Intent启动应用apk安装 |--Intent常用功能 |--IO将输入流转成字节 |--Json读js资源文件 |--layout布局样式之style配置 |--listview 页面 图片加文字 |--ListView之CursorAdapter异步查询框架之短信 |--ListView之动态添加子view |--ListView优化之分页加载 |--ListView优化之动态加载 |--ListView优化之控制getView实现复杂显示 |--ListView优化之标准写法 |--listview老虎机 界面设计 水果机 |--listview页面跳转 数据库交互 事务 dao biz 层 |--Log的收集 |--Manager下的info |--Manager之ActivityManager进程管理 |--Manager之LocationManager |--Manager之PackageManager |--Menu之不同模式下显示不同菜单 |--openGL-ES上绘制文字 |--openGL-ES纹理贴图 |--openGL-ES获取帧率 |--openGL-ES雾化 |--PopupWindow的使用 |--PopupWindow的返回健关闭 |--RadioGroup的用法(里面的成员可以是任何view) |--SD卡之计算剩余空间 |--Spinner下拉菜单组件 |--SplashActivity |--StringUtils工具类的常用方法 |--TabHost一个界面显示多Activity |--TextView单行跑马灯效果 |--TextView虚拟获得焦点 |--uploadServlet |--uri之表示资源resource |--ViewPage的使用 |--view中的tag用法之存储对象 |--view常用属性 |--xml常用属性 |--xml文件的pull解析与序列化写入 |--xml的封装序列化 |--任务循环之只在Activity显示时执行 |--修改文件的最后修改时间 |--偏好设置(回显) |--内存优化之各种方法 |--内容提供者之短信的序列化对象读写 |--内容提供者之短信的获取与写入 |--内容提供者之联系人读写与批量操作 |--内容提供者之获取通话记录 |--内容提供者的定义 |--写入联系人信息 |--利用FinalHttp实现多线程断点续传 |--加密之MD5 |--动画Animation详解 |--动画之view左右抖动 |--动画之移动动画 |--动画之组合动画 |--动画之缩放动画ScaleAnimation |--反序列化对象 |--发送短信 读天气 调音量 |--回调函数的定义 |--图片之BitMap、Drawable、inputStream及byte[] 互转 |--图片之保存图片至SD卡 |--图片之删除40%最近没有被使用的 |--图片之的本地缓存至SD卡 |--图片之网络异步下载图片 |--图片之获取SD卡所有及边界可调及压缩和软引用和内存回收 |--图片的LRU算法内存保存和读取 |--图片的缩放处理(防内存溢出) |--多媒体应用设计图 |--多线程下载 |--多线程下载及断点续传 |--多线程之AsyncTask的用法 |--多线程之线程池ExecutorService |--字体为粗体 |--安卓下的多线程断点上传 |--对话框与进度条结合用法 |--屏幕之Activity全屏 |--屏幕之横竖屏切换 |--屏幕之调节屏幕亮度 |--屏幕相关之Display类获取屏幕尺寸和分辨率 |--屏幕适配之ScrollView |--屏幕适配之像素dp和px之间转换 |--工具类之Log的封装类 |--工具类之不同log打印的封装 |--工具类之开启新的Activity |--布局加载器的获取 |--广播接收者之开机启动 |--广播接收者之获取管理员权限 |--广播接收者代码注册与卸载 |--广播接收者常用广播的获取 |--应用之分享(隐式意图) |--应用之卸载(隐式意图) |--应用之安装(隐式意图) |--应用之完美退出 |--应用之获取名称和图标 |--应用之获得占用内存大小 |--应用之通过包名开启一个应用 |--应用之隐式意图开启设置界面 |--应用启动之检查版本更新及初始化 |--延时任务的工具类 |--异常之UncaughtExceptionHandler全局捕获处理 |--异步任务AsyncTask的用法 |--异步任务的自定义 |--快捷方式增删查 |--手势识别器GestureDetector的用法 |--拍照之调用系统相机并显示及保存 |--拨打电话 |--按健之长按menu事件屏蔽 |--按健监听按返回健回桌面 |--搜索之调用系统Searchable的用法 |--数据库CURD通过execSQL与rawQuery |--数据库SQLiteOpenHelper标准写法 |--数据库复杂多表查询 |--数据库查询之归属地 |--数据库直接CURD |--数据提交无需权限 |--文件之从服务器下载 |--文件之拷贝文件至某个目录 |--文件之指定编码读写文件 |--文件之释放Assets下的文件到应用的File目录 |--文件之随机存储RandomAccessFile |--文件使用时间排序 |--文件复制粘贴 |--文件路径之通过uri获取 |--时间java常用应用 |--时间之handle记时器 |--时间之time的用法得到特定时间的long值 |--时间之之定时任务TimerTask |--时间之倒计时CountDownTimer |--时间之当前时间动态显示 |--时间之自动任务ScheduledExecutorService |--时间之记时器 |--时间日期格式化 |--服务之判断是否处于运行状态 |--服务之定义录音机 |--服务之应用内绑定服务调用方法 |--服务之电话录音 |--服务之看门狗代码示例 |--格式化之DecimalFormat数字格式化 |--桌面快捷方式的添加代码示例 |--桌面控件widget的创建方法 |--模拟发短信 指定号码 短信窃听提示 |--消息机制 mesage looper |--滑动之左右滑动的两种定义 |--电话簿读取联系人信息 |--监听 |--监听之CheckBox是否选中监听 |--监听之EditText内容变化监听 |--监听之GridView条目点击监听 |--监听之ListView条目点击事件监听 |--监听之ListView滑动监听 |--监听之单击监听的两种定义 |--监听之双击监听 |--监听之电话状态监听 |--监听之触摸监听 |--短信之根据id删除及查询短信 |--短信发送小demo |--短信的截取 |--系统之SD卡清理 |--系统之获取所有开机启动应用 |--系统之重启实现 |--系统信息之获取SD卡内存信息 |--系统信息之获取动态内存RAM信息 |--系统信息之获取可用内存 |--系统信息之获得mac地址 |--系统信息之获得手机sim卡序列号 |--缓存优化之几种方案lastModified |--缓存优化之本地缓存优化(超过规定值或SD卡容量不够时) |--网络post提交查询请求 |--网络之HttpClient的get和post用法 |--网络之判断网络状态是否可用 |--网络之设置apn |--网络图片查看器 |--网络图片的下载与缓存 |--网络文件的下载与关联进度条 |--联系人之各种查找 |--联系人读写与批量操作 |--联系人读取 |--自定义shape形状颜色渐变资源 |--自定义Toast |--自定义view的属性 |--自定义下拉刷新ListView |--自定义动画资源 |--自定义常用小控件 |--自定义控件之小技巧 |--自定义控件风格和全局背景 |--自定义组合控件 |--自定义配置文件资源 |--自定义颜色状态选择资源 |--自定义颜色资源 |--获取网页的源码 |--读取外部资源的文件3种方式 |--读取手机内的短信 |--通信之Application实现应用全局通信 |--重启adb |--隐式转换 页面 |--震动效果的实现
本书以Android应用程序的开发为主题,并结合真实的案例向读者详细介绍了Android的基本组件的使用及应用程序开发的整个流程。本书的讲述由浅入深,实例全面并典型,几乎囊括了所有和Android应用相关的项目。全书分为18章,分别讲解了UI布局实例集锦、控件实例集锦、自动化服务实例集锦、数据存储实例集锦、电话和短信实例集锦、图形图像实例集锦、和网络有关的实例集锦、多媒体实例集锦、Google地图实例集锦、GoogleAPI实例集锦、平板应用实例集锦、游戏应用与程序优化。并且在本书最后,通过4个大型综合实例,分别介绍了开发手机地图系统、音乐播放器系统、NBA激情投篮游戏、综合邮件系统的基本过程。 目录: 第1章 UI布局开发实例集锦 1 实例001: 使用线性布局(LinearLayout) 来布局屏幕 1 实例002: 使用相对布局(RelativeLayout)来布局屏幕 3 实例003: 使用表格布局(TableLayout) 来布局屏幕 5 实例004: 使用绝对布局(AbsoluteLayout) 来布局屏幕 6 实例005: 使用标签布局(TabLayout)来 布局屏幕 8 实例006: 使用层布局(FrameLayout) 10 实例007: 创建一个桌面组件Widget 11 实例008: 在屏幕中实现一个按钮效果 12 实例009: 在屏幕中显示文字 13 实例010: 在屏幕中显示编辑框 17 实例011: 在屏幕中显示复选框 18 实例012: 在屏幕中显示单选框 21 实例013: 在屏幕中显示下拉列表框 22 实例014: 在屏幕中实现自动输入文本 效果 26 实例015: 使用日期选择器控件DatePicker 28 实例016: 自动选择一个输入时间 30 实例017: 实现屏幕自动滚动 32 实例018: 实现一个进度条效果 32 实例019: 开发一个评分程序 35 实例020: 在屏幕中显示一幅指定的图片 36 实例021: 设置一幅图片作为按钮来使用 38 实例022: 实现QQ空间中的显示照片 效果 40 第2章 控件开发实例集锦 44 实例023: 显示在文本框中输入的信息 44 实例024: 使用RadioGroup控件实现选 项选择功能 46 实例025: 使用CheckBox控件实现同意 条款效果 48 实例026: 使用Spinner控件实现选项选择 51 实例027: 使用Gallery控件实现个人相 簿功能 55 实例028: 开发一个文件搜索程序 58 实例029: 单击按钮后实现按钮置换 60 实例030: 模拟实现一个时钟界面效果 62 实例031: 联合使用DatePicker和TimePicker 来选择日期和时间 65 实例032:动态分隔手机屏幕 68 实例033:使用ListActivity实现动态菜单 列表 71 实例034:加载手机磁盘中的文件 73 实例035:实现抽屉样式效果 76 实例036:在屏幕中动态显示多种对话框 82 实例037:手机秘书--重要事情提醒 88 实例038:动态添加或删除菜单 96 实例039: 自定义Android控件实现单选 按钮 100 实例040: 使用自定义控件在屏幕中绘 制一条虚线 104 实例041: 在屏幕中实现手风琴效果 106 第3章 自动化服务实例集锦 109 实例042: 自动获取手机屏幕的分辨率 109 实例043: 自动获取手机电池的剩余电量 112 实例044: 来电时自动发送信息提醒 115 实例045: 获取手机存储卡的容量 119 实例046: 操作存储卡和内存卡中的数据 122 实例047: 设置闹钟 129 实例048: 实现黑名单来电自动静音处理 135 实例049: 设置一个自动开机界面 138 实例050: 更换手机屏幕背景图片系统 140 实例051: 设置自动更换手机桌面背景 144 实例052: 自动控制后台系统服务 154 实例053: 在屏幕中拖动一个按钮 157 第4章 数据存储实例集锦 163 实例054: 在屏幕中显示SharedPreferences 中存储的信息 163 实例055: 演示数据添加、删除等操作 165 实例056: 编写一个手机日记本程序 170 实例057: 使用ContentProvider开发一个 手机日记本 177 实例058: 使用文件保存数据 188 实例059: 将网上的图片保存到SD卡并在 手机中显示出来 190 实例060: 保存联系人信息 194 第5章 电话和短信实例集锦 197 实例061: 编写一个拨号程序 197 实例062: 发送一条短信 200 实例063: 单击按钮实现拨号功能 203 实例064: 一个通用发短信程序 206 实例065: 收到短信后用E-mail邮件进行 通知 210 实例066: 实现触屏拨号功能 214 实例067: 一个短信群发程序 215 实例068: 来电后自动发送邮件通知 219 实例069: 监听手机拨接状态 220 实例070: 检查短信是否发送成功 223 第6章 图形图像实例集锦 229 实例071: 在屏幕中绘制一个矩形 229 实例072: 在屏幕中绘制一个画布 232 实例073: 实现水纹的透明效果 235 实例074: 渲染几何图形 239 实例075: 用图片为背景实现动画效果 242 实例076: 在手机屏幕中实现Frame动画 效果 244 实例077: 对图片进行缩放处理 246 实例078: 旋转屏幕中的图片 250 实例079: 实现旗帜飞扬的效果 253 实例080: 模拟构建一个3D场景效果 258 实例081: 模拟实现粒子系统效果 261 实例082: 在Canvas中写文字 265 实例083: 移动屏幕中的图片 272 实例084:在屏幕中绘制一个三维圆柱体 276 实例085: 获取并显示图片的宽和高 285 实例086: 编写一个手机屏保程序 287 实例087: 以触摸方式移动图片 295 第7章 和网络有关的实例集锦 299 实例088: 传递HTTP参数 299 实例089: 在屏幕中使用HTML程序 303 实例090: 在手机中浏览网页 304 实例091: 使用内置浏览器打开网页 305 实例092: 显示QQ空间中的照片 307 实例093: 通过RSS系统在线浏览新闻 309 实例094: 下载网络图片作为手机背景 320 实例095: 将文件上传至服务器 323 实例096: 开发一个移动博客发布器 326 实例097: 远程下载并安装一个软件 331 实例098: 控制蓝牙系统 336 第8章 多媒体实例集锦 346 实例099: 播放一个指定的MP3文件 346 实例100: 调节手机音量的大小 350 实例101: 实现相机预览和拍照功能 353 实例102: 在手机中播放影片 360 实例103: 手机录音系统 363 实例104: 设置手机中的铃声 368 实例105: 在线播放网络中的MP3 371 实例106: 在线下载音乐作为手机铃声 379 实例107: 播放GIF格式的动画 385 实例108: 在手机中播放MP4视频 391 实例109: 在线观看3GP视频 394 第9章 Google地图实例集锦 403 实例110: 定位当前位置的坐标 403 实例111: 在手机中使用Google地图 406 实例112: 在地图中定位输入的坐标 413 实例113: 在地图中快速查询某个位置 416 实例114: 随着手机的移动自动更新位置 418 实例115: 在手机地图中描绘线路并计算 线路距离 423 实例116: 在Google地图中显示指定的 位置 430 实例117: 在手机地图中查询一个地址 432 实例118: 在手机中实现地址查询 434 实例119: 开发一个路径导航系统 438 第10章 Google API实例集锦 446 实例120: 模拟验证官方账号 446 实例121: 在手机中开发一个Google搜索 程序 453 实例122: 在手机中编写一个翻译软件 458 实例123: 生成一个二维码 460 实例124: 使用Google Chart API生成二 维码 463 第11章 平板应用 469 实例125: 开发一个音乐播放器 469 实例126: 开发一个在线天气播报系统 475 实例127: 开发一个网页浏览程序 485 实例128: 使用文件来保存音乐状态 491 实例129: 在屏幕中显示不同的进度条 效果 494 第12章 游戏应用 498 实例130: 一个简单的贪吃蛇游戏 498 实例131: 开发一个魔塔游戏 504 实例132: 疯狂足球游戏 524 第13章 Android程序优化 547 实例133: 测试计算机的性能 547 实例134: 测试内存性能 550 实例135: 优化Android模拟器 553 实例136: 使用merge标签优化UI界面 556 实例137: 优化Android Layout 559 实例138: 优化Bitmap图片 560 第14章 综合实例--手机地图系统 563 实例139: 使用Google地图开发一个综合 地图系统 563 14.1 项目分析 563 14.1.1 规划UI界面 563 14.1.2 数据存储设计 564 14.2 具体实现 565 14.2.1 新建工程 565 14.2.2 主界面 565 14.2.3 新建界面 567 14.2.4 设置界面 570 14.2.5 帮助界面 574 14.2.6 地图界面 576 14.2.7 数据存取 587 14.2.8 实现Service服务 592 14.3 发布自己的作品来赢利 594 14.3.1 申请成为会员 594 14.3.2 生成签名文件 597 14.3.3 使用签名文件 602 14.3.4 发布 604 第15章 综合实例--音乐播放器系统 605 实例140:开发一个音乐播放器 605 15.1 项目介绍 605 15.1.1 项目背景介绍 605 15.1.2 项目目的 606 15.1.3 对读者的意义 606 15.2 需求分析 606 15.2.1 构成模块 606 15.2.2 功能结构图 609 15.2.3 系统功能说明 610 15.2.4 总体目标 610 15.3 设计数据库 611 15.3.1 字段设计 611 15.3.2 数据库连接 611 15.3.3 创建数据库 612 15.3.4 操作数据库 613 15.3.5 数据显示 614 15.4 具体编码 615 15.4.1 服务信息主界面 615 15.4.2 播放器主界面 616 15.4.3 播放列表功能 628 15.4.4 菜单功能模块 631 15.4.5 播放设置界面 634 15.4.6 设置显示歌词 638 15.4.7 文件浏览器模块 639 第16章 体育类游戏--NBA激情投篮 644 实例141:NBA激情投篮 644 16.1 项目介绍 644 16.1.1 意义和技术分析 644 16.1.2 策划游戏 645 16.1.3 准备工作 645 16.2 项目架构 646 16.2.1 总体架构 646 16.2.2 规划类 646 16.3 具体编码 648 16.3.1 编写主类LanqiuActivity 648 16.3.2 编写常量类 652 16.3.3 设计游戏试玩界面 658 16.3.4 绘制游戏场景 663 第17章 综合邮件系统 672 实例142:开发一个综合邮件系统 672 17.1 项目介绍 672 17.1.1 项目背景介绍 672 17.1.2 项目目的 672 17.2 系统需求分析 673 17.2.1 构成模块 673 17.2.2 系统流程 675 17.2.3 功能结构图 676 17.2.4 系统功能说明 677 17.2.5 系统需求 677 17.3 数据存储设计 677 17.3.1 用户信息类 678 17.3.2 SharedPreferences 682 17.4 具体编码 684 17.4.1 欢迎界面 684 17.4.2 系统主界面 687 17.4.3 邮箱类型设置 694 17.4.4 邮箱收取设置 697 17.4.5 邮箱发送设置 703 17.4.6 邮箱用户检查 708 17.4.7 设置用户别名 713 17.4.8 用户邮件编辑 716 17.5 总结 723
Android 开机动画的加载流程如下: 1. 开机自检:开机后,首先进行硬件自检。如果自检通过,将会启动 bootloader。 2. Bootloader:Bootloader 负责初始化硬件设备,加载 kernel,并且将 kernel 加载到内存中。 3. Kernel:Kernel 是 Android 操作系统的核心,负责初始化硬件设备,启动驱动程序,加载文件系统等。 4. Init 进程:Init 进程是 Android 系统中的第一个用户进程,它负责启动系统中所有的服务,并且加载所有的配置文件和属性。 5. SurfaceFlingerSurfaceFlingerAndroid 系统中用于显示图形的核心服务,它在启动后会创建一个显示屏幕,显示屏幕上的内容就是从应用程序中传递过来的。 6. Zygote 进程:Zygote 进程是 Android 系统中的一个特殊进程,它负责预加载常用的类和资源,以提高应用程序的启动速度。当应用程序需要启动时,Zygote 进程会 fork 出一个新的进程,该进程会继承 Zygote 进程的状态,从而加速应用程序的启动。 7. 开机动画:在上述进程启动后,系统会加载开机动画开机动画通常是一个视频或者一组图片,这些图片或视频会被 SurfaceFlinger 显示在屏幕上。 8. 启动屏幕:当开机动画结束后,系统会显示一个启动屏幕,表示 Android 系统已经启动完毕。此时,用户就可以开始使用 Android 设备了。 总的来说,Android 开机动画加载流程比较复杂,其中涉及到多个进程和服务,需要相互配合才能完成整个过程。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

八归少年

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值