- Android群英传
- 徐宜生
- 1227字
- 2020-08-27 08:27:10
第1章
Android体系与系统架构
本章作为本书的第1章,将带领读者对Google生态圈及Android系统有一个宏观的概念和认识。同时,让读者能够了解整个系统的架构,了解手机中的Android系统、IDE中的Android系统都由哪些元素构成。
学习本章,你将了解到以下内容:
● Google生态系统
● Android系统架构
● Android源代码与系统目录结构
1.1 Google生态系统
Android自诞生以来,就以一个“富二代”的形象出现在世人的眼中。从Google的收购,到成立开放手机联盟,到现在一举成为市场占有率最高的移动操作系统,Android一直就流淌着“富二代”的血。底层通过最快的C语言保证效率,上层使用Java简单、快速进行开发,开放的系统让各个Android社区、开发者论坛空前火爆,甚至是可以进行无限可能的系统定制化。可以说Android的到来,奠定了移动操作系统一个里程碑式时代的开始。现在,Google正利用其搜索、移动、web的各个入口,来逐渐掌握互联网的控制权。而Android有了Google这样一个“干爹”的支持,更是如鱼得水,不仅在搜索上利用Google Now的优势,更利用Google Map这样一个强有力的工具,将移动系统与Web系统紧密地联系在了一起。
Android诞生已经六年了,Android在世人的见证下不断成长,就好比人类的进化史,一步步逐渐走向更辉煌的未来。
图1.1 人类进化史
图1.2 Android进化史
1.2 Android系统架构
我们每天都在讲“Android”、“Android”,可谁能告诉我,“Android”到底是什么呢?从宏观上讲,Android是一个移动操作系统,但这是一个很宽泛的概念。达·芬奇通过解剖了解人体结构,才能把人物画得逼真传神,那么我们今天也来“解剖”一下Android。
如图1.3所示,这是一张讲解Android系统架构的经典示意图。它将Android大致分为了四层,即Linux内核层、库和运行时、Framework层和应用层。Android的体系架构鼓励系统组件重用,共享组件间的数据,并且定义组件间的访问权限控制。可以说,这些层次结构既是相互独立,又是相互关联的。
图1.3 Android系统架构
下面我们继续“开刀”。有人说,Android是一个用于连接设备的软件集合,图1.4就代表了一个最抽象的Android系统架构。
图1.4 Android架构总览
1.2.1 Linux
Linux层,Android最低层最核心的部分。当我们打开手机Setting,选择about phone选项,这一选项所显示的内核版本,就是我们所用的Linux内核的版本。Linux层包含了Android系统的核心服务,包括硬件驱动、进程管理、安全系统,等等。
1.2.2 Dalvik与ART
Dalvik包含了一整套的Android运行环境虚拟机,每个App都会分配Dalvik虚拟机来保证互相之间不受干扰,并保持独立。它的特点是在运行时编译。打个比方,就好比你买了一辆可折叠的自行车,平时是折叠的,只有骑的时候,才需要组装起来用。而在Android 5.X版本开始,ART模式已经取代了Dalvik, ART采用的是安装时就进行编译,以后运行时就不用编译了,这就好比你买了辆组装好了的自行车,装好就可以骑了。当然,对在其虚拟机环境中运行的大部分App来说,它们都运行着同样的代码。
1.2.3 Framework
如图1.5所示为图1.4中Android App Framework的详细版。它包含了整个Android Framework的重点,如果你以后要研究Framework的具体流程,基本就是在和它们打交道。
图1.5 Android App Framework
1.2.4 Standard libraries
如图1.6所示为图1.4中Standard libraries的详细版,这里包含的是Android中的一些标准库,所谓标准,就是开发者在开源环境中可以使用的开发库。
图1.6 Standard libraries
1.2.5 Application
图1.7和图1.8分别表示了使用NDK开发和Java开发的App的主要构成。可以看出,不管是哪种App,它们都有Android Manifest文件、Dalvik Classes、Resource Bundle这几个东西,相信解压过Apk的朋友应该注意到了,这些就是我们解压Apk后的文件。
图1.7 Android NDK App
图1.8 Android SDK App
对于开发者来说,与Android系统最直接的接触就是SDK,应用开发者应当关注每个版本的SDK修改,从而提高应用的兼容性。如果站在Android设计者的角度上来看整个Android的架构,设计者希望Android的框架层能够起到承上启下的功能,让应用的各个组件之间解耦,并通过框架来进行统一的调度、管理。
Android的系统架构,说简单点,可以只用一张图展示,说复杂点,可以写几千页的书,Android的系统架构就像人心一样,有时候看似简单,却蕴藏着难以捉摸的东西,要想真搞清楚,也绝非一朝一夕之功。所以,初学者首先只需要对这些有一个大概的认识就可以了,等掌握了使用方法后,就可以慢慢地了解它的运行原理,到时候,自然而然,你就会看清楚Android的系统架构。
1.3 Android App组件架构
前面讲解了Android的系统架构,而在应用层,Android的App组件架构,通常就是我们所说的Android四大组件,指的是Activity、BroadCastReciever、ContentProvider和Service,它们是组成一个Android App的最基本元素。
1.3.1 Android四大组件如何协同工作
Android中的四大组件的使用方法与适用场景都各不相同,但它们之间也保持着紧密的联系,你中有我,我中有你,紧密而不可分。
Activity作为人机交互的第一界面,负责向用户展示信息和处理结果,而这些信息的来源,可以是通过资源获取,也可以通过Content Provider来获取其他应用的信息,或是Service从后台计算、下载、处理的结果,当然也可以是通过BroadCast Reciever获取到的广播信息。同时,Android系统还提供了一个信使——Intent,作为信息传递的载体。组件与组件之间通过Intent来通信、传递信息、交换数据,正是通过这样一种方式,四大组件形成了各自独立而又紧密联系的关系,让整个Android系统“活”了起来。
Android的四大组件在开发者的调度下,共同完成着开发者赋予它们的使命,它们之间没有孰优孰劣,所有的组件存在的道理就是为了让程序能够更好地实现开发者的功能。当然,熟知每个组件的功能、特点,才能在使用时运筹帷幄。在这里,大家只需要对四大组件的协同工作模式有个基本的概念即可,随着本书的讲解,大家会慢慢掌握这些组件的使用技巧。
1.3.2 应用运行上下文对象
在高中的时候,语文课本上经常会出现这样一句话——“请联系上下文,分析这句话在文中的作用”,那么这个“上下文”到底是指什么意思呢?在语文中,我们可以理解为语境,在程序中,我们可以理解为当前对象在程序中所处的一个环境,一个与系统交互的过程。
Android系统的上下文对象,即在Context中,为我们封装了这样一个“语境”。Activity、Service、Application都是继承自Context。
Android应用程序会在如下所示的几个时间点创建应用上下文Context。
● 创建Application
● 创建Activity
● 创建Service
不难发现,创建Context的时机就是在创建Context的实现类的时候。当应用程序第一次启动时,Android系统都会创建一个Application对象,同时创建Application Context,所有的组件都共同拥有这样一个Context对象,这个应用上下文对象贯穿整个应用进程的生命周期,为应用全局提供了功能和环境支持。而创建Activity和Service组件时,系统也会给它们提供运行的上下文环境,即创建Activity实例、Service实例的Context对象。所以很多读者在Activity中获取Context对象时,可以直接使用this,而在匿名内部类中,就必须指定XXXXActivity.this才可以获得该Activity的Context对象。当然,你也可以通过getApplicationContext()方法来获取整个App的Context,但是通过getApplicationContext()方法获得的是整个应用的上下文引用,这与某个组件的上下文引用,在某些时候还是有区别的。
1.4 Android系统源代码目录与系统目录
Android源代码的目录中包含了Android系统所有的源代码,从底层驱动到上层应用,Android系统对所有文件都进行了详细管理。而在手机中,Android系统的目录与源代码的目录并不是一一对应的,而是与源代码编译之后,与打包生成的Image文件的结构相同。了解这些目录的结构,对于认识整个Android系统有很好的帮助。
1.4.1 Android系统源代码目录
前面我们已经把Android“大卸八块”了,下面我们就来给Android登记入库,不过这可不是一件容易的事情,要想看完整个Android的源代码,你要懂C、懂脚本、懂Java,不仅软硬兼通,而且有一颗耐得住寂寞、忍得了枯燥的心。所以,对于大多数人来说,我们只需要了解它的框架结构,出了问题知道从哪里着手解决就可以了。这就好比图书管理员,他不一定要把所有的书都读一遍,但是只要有用到,他就可以很快地找到相应的资料。
这里笔者给读者朋友们提供一个查看Android源代码的网站:http://androidxref.com/。网站首页如图1.9所示。
图1.9 AndroidXRef1
图1.10展示了该网站中Android 5.0版本的源代码搜索界面。
图1.10 AndroidXRef2
这里就是我们整个Android图书馆的索引了,每个目录都具有不同的功能和目的,而它们组成在一起,便构成了整个Android大厦,整个结构关系图如下所示。
- Makefile -bionic (bionic C库) -bootable (启动引导相关代码) -build (存放系统编译规则等基础开发包配置) -cts (Google兼容性测试标准) -dalvik (dalvik虚拟机) -development (应用程序开发相关) -external (android使用的一些开源的模块) -frameworks (Framework框架核心) -hardware (厂商硬件适配层HAL代码) -out (编译完成后的代码输出目录) -packages (应用程序包) -prebuilt (x86和arm架构下预编译资源) -sdk (sdk及模拟器) -system (底层文件系统库、应用及组件) -vendor (厂商定制代码)
不过这里要注意的是,并不是所有的源代码结构都是这样。只有AOSP的Android项目才是这样一个结构,有些芯片厂商如MTK,它们的目录结构就与此不同。
Android作为手机操作系统,我们需要将源代码编译后才能使用,那么问题来了,代码编译哪家强?Eclipse? Android Studio?这些都不对,我们首先需要知道,Eclipse、Android Studio这些属于开发IDE,也就是我们的集成开发环境,它体现的是一种简化计算机与开发者的交互,然而当你接触的程序架构越来越丰富,在了解越来越深入后,你就会发现,很多事情,IDE是无法完成的,比如自动化编译、定制编译、版本控制、自动测试等。因此Android与很多语言一样,引入了Makefile机制。那么Makefile到底有什么好处呢?我们先看一下对Makefile的解释:一个像Android这样的大型工程,它的源文件不计其数,不同的功能、模块,按类型分别放置在不同的目录中,这些模块通常会有一个叫Makefile的文件来进行管理。它定义了一系列的规则来指定模块,哪些文件需要编译,以及这些文件该按照怎样的顺序去编译。甚至,它还可以配置更复杂的功能操作,比如定义编译规则,打包规则等,因为Makefile就像一个shell脚本,不仅可以使用自己的语法,也能调用操作系统的命令。
可以看到,Makefile最大的好处就是自动化编译,同时还可以做到可控制的编译,Android通过Makefile来描述Android各个组件间的联系并指导它们进行自动化编译。Makefile的语法,指定了各个源代码该如何连接并生成相应的可执行程序。这时候大家再来看看我们前面列出的Android源代码目录结构,每个目录中,还会包含更多的目录,而它的每一个最小的功能单位的目录下,都会有一个Makefile文件,这样每一级向上,通过这样一个个Makefile文件,就把整个源代码有条不紊地联系在一起了。
很多人可能对Android源代码的编译没有概念,这里举一个例子,笔者公司的电脑CPU是i73770,主频3.4GHz,全编一次Android的代码需要90分钟,如果没有Makefile,简直无法想象该如何去编译源代码。
1.4.2 Android系统目录
在Android手机里,系统的目录结构与源代码目录结构还是有所不同的,我们通过ADB连接上手机,通过Linux的ls命令查看Android系统的根目录,如图1.11所示。其中/system和/data是开发者非常关心的两个目录。
图1.11 Android系统目录
● /system/app/
这里面放的是一些系统的App,如图1.12所示为App目录。
图1.12 Android /system/app/目录
● /system/bin/
这里面主要放的是Linux自带的组件,如图1.13所示为bin目录。
图1.13 Android /system/bin/目录
● /system/build.prop
这里记录的是系统的属性信息,如图1.14所示。
图1.14 Android /system/build.prop
● /system/fonts/
系统字体存放目录root后可下载TTF格式字体替换原字体,达到修改系统字体的效果,如图1.15所示fonts目录。
图1.15 Android /system/fonts/目录
● /system/framework/
系统的核心文件、框架层,如图1.16所示。
图1.16 Android /system/framework/目录
● /system/lib/
存放几乎所有的共享库(.so)文件,如图1.17所示,一些手机中的.so库文件。
图1.17 Android /system/lib/目录
● /system/media/
该目录用来保存系统提示音、系统铃声,如图1.18所示。
图1.18 Android /system/media/目录
其中/system/media/audio/目录,这里面保存着Android系统默认的铃声,alarms目录是闹铃提醒,notification目录是短信或提示音,ringtones目录是来电铃声,而ui目录则是一些界面音效,如图1.19所示。
图1.19 Android /system/media/audio/目录
● /system/usr/
该目录用来保存用户的配置文件,如键盘布局、共享、时区文件等,如图1.20所示。
图1.20 Android /system/usr/目录
● /data/app/
data目录包含了用户的大部分数据信息。其中,/data/app/这个目录包含了用户安装的App或者升级的App,如图1.21所示。
图1.21 Android /data/app/目录
● /data/data/
这个目录应该是开发者访问的最多的目录了,这里包含了App的数据信息、文件信息、数据库信息等,以包名的方式来区分各个应用,如图1.22所示。
图1.22 Android /data/data/目录
● /data/system/
这个目录包含了手机的各项系统信息,如图1.23所示。
图1.23 /data/system/目录
● /data/misc/
这个目录保存了大部分的Wi-Fi、VPN信息,如图1.24所示。
图1.24 Android /data/misc/目录
1.4.3 Android App文件目录
现在终于回到了我们熟悉的应用层,大家可以长舒一口气,不用再看几个GB大小的源代码了。下面我们就以Android Studio IDE为开发环境,来分析一下Android Application的文件目录结构。
当你使用Android Studio生成一个Android Application工程后,文件目录结构如图1.25所示。
图1.25 Android Application目录
关于Eclipse和Android Studio的文件目录区别,在第2章中会进行详细讲解,简单来说,大家只需要了解一点,Android Studio中的Project就相当于Eclipse里面的Workspace,而Android Studio中的Module就相当于Eclipse里面的Project就可以了。
图1.25中,App目录中的代码为应用程序代码,而下面的Gradle Scripts为编译脚本,后面我们讲Android Studio的使用的时候,会再详细地了解它们的作用。
总体来看,Android Application的目录是比较清晰、简单的,这也得力于Android底层做的良好的封装和IDE的强大。后面我们的大部分工作都将在这个目录结构下进行操作。