Android源码级别开发

Android源码级别开发

1、课程简介(3

1、系统开发概述

2、系统编译简介

3、源码查看工具

4、系统启动流程

5、Handler消息机制

6、AsyncTask原理

系统架构的回顾(13

系统分层

Linux内核层: 包含Linux内核和驱动模块(比如USB, Camera, 蓝牙等)

Libraries层: 这一层提供动态库(也叫共享库), android运行时库, Dalvik虚拟机等. 编程语言主要为CC++, 所以可以简单的看成Native

FrameWork层: 这一层大部分用java语言编写,它是android平台上Java世界的基石

Applications层: 应用层, 主要存放各种各样的应用程序



详细说明:

Linux 内核层

Android基于那个版本研发的:2.6.7

display driver:显卡驱动

camera draver:相机驱动

bluetooth driver:蓝牙驱动

flash memory driver:闪存驱动

Binder(IPC) Driver:Android系统进程间通信.

USB driver:usb驱动

keypad driver:键盘驱动

wifi driver:wifi驱动

audio driver :音频驱动

power Management:电源管理

上面的这些驱动都是用c语言写的

 

知识拓展:

NFC是Near Field Communication缩写,即近距离无线通讯技术。

库层(libraries图书馆)

surface Manager:显示管理器

Media Framework:多媒体框架

SQLite :所有应用程序都可以使用的强大而轻量级的关系数据库引擎

OpenGl | ES :渲染三维图形引擎

FreeType:是一个完全免费(开源)的、高质量的且可移植的字体引擎

Webkit:是一个开源的浏览器引擎

SGL:基本的2D图形引擎

SSL:(Secure Sockets Layer 安全套接层),及其继任者传输层安全(Transport Layer SecurityTLS

是为网络通信提供安全及数据完整性的一种安全协议TLSSSL在传输层对网络连接进行加密。

libc :基本的C语言函数库,包含了C语言最基本的库函数


Android 运行时

Cor Libraries :核心库;核心函数库;核心函式库

dalvik virtual machine:Dalvik虚拟机

 

应用框架层

Activity Manager :这个类主要用来管理所有设备上的Activities

Window Manger:整个Android的窗口机制是基于一个叫做 WindowManager,其实我们的Activity或者Diolog底层的实现也是通过WindowManager,这个 WindowManager是全局的,整个系统就是这个唯一的东东。它是显示View的最底层了。

Content Providers :Content providers是连接跨进程数据的标准接口。

View System:视图显示系统

Notification Manager :通知管理

Package Manager : 包管理器

Telephony Manager :电话管理器

Resource Manager :资源管理器

Location Manager: 位置管理,用于定位;

XMPP service::XMPP是一种基于标准通用标记语言的子集XML的协议,它继承了在XML环境中灵活的发展性;

 

应用层:

桌面,联系人,电话,浏览器,第三方软件等等

 

补充:

Java世界经由JIN层通过IPC方式与Native世界进行交换。IPCInter-Process Communication,进程间通信) ,常用的IPC方法Binder,除此之外还可以使用Socket

 

现在很多设备开始使用Android系统:例如车载系统;

物联网

 

 

系统编译简介

 

1、系统环境(3

操作系统选择:

Android 系统的编译环境目前只支持 Linux 以及 Mac OS 两种操作系统。

注意

如果采用虚拟机安装时需要考虑占用磁盘空间(源码+编译)

如果是2.3 源码需要5G,编译需要10G

google推荐使用64位的操作系统

现在一般是用ubuntu 14.04,我用的是11.10

 

经验分享:

其中一种是在window 系统上安装虚拟机 ,虚拟机上安装Linux系统;

4.4源码,给盘符90G,尽量多给点;

2.3  源码3.7G,不包含内核代码;如果下完估计要5G

 

 

 

源码下载(22

下载源码流程相对麻烦点, 但官方文档中有对源码下载进行说明.

官方文档地址: http://source.android.com/source/downloading.html

 

以下是详细步骤:

 

1.下载Git(版本控制工具).

2.安装curl(上传和下载数据的工具).

3.安装repo(一个基于git的版本库管理工具, 这里用于自动批量下载android整个项目).

 

4.创建文件夹, 用于存放下载的Android源码.

 

5.初始化库.

 

开始同步下载.

 

下载源码具体命名和细节:

Android源码下载支持的系统目前只有Ubuntu和Mac OS两种操作系统, 本次以Ubuntu系统为例.

官方网站: http://source.android.com/source/downloading.html

下载Git(版本控制工具). 调出命令行: ctrl + alt + T

sudo apt-get install git

 

安装curl(上传和下载数据的工具).

sudo apt-get install curl

 

安装repo(一个基于git的版本库管理工具, 这里用于自动批量下载android整个项目.).

// 创建目录

mkdir bin

 

// 下载repo脚本到本地bin文件夹下

curl http://android.git.kernel.org/repo >~/bin/repo

// 如果上面下载失败, 采用下面这种方式

curl "http://php.webtutor.pl/en/wp-content/uploads/2011/09/repo" >~/bin/repo

 

// 给所有用户追加可执行的权限

chmod a+x ~/bin/repo

 

// 临时把repo添加到环境变量中, 方便后面执行.

// 注意: 每次重启ubuntu之后此环境变量失效, 重新配置就可以了.

export PATH=~/bin:$PATH

 

创建文件夹, 用于存放下载的Android源码.

// 创建目录

mkdir android_source

 

// 修改权限

chmod 777 android_source

 

cd android_source

 

初始化库.

// 需要先配置git的用户信息

git config --global user.email "trygf521@126.com"

git config --global user.name "yangguangfu"

//b-bracher分支,这里是下载这个版本的目录结构下下来

repo init -u https://android.googlesource.com/platform/manifest -b android-2.3_r1

 

// 如果上面初始化失败, 国内的连接下载代码  gingerbread(姜饼)

repo init -u git://codeaurora.org/platform/manifest.git -b gingerbread

//

repo init -u git://android.git.kernel.org/platform/manifest.git -b  gingerbread

 

出现以下信息成功初始化

repo initialized in /home/yangguangfu/android_source

 

开始同步下载.

repo sync

 

注意: 下载过程中, 因为网络问题, 可能会中断下载. 当中断下载时, 继续使用repo sync命令继续下载,网络比较好的情况下要下载8个小时左右,主要原因是有中断情况。

 

正在下载中

 

 

下载完成:

 

 

 

下载过程中常见问题:

apt-get是一条linux命令,适用于deb包管理式的操作系统,主要用于自动从互联网的软件仓库中搜索、安装、升级、卸载软件或操作系统。是debianubuntu发行版的包管理工具,与红帽中的yum工具非常类似。

apt-get install xxxx 安装
apt-get remove xxxx 卸载但不删除配置
apt-get purge xxxx 卸载并且删除相关配置

 

curl是利用URL语法在命令行方式下工作的文件传输工具。

 

下载时可能会出现失败的情况:需要多试几次,或者

apt-get update

apt-get install git-core curl --fix-missing

 

10.10配置软件源:

systemàadministrationàsynaptic package manageràsettingàrepositoriesàsoftware sources

Ubuntu 的软件源列表存放在 /etc/apt/sources.list 当中。

 

google的http://source.android.com/source/downloading.html,为了防止连接数过多,每个ip都需要认证。。。

第一步:从这里 the password generatorhttps://android.googlesource.com/new-password  获取用户名和密码

第二步:将上面的页面上以machine开头的两行复制到  ~/.netrc文件中

第三步:repo init -u https://android.googlesource.com/a/platform/manifest  多了个“/a”

然后就可以repo sync

 

一点小提示:有时候googleandroid服务器老是断,总不能让我们守在电脑旁边一直手工重新./repo sync吧,这可是需要N个小时才能下载完的啊。


我们就写个小脚本让电脑自动reposync,直到下载成功为止:

#!/bin/shcount=0

ret=1

while [ $ret -ne 0 ]

do

repo syncret=$?

count=$(( $count + 1))

echo "try $count, ret:$ret"

done

echo "try $count, ret:$ret"

把上面的内容复制到一个文件里tryrepo.sh

然后修改tryrepo.sh的属性,开始自动工作吧。第二点早上应该就大功告成了

chmod a+x tryrepo.sh./tryrepo.sh

 

编译源码(20

 

编译环境搭建--安装软件

编译的目的-修改了代码、风格、或者功能。小米手机、锤子手机等待。

JDK安装(不同的源码编译时需要的JDK版本不同)

android2.2需要JDK5

android2.3需要JDK6,如果你安装的是JDK5直接报错。

安装编译时依赖的软件(: zip, gcc, g++, libesd0-dev, lib32z1-dev…等等)

编译:make -j4 (-j4为可选参数, j4代表4核同时编译)

2、在编译源码之前需要做一些准备操作, 详细步骤如下:

 

1. 安装JDK, google官方要求编译2.3源码需要JDK1.6.

1). 下载JDK1.6, 下载地址:

http://download.oracle.com/otn/java/jdk/6u45-b06/jdk-6u45-linux-x64.bin

2). 创建目录.

sudo mkdir /usr/java

 

3). 把下载好的jdk-6u45-linux-x64.bin拷贝到上面创建的目录下.

sudo cp /home/liyindong/jdk-6u45-linux-x64.bin /usr/java

 

4). 添加可执行权限.

sudo chmod 755 /usr/java/jdk-6u45-linux-x64.bin

 

5). 解压.

cd /usr/java

sudo ./jdk-6u45-linux-x64.bin

 

6). 配置环境变量.这块需要路径要对

export JAVA_HOME=/usr/java/jdk1.6.0_45

export PATH=$PATH:$JAVA_HOME/bin

export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar

 

7). 验证是否成功.

yangguangfu@yangguangfu-VirtualBox:~$ java -version

java version "1.6.0_45"

Java(TM) SE Runtime Environment (build 1.6.0_45-b06)

Java HotSpot(TM) 64-Bit Server VM (build 20.45-b01, mixed mode)

 

2. 安装其他编译时依赖的软件.

注意: ubuntu自带的源中速度比较慢, 有些软件找不到, 所以需要修改为国内的源, 修改源步骤如下:

1). 备份ubuntu自带的源.

sudo cp /etc/apt/sources.list /etc/apt/sources.list.old

 

2). 修改源文件.

sudo gedit /etc/apt/sources.list

 

3). 这时会弹出一个文本编辑框, 先删除所有内容, 然后把以下内容拷贝进去, 并保存.

deb http://mirrors.163.com/ubuntu/ trusty main restricted universe multiverse

deb http://mirrors.163.com/ubuntu/ trusty-security main restricted universe multiverse

deb http://mirrors.163.com/ubuntu/ trusty-updates main restricted universe multiverse

deb http://mirrors.163.com/ubuntu/ trusty-proposed main restricted universe multiverse

deb http://mirrors.163.com/ubuntu/ trusty-backports main restricted universe multiverse

deb-src http://mirrors.163.com/ubuntu/ trusty main restricted universe multiverse

deb-src http://mirrors.163.com/ubuntu/ trusty-security main restricted universe multiverse

deb-src http://mirrors.163.com/ubuntu/ trusty-updates main restricted universe multiverse

deb-src http://mirrors.163.com/ubuntu/ trusty-proposed main restricted universe multiverse

deb-src http://mirrors.163.com/ubuntu/ trusty-backports main restricted universe multiverse

 

deb http://mirrors.sohu.com/ubuntu/ trusty main restricted universe multiverse

deb http://mirrors.sohu.com/ubuntu/ trusty-security main restricted universe multiverse

deb http://mirrors.sohu.com/ubuntu/ trusty-updates main restricted universe multiverse

deb http://mirrors.sohu.com/ubuntu/ trusty-proposed main restricted universe multiverse

deb http://mirrors.sohu.com/ubuntu/ trusty-backports main restricted universe multiverse

deb-src http://mirrors.sohu.com/ubuntu/ trusty main restricted universe multiverse

deb-src http://mirrors.sohu.com/ubuntu/ trusty-security main restricted universe multiverse

deb-src http://mirrors.sohu.com/ubuntu/ trusty-updates main restricted universe multiverse

deb-src http://mirrors.sohu.com/ubuntu/ trusty-proposed main restricted universe multiverse

deb-src http://mirrors.sohu.com/ubuntu/ trusty-backports main restricted universe multiverse

 

deb http://mirrors.oschina.net/ubuntu/ trusty main restricted universe multiverse

deb http://mirrors.oschina.net/ubuntu/ trusty-backports main restricted universe multiverse

deb http://mirrors.oschina.net/ubuntu/ trusty-proposed main restricted universe multiverse

deb http://mirrors.oschina.net/ubuntu/ trusty-security main restricted universe multiverse

deb http://mirrors.oschina.net/ubuntu/ trusty-updates main restricted universe multiverse

deb-src http://mirrors.oschina.net/ubuntu/ trusty main restricted universe multiverse

deb-src http://mirrors.oschina.net/ubuntu/ trusty-backports main restricted universe multiverse

deb-src http://mirrors.oschina.net/ubuntu/ trusty-proposed main restricted universe multiverse

deb-src http://mirrors.oschina.net/ubuntu/ trusty-security main restricted universe multiverse

deb-src http://mirrors.oschina.net/ubuntu/ trusty-updates main restricted universe multiverse

 

4). 保存之后, 更新数据源.

sudo apt-get update

 

执行完上面几步, 数据源就更新完成了, 下面就开始安装编译依赖的软件, 同样, 在终端中以行为单位依次输入以下命令:

sudo apt-get install gnupg

sudo apt-get install flex

sudo apt-get install bison

sudo apt-get install gperf

sudo apt-get install zip

sudo apt-get install curl

sudo apt-get install build-essential

sudo apt-get install libesd0-dev

sudo apt-get install libwxgtk2.6-dev

sudo apt-get install libsdl-dev

sudo apt-get install lsb-core

sudo apt-get install lib32readline-gplv2-dev

sudo apt-get install g++-multilib

sudo apt-get install lib32z1-dev

sudo apt-get install libswitch-perl

这个过程有些费时,快的话一个小时左右。

 

 

3. 开始编译, 在你下载源码的目录, 执行一下命令:

   make

 

4、Make 文件说明(3

编译整个系统——make,耗时较长

编译SDK——make sdk

单个模块编译——make Media Provider,会将该模块依赖的所有模块也一起编译

编译某个目录下的模块——mm

编译某个目录下的指定模块——mmm

 

 

编译的结果输出(3


 

所有结果都在/out 目录

/out/host/:存放开发工具, 如:emulatoradbaapt 等。

/out/target/common/:主要存放 Java 应用代码和 Java 库。

/out/target/product/<product_name>/:<.img>镜像文件.

/out/target/product/<product_name>/镜像文件

 

编译结束后会生成镜像文件和一些目录

 

ramdisk.img:在启动时将被 Linux 内核挂载为只读分区,它包含了 /init 文件和一些配置文件。它用来挂载其他系统镜像并启动 init 进程。

 

system.img:包含了 Android OS 的系统文件,共享库,可执行文件以及预置的应用程序,将被挂载为根分区。

userdata.img:将被挂载为 /data,包含了应用程序相关的数据以及和用户相关的数据。

 

 

刷机:一般是系统升级或是换系统。

烧机:重新灌录软件。包括应用软件和操作系统(OS)。

 

 

6、Build系统介绍(3

 Android Build 系统是用来编译 Android 系统,Android SDK 以及相关文档的一套框架。众所周知,Android 是一个开源的操作系统。Android 的源码中包含了许许多多的模块。 不同厂商的不同设备对于 Android 系统的定制都是不一样的。如何将这些模块统一管理起来,如何能够在不同的操作系统上进行编译,如何在编译时能够支持面向不同的硬件设备,不同的编译类型, 且还要提供面向各个产商的定制扩展,是非常有难度的。 Android Build 系统很好的解决了这些问题,这里面有很多值得我们开发人员学习的地方。对于 Android 平台开发人员来说,本文可以帮助你熟悉你每天接触到的构建环境。对于其他开发人员来说,本文可以作为一个 GNU Make 的使用案例,学习这些成功案例,可以提升我们的开发经验。

 

 

源码查看工具的安装(11

要学会看源代码,比较我们今天学习Android启动流程、handler消息机制等等都是通过看源码学习的。如果有一天你需要研究多媒体模块,怎么办,看源代码。

安装工具<Source Insight>

 第一次安装需要输入序列号。点击keygen.exe生成即可。

2、工具使用:

新建源码工程: ProjectàNew project

设置工程路径

where do you want to store the project data files?

你想保存的工程数据文件在哪里?

 

导入源码

源码的导入方式一:具体需要研究那个模块,就将该模块导入

源码的导入方式二:导入整个源码,Add Tree方式

修改文字大小:OptionsàDocument Options…àScreen Fonts…

如图:

 



 

点击上面的OK

 

 

点击上面的OK


 

选中要加载的代码如下图

 

点击上图Add Tree 后会弹出两个对话框

第一个对话框:不用管

 

 

 

第二个对话框:点击确定

 

 

 

加载代码中。。如下图

 

 

 

加载后如下图

 

 

 

点击Close

 

 

加载后搜索Activity或者Context

 

 

 

分析Android系统启动过程(75

1、Bootloader 引导程序

2、Linux Kernel 内核启动

3、Android 系统启动

查看代码流程:

1、搜索init.c---选择(system/core/init.c)双击--->在左边搜索:main---->里面有定义变量,创建各种目录,挂载目录,初始化日志,初始化解析配置文件--->

 

2、搜索Init.rc--->选择(system/core/rootdir)双击打开----->early-init(最高级别)---->设置全局变量、创建目录、加载目录----->netd噪声等效温差---->ril-daemon(守护进程服务)-->zygote(孵化器这个很重要)------->bootanim(启动动画)----->keystore(签名)

 

zygote(孵化器这个)----->app_process是个目录呢(\frameworks\base\cmds\app_process---->打开里面文件------->搜索:main方法------>AppRunTime(应用运行时)---->启动zygote(孵化器)------>

搜索ZygoteInit.java---->左边搜索main方法--->

VMRuntime.getRuntime().setMinimumHeapSize(5 * 1024 * 1024)(设置5MB空间)----->ZygoteInit.class.getClassLoader().getResourceAsStream(

                PRELOADED_CLASSES)---->

5、源码目录下搜索:preloaded-classesframeworks\base)

---->打开查看(里面就是很多类,这些类是系统运行时需要)--->startSystemServer(Zygote孵化器进程开始孵化系统核心服务)--->

 

6、搜索SystemServer(看到的是ServerThread)---->查看左边SystemServer---->

main方法----->System.loadLibrary("android_servers");加载c库--->init1调用动态连接库中的C函数----->

7、//这里init1的函数函数定义在

frameworks\base\services\jni\com_android_server_SystemServer.cpp) native public static void init1(String[] args);

----->

8、com_android_server_SystemServer.cpp的代码片段如下------>

native方法init1,映射到android_server_SystemServer_init1(这里定义函数指针)----->>转调----->>extern "C" int system_init();--->

 

右边搜索-->system_init---->查看并写注释--->

SystemServer类中静态方法init2---->查看并写注释--->

左边搜索:ServerThread---->run方法里面就是启动系统核心服务并且放到ServiceManager进行同一管理--->

ActivityManangerService ---->systemReady方法如具体实现-->

---->ActivityStack中的resumeTopActivityLocked--->具体实现-->

startHomeActivityLocked----> Home界面显示,这时Android系统启动完毕,进入待机画面

 

查看源码细节:

 

当系统引导程序启动Linux内核时,内核会加载各种数据结构和驱动程序,有了驱动之后,开始启动Android系统并加载用户级别的第一个进程init(system/core/init/Init.c)

   int main(int argc, char **argv)

    {

 

        ....

        //定义各种变量

        int keychord_fd_init = 0;

 

        //创建各种文件夹

        mkdir("/dev", 0755);   

 

        ....           

 

        //挂载文件夹

        mount("devpts", "/dev/pts", "devpts", 0, NULL);

 

        //初始化日志

        log_init();         

 

        //初始化解析配置文件

        init_parse_config_file("/init.rc");

 

        ......

 

        return 0;

 

 

    }

 

加载Init.rc(system/core/rootdir)文件。主要启动了一个zygote(孵化器)进程,此进程是Android系统启动关键服务的一个母进程:

   service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server

        socket zygote stream 666

        onrestart write /sys/android_power/request_state wake

        onrestart write /sys/power/state on

        onrestart restart media

        onrestart restart netd

 

       //app_process是个目录呢-\frameworks\base\cmds\app_process

 

Zygote(孵化器)进程初始化在Appmain.cpp(frameworks\base\cmds\appprocess),代码如下

   int main(int argc, const char* const argv[])

    {

             //定义Android运行时环境

 

            AppRuntime runtime;

 

            int i = runtime.addVmArguments(argc, argv);

 

            // Next arg is parent directory

            if (i < argc) {

                runtime.mParentDir = argv[i++];

            }

 

            .......

 

            bool startSystemServer = (i < argc) ?

                    strcmp(argv[i], "--start-system-server") == 0 : false;

            setArgv0(argv0, "zygote");

            set_process_name("zygote");

 

            //使运行时环境启动Zygote的初始化

            runtime.start("com.android.internal.os.ZygoteInit",

                startSystemServer);

           .......

      }

 

现在从C或者C++进入Java世界中,初始化ZygoteInit.java这个类,代码如下:

public static void main(String argv[]) {

    try {

 

        //加载系统运行时依赖的类

        preloadClasses();

        //加载资源文件

        preloadResources();

 

        if (argv[1].equals("true")) {

            //Zygote孵化器进程开始孵化系统核心服务

            startSystemServer();

        } else if (!argv[1].equals("false")) {

            throw new RuntimeException(argv[0] + USAGE_STRING);

        }           

 

       ........

}

 

 

 

//开始孵化系统核心服务方法

 private static boolean startSystemServer()

        throws MethodAndArgsCaller, RuntimeException {

    /* Hardcoded command line to start the system server */

    String args[] = {

        "--setuid=1000",

        "--setgid=1000",

        "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,3001,3002,3003",

        "--capabilities=130104352,130104352",

        "--runtime-init",

        "--nice-name=system_server",

        "com.android.server.SystemServer",

    };

       ........................

        //Zygote孵化器分叉开启SystemServer类,并且把上面定义的参数,传给SystemServer类,用户启动系统关键服务。

        pid = Zygote.forkSystemServer(

                parsedArgs.uid, parsedArgs.gid,

                parsedArgs.gids, debugFlags, null,

                parsedArgs.permittedCapabilities,

                parsedArgs.effectiveCapabilities);

 

    ..................

 

   }   

 

Zygote进程分叉出SystemServer类,main函数如下:

       public static void main(String[] args) {

 

                .......

                //加载本地的动态链接库。

 

                System.loadLibrary("android_servers");

                //调用动态连接库中的C函数。

                init1(args);

 

        }

 

    //这里init1的函数函数定义在(frameworks\base\services\jni\com_android_server_SystemServer.cpp

    native public static void init1(String[] args);

 

comandroidserver_SystemServer.cpp的代码片段如下:

   static JNINativeMethod gMethods[] = {

        /* name, signature, funcPtr */

        //native方法init1,映射到android_server_SystemServer_init1(这里定义函数指针)

        { "init1", "([Ljava/lang/String;)V", (void*) android_server_SystemServer_init1 },

    };

 

 

 

    int register_android_server_SystemServer(JNIEnv* env)

    {

        //转调

        return jniRegisterNativeMethods(env, "com/android/server/SystemServer",

                gMethods, NELEM(gMethods));

    }

 

 

    //此方法没有方法体

    extern "C" int system_init();

 

system_init()方法体,在system_init.cpp类,代码如下;

       extern "C" status_t system_init()

        {

 

 

             //开启一些硬件相关服务

              SensorService::instantiate();

 

 

 

                // Start the media playback service

               MediaPlayerService::instantiate();

 

                // Start the camera service

               CameraService::instantiate();

 

                // Start the audio policy service

               AudioPolicyService::instantiate();

            }

 

              .......

            //获取Android运行时环境

 

            AndroidRuntime* runtime = AndroidRuntime::getRuntime();

 

            LOGI("System server: starting Android services.\n");

            //调用SystemServer类中静态方法init2,native 层转调Java

            runtime->callStatic("com/android/server/SystemServer", "init2");

 

            ........

 

        }

 

SystemServer类中静态方法init2代码如下:

   public static final void init2() {

    Slog.i(TAG, "Entered the Android system server!");

    //进入Android系统服务的初始化

    Thread thr = new ServerThread();

    thr.setName("android.server.ServerThread");

    thr.start();

  }

 

ServerThread中的Run中的run方法如下:

   .....

    //初始化系统服务,并且添加各种服务到ServiceManager,便于管理;

       ServiceManager.addService("entropy", new EntropyService());

 

        ......

    //调用了ActivityManagerService systemReady的方法

     ((ActivityManagerService)ActivityManagerNative.getDefault())

            .systemReady(new Runnable() {

        public void run() {

            //

            if (connectivityF != null) connectivityF.systemReady();

            if (dockF != null) dockF.systemReady();

            if (usbF != null) usbF.systemReady();

            if (uiModeF != null) uiModeF.systemReady();

            if (recognitionF != null) recognitionF.systemReady();

           .........

        }

    });

 

     .....................

}

 

ActivityManangerService 下的systemReady方法如下:

public void systemReady(final Runnable goingCallback) {

    ......

    //调用ActivityStack中的resumeTopActivityLocked的方法去启动Activity

   mMainStack.resumeTopActivityLocked(null);

 

 

}

 

ActivityStack中的resumeTopActivityLocked方法如下:

 final boolean resumeTopActivityLocked(ActivityRecord prev) {

 

    //找到第一个当前没有关闭的Activity,系统刚刚启动没有任何Activity执行,所有nextnull

    ActivityRecord next = topRunningActivityLocked(null);

 

    // Remember how we'll process this pause/resume situation, and ensure

    // that the state is reset however we wind up proceeding.

    final boolean userLeaving = mUserLeaving;

    mUserLeaving = false;

 

    if (next == null) {

        // There are no more activities!  Let's just start up the

        // Launcher...

        if (mMainStack) {

            //启动Launcher 应用的第一个Activity页面

            return mService.startHomeActivityLocked();

        }

    }

}

 

Home界面显示,这时Android系统启动完毕,进入待机画面;


6、回顾Android系统启动过程(12

 

7Handler消息机制

 

1、Handler四大核心对象及源代码(60

 

Handler: 消息处理器.

   发送消息

   处理消息

Message: 消息(数据载体). 

MessageQueue: 消息队列(存储消息).

Looper: 轮询器.

  MessageQueue取消息

  分发给Handler处理

 

 

查看源码步骤:

1、查看 Message.java\frameworks\base\core\java\android\os)源代码---->

obtain()方法以及同名方法---->讲解-->

2.查看Handler无参构造方法---->

myLooper()--->prepare()--->prepareMainLooper()--->

消息队列MessageQueue创建-->在Looper构造方法里构造

Looper的创建--->prepare()方法中

 

谁调用prepareMainLooper?---->

搜索ActivityThread.java--->看一看main方法-->

Looper类中的loop方法-->main方法执行loop-->

使用Handler对象发消息sendMessage--->

回到loop方法,主线程被唤醒,继续执行while循环--->

Handler中的dispatchMessage方-->

用户在使用Handler时,必须实现handleMessage方法处理消.

 

 

 

Handler消息机制

Message对象的创建:

   Message msg = new Message();

    Message msg = Message.obtain();

 

Handler对象,初始化完毕后,其中主线程的Looper对象已经开始轮询,循环取消息,但没有消息,主线程处于休眠。代码如下:

   new Handler(){

 

        //得到一个主线程的Looper对象

        mLooper = Looper.myLooper();

        if (mLooper == null) {

            throw new RuntimeException(

                "Can't create handler inside thread that has not called Looper.prepare()");

        }

        //主线程的消息队列对象

        mQueue = mLooper.mQueue;

        mCallback = null;

 

    }

 

主线程的Looper的初始化,在ActivityThread.java中的main函数中,代码如下:

   public static final void main(String[] args) {

 

            .....

        //在主线程中调用了prepareMainLooper方法,此方法中创建了一个Looper对象,此Looper对象就是主线程中的Looper.

            Looper.prepareMainLooper();

            .....

 

            Looper.loop();

 

 

        }

 }  

 

Looper类中的loop方法,其中有一个死循环,是否阻塞主线程?设计概念管道(Pipe),管道可以实现进程间通信。原理:管道其实即使Linux系统一种通讯方式,实现方式主要是一个特殊的文件来实现,此文件有两个描述符(对文件进程操作的一个句柄(引用)),一个是读取的,一个是写的。

应用场景:主线程拿着读取的描述符在等待读取,这时候子线程拿着写入的操作符进写入,当写入时候会唤醒主线程,主线程开始读取线程写入的内容。执行循环的代码。

Handler的场景:主线程在while循环中,取消息:1,取到消息后,分发消息;2.没取到消息,阻塞主线程,主线程休眠。当子线程sendMessage发消息时,这时用写入的描述符希写入到管道中,主线程被唤醒,继续跑它的循环,取消息。

   public static final void loop() {

    Looper me = myLooper();

    MessageQueue queue = me.mQueue;

    while (true) {

        Message msg = queue.next(); // might block

        //if (!me.mRun) {

        //    break;

        //}

        if (msg != null) {

            if (msg.target == null) {

                // No target is a magic identifier for the quit message.

                return;

            }

            if (me.mLogging!= null) me.mLogging.println(

                    ">>>>> Dispatching to " + msg.target + " "

                    + msg.callback + ": " + msg.what

                    );

            msg.target.dispatchMessage(msg);

            if (me.mLogging!= null) me.mLogging.println(

                    "<<<<< Finished to    " + msg.target + " "

                    + msg.callback);

            msg.recycle();

        }

    }

}

 

使用Handler对象发消息,sendMessage代码如下:

   public final boolean sendMessage(Message msg)   {   

        //1.转调

        return sendMessageDelayed(msg, 0);

    }

 

 

 

 

    public final boolean sendMessageDelayed(Message msg, long delayMillis)  {

    if (delayMillis < 0) {

        delayMillis = 0;

    }

    //2.转调

    return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);

    }

 

 

 

 

    public boolean sendMessageAtTime(Message msg, long uptimeMillis)  {

    boolean sent = false;

    MessageQueue queue = mQueue;

    if (queue != null) {

        //3.把当前handler对象赋值给Message中的target对象;

        msg.target = this;

        //4.把消息传递给消息队列存起来。

        sent = queue.enqueueMessage(msg, uptimeMillis);

    }

    else {

        RuntimeException e = new RuntimeException(

            this + " sendMessageAtTime() called with no mQueue");

        Log.w("Looper", e.getMessage(), e);

    }

    return sent;

   }

 

 

 

 

 

  //此方法是把传递进来的消息按照先后顺序或者时间来进行排序,并且存起来。

   final boolean enqueueMessage(Message msg, long when) {

        ........

 

        msg.when = when;

        //Log.d("MessageQueue", "Enqueing: " + msg);

        Message p = mMessages;

        if (p == null || when == 0 || when < p.when) {

            msg.next = p;

            mMessages = msg;

            needWake = mBlocked; // new head, might need to wake up

        } else {

            Message prev = null;

            while (p != null && p.when <= when) {

                prev = p;

                p = p.next;

            }

            msg.next = prev.next;

            prev.next = msg;

            needWake = false; // still waiting on head, no need to wake up

        }

    }

    if (needWake) {

        nativeWake(mPtr);

    }

    return true;

}

 

主线程被唤醒,继续执行while循环。

   public static final void loop() {

            Looper me = myLooper();

            //取出刚刚发送的消息

            MessageQueue queue = me.mQueue;

            while (true) {

                Message msg = queue.next(); // might block

                //if (!me.mRun) {

                //    break;

                //}

                if (msg != null) {

                    if (msg.target == null) {

                        // No target is a magic identifier for the quit message.

                        return;

                    }

                    if (me.mLogging!= null) me.mLogging.println(

                            ">>>>> Dispatching to " + msg.target + " "

                            + msg.callback + ": " + msg.what

                            );

                    //因为Message中的target对象就是handler对象,这里其实调用的是handler中的dispatchMessage方法。

                    msg.target.dispatchMessage(msg);

                    if (me.mLogging!= null) me.mLogging.println(

                            "<<<<< Finished to    " + msg.target + " "

                            + msg.callback);

                    msg.recycle();

                }

            }

        }

 

Handler中的dispatchMessage方法,代码如下:

   public void dispatchMessage(Message msg) {

        if (msg.callback != null) {

            handleCallback(msg);

        } else {

            if (mCallback != null) {

                if (mCallback.handleMessage(msg)) {

                    return;

                }

            }

            //调用了自动的handleMessage

            handleMessage(msg);

        }

    }

 

/**

 * Subclasses must implement this to receive messages.

 * 子类必须实现此方法接收消息

 */

public void handleMessage(Message msg) {

}

 

用户在使用Handler时,必须实现handleMessage方法处理消息,代码如下:

   Handler handler = new Handler(){

        public void handleMessage(Message msg){

         .....

            //处理不同的消息

 

        }

 

 

    }

 

 

2、画图分析(10

 

 

 

AsyncTask原理(78

 

 

1、AsyncTask 异步任务, 主要包含两个关键类:

InternalHandler: 消息处理器, 用于处理线程之间消息.

ThreadPoolExecutor: 线程池, 用于处理耗时任务.

 

2、AsyncTask的伪代码实现

        new AsyncTask<String ,String ,String>(){

 

           //2.在主线程执行,做一条准备操作;

            public void onPreExecute(){

 

            }

            //3.运行在子线程中,做一些耗时的操作,比如联网请求数据。

            public String doInBackground(String ...params){

 

                return null;

 

            }

            //4.result就是doInBackground方法返回的值,做一些释放资源的操作。

            public void onPostExecute(String result){

 

            }

 

 

         }.execute(String ...params);//1.在主线程中执行这个方法,要开始执行异步任务了;

 

自定义AsyncTask机制。

 

 

创建一个小工程名字叫:自定义异步任务,并且自定义类CommonAsyncTask

 

package com.example.asynctask;

/**

 * 自定义异步任务

 *

 */

public abstract class CommonAsyncTask {

/**

 * 执行任务之前,调用该方法,运行在主线程中。

 */

public abstract void onPreExecute();

/**

 * 运作在子线程中,需要执行耗时任务。

 */

public abstract String doInBackground(String ...params);

/**

 *

 * 在任务执行之后,调用该方法,运行在主线程中

 */

public abstract void onPostExecute(String result);

/**

 * 开始之异步任务.

 * @param params 参数

 */

public void execute(String ...params){

}

 

}

 

 

 

开始执行任务并实现相关方法

 

 在里面在写相应方法

public void execute(final String ...params){

onPreExecute();

new Thread(){

public void run() {

String result = doInBackground(params);

};

}.start();

}

class InternalHandler extends Handler{

@Override

public void handleMessage(Message msg) {

}

}

 

 

Ctrl+Shift+x---功能是把小写变成大小

Ctrl+1--->提示创建变量

 

private IntenalHandler handler;

 

 

public void execute(final String ...params){

if(handler == null){

handler = new InternalHandler();

}

onPreExecute();

new Thread(){

public void run() {

String result = doInBackground(params);

//1.第一种写法。

//Message msg =handler.obtainMessage(DOINBACKGROUND_FINISH, result);

//handler.sendMessage(msg);

//2.推荐这种写法

handler.obtainMessage(DOINBACKGROUND_FINISH, result).sendToTarget();

//3.第三种写法

//Message msg = new Message();

//msg.what = DOINBACKGROUND_FINISH;

//msg.obj = result;

//handler.sendMessage(msg);

};

}.start();

}

 

 

 

class IntenalHandler extends Handler{

@Override

public void handleMessage(Message msg) {

if(msg.what==DOINBACKGROUND_FINISH){

String result = (String) msg.obj;

System.out.println("子线程执行完成:"+result);

onPostExecute(result);

}

}

}

 

 

 

 

在点击事件中使用

 

 

public void click(View view){

new CommonAsyncTask() {

@Override

public void onPreExecute() {

printThreadName("当前是onPreExecute方法");

}

@Override

public String doInBackground(String... params) {

printThreadName("当前是doInBackground方法");

SystemClock.sleep(10000);

System.out.println("doInBackground收到的参数:"+params[0]+","+params[1]);

return "请求成功";

}

@Override

public void onPostExecute(String result) {

printThreadName("当前是onPostExecute方法");

Toast.makeText(MainActivity.this, "当前是onPostExecute方法:"+result, 1).show();

}

}.execute(new String[]{"参数1","参数2"});

}

 

 

/**

 * 输出当前正在运行的进程名称

 * @param msg

 */

public void printThreadName(String msg){

System.out.println("当前线程名称:"+Thread.currentThread().getName()+",消息是:"+msg);

}

 

 

 

查看源代码顺序

 

Source Insight 搜索AsyncTask.java->接着查找execute方法

查看onPreExecute();是一个空方法--->

分析mWorker.mParams = params---->mWorkerAsyncTask构造方法中初始化

mWorker以参数传给FutureTask构造方法-->查看FutureTask构造方法

看源码可知道WorkerRunnableCallable的实现类

FutureTask构造方法中的Sync类,里的callablemWorker

分析 sExecutor.execute(mFuture);

查看sExecutor--->线程池

mFuture 指的就是FutureTask

查看mWorker的初始化过程

 

查看mWorker的初始化过程,代码如下:

   //mWorkerAsyncTask构造方法在一开始一步任务时,已经调用。

 

    public AsyncTask() {

    mWorker = new WorkerRunnable<Params, Result>() {

        public Result call() throws Exception {

              ......

        }

    };

    //1.mWorker对象传递给了FutureTask的构造函数

    mFuture = new FutureTask<Result>(mWorker) {

        @Override

        protected void done() {

          .......

        }

     };

   }

 

 

    //FutureTask类中接收了Callable的类型,其实WorkerRunnable类型实现了Callable的类型。

    public FutureTask(Callable<V> callable) {

    if (callable == null)

        throw new NullPointerException();

        //2.callable也就是mWorker传递给Sync构造方法

      sync = new Sync(callable);

    }

 

 

 

 

    Sync(Callable<V> callable) {

        //把接收过来的callablemWorker)对象赋值给Sync的成员变量callable;

        this.callable = callable;

    }

sExecutor.execute(mFuture);线程池开始执行任务,我们塞给它Runable,这个时候只需要看mFuture的run方法即可。

   public void run() {

     //1.调用了SyncinnerRun方法

      sync.innerRun();

    }

 

 

 

    void innerRun() {

        if (!compareAndSetState(READY, RUNNING))

            return;

 

        runner = Thread.currentThread();

        if (getState() == RUNNING) { // recheck after setting thread

            V result;

            try {

                //2.调用了callable(mWorker)call方法,获取一个返回结果

                result = callable.call();

            } catch (Throwable ex) {

                setException(ex);

                return;

            }

            //4.把结果传递给set方法

            set(result);

        } else {

            releaseShared(0); // cancel

        }

    }

 

 

    //AsyncTask构造方法中初始化。

    mWorker = new WorkerRunnable<Params, Result>() {

        public Result call() throws Exception {

            Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);

            //3.调用了用户实现的doInBackground方法,去执行一个耗时的任务,运行在子线程中。

            //doInBackground的参数是execute方法传进来的参数。

            return doInBackground(mParams);

        }

    };

 

 

 

     protected void set(V v) {

       //5.继续把参数传给innerSet方法

       sync.innerSet(v);

    }

 

 

       void innerSet(V v) {

            for (;;) {

                int s = getState();

                if (s == RAN)

                    return;

                if (s == CANCELLED) {

                    // aggressively release to set runner to null,

                    // in case we are racing with a cancel request

                    // that will try to interrupt runner

                    releaseShared(0);

                    return;

                }

                if (compareAndSetState(s, RAN)) {

                    //6.doInBackground返回的方法结果负责给成员变量result;

                    result = v;

                    releaseShared(0);

                    //7.调用FutureTask中的done方法

                    done();

                    return;

                }

            }

        }

 

 

 

 

 

        //该方法默认在AsyncTask构造方法中初始化,并且覆盖done方法。

        mFuture = new FutureTask<Result>(mWorker) {

        @Override

        protected void done() {

            Message message;

            Result result = null;

 

            try {

                //8.调用FutureTask中的get方法获取result(doInBackground)方法的结果。

                result = get();

            } catch (InterruptedException e) {

                android.util.Log.w(LOG_TAG, e);

            } catch (ExecutionException e) {

                throw new RuntimeException("An error occured while executing doInBackground()",

                        e.getCause());

            } catch (CancellationException e) {

                message = sHandler.obtainMessage(MESSAGE_POST_CANCEL,

                        new AsyncTaskResult<Result>(AsyncTask.this, (Result[]) null));

                message.sendToTarget();

                return;

            } catch (Throwable t) {

                throw new RuntimeException("An error occured while executing "

                        + "doInBackground()", t);

            }

            //11.创建一个消息对象

            message = sHandler.obtainMessage(MESSAGE_POST_RESULT,

                    new AsyncTaskResult<Result>(AsyncTask.this, result));

            //12.把当前消息使用sHandlerIntenalHandler其实就是Handler)发送出去。

            message.sendToTarget();

        }

    };

 

 

 

     public V get() throws InterruptedException, ExecutionException {

        //9.转调Sync中的innerGet方法

       return sync.innerGet();

     }

 

 

     V innerGet() throws InterruptedException, ExecutionException {

          ......

        //10.resultdoInBackgroud的结果)返回回去.result成员变量在innerSet方法中赋值。详情看第6步。

        return result;

    }

 

 

 

 

    private static class InternalHandler extends Handler {

        @SuppressWarnings({"unchecked", "RawUseOfParameterizedType"})

        @Override

        public void handleMessage(Message msg) {

            AsyncTaskResult result = (AsyncTaskResult) msg.obj;

            switch (msg.what) {

                case MESSAGE_POST_RESULT:

                    // There is only one result

                    //13.调用AsyncTask中的finish()方法,并且把doInBackground方法中执行的结果传递进去。

                    result.mTask.finish(result.mData[0]);

                    break;

                case MESSAGE_POST_PROGRESS:

                    result.mTask.onProgressUpdate(result.mData);

                    break;

                case MESSAGE_POST_CANCEL:

                    result.mTask.onCancelled();

                    break;

            }

        }

    }

 

 

 

 

     private void finish(Result result) {

        if (isCancelled()) result = null;

        //14.doInBackgroud的返回的结果传递给用户实现的onPostExecute方法,这个方法是执行在主线程中。用户可以做一些更新页面的操作。

        onPostExecute(result);

        mStatus = Status.FINISHED;

      }

 

 

 

 

  • 0
    点赞
  • 1
    评论
  • 3
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值