Android 开发入门与实战(第二版)
上QQ阅读APP看书,第一时间看更新

第5章 良好的学习开端——Android应用程序架构分析

从本章你可以学到:

Android系统结构

Android应用程序工程结构组成

5.1 Android系统架构

Android是一个移动设备的开发平台,而“系统”在新手的学习路上往往会给人一种神秘并且抽象的感觉。而这章会带大家一起简单分析一下Android的系统架构,通过分析,相信大家会了解到,其实Android系统也是由很多“个体”组成,如果大家想对系统进行完整的学习,那么可以根据体系架构图中所示,进一步深入分析各个“个体”(应用框架层,Libraries,Linux Kernel)。当然,这个过程是需要付出很多努力的。而我们现在主要关注于Android应用层这个“个体”。

在分析之前,我们先来看图5-1,这张图是Android官网的Android系统架构图。从图5-1中我们可以看到Android系统架构一共有四个主要的组成部分,从上往下依次是APPLICATIONS(应用程序层),APPLICATION FRAMEWORK(应用程序框架层),LIBRARIES(ANDROID RUNTIME) (库以及运行环境),以及LINUX KERNEL(Linux内核)。下面将对每个组成部分进行简单的说明。

▲图5-1 Android系统架构图

5.1.1 Applications(应用程序层)

在Android平台中,用户能够与之直观交互的就是应用程序了。而这些程序(例如Home[桌面],联系人[Contacts],电话[Phone],浏览器[Browser]等)都是处于平台中的应用程序层。应用程序目前都是使用 Java 语言编写的,虽然 Android 平台已经内置电话,浏览器等众多应用,但是开发人员依然可以开发自己的应用来替代这些内置程序。这也造就了Android平台的灵活性和个性化。

5.1.2 Application Framework(应用程序框架层)

应用程序框架是开发Android应用程序的基础,这一层提供了大量的API供开发者使用,开发者可以使用框架层的 API 来实现自己的程序,并且通过这套框架,各种组件、服务都可以被开发者重复的利用。以下是对应用程序框架层的基本介绍。

1.Activity Manager(活动管理器)

管理系统中的Activity,比如Android的生命周期,activity task等。

2.Window Manager(窗口管理器)

管理所有的窗口程序。

3.Content Provider(内容提供器)

用于不同程序之前的数据分享等。

4.View System(视图系统)

构建应用程序的基本组件。

5.Notification Manager(通告管理器)

在状态栏显示自定义的提示信息。

6.Package Manager(包管理器)

管理Android系统内的程序。

7.Telephony Manager(电话管理器)

管理访问移动设备上的电话服务。

8.Resource Manager(资源管理器)

管理应用程序中使用的各种本地资源,如图片、布局文件、颜色文件等。

9.Location Manager(位置管理器)

提供位置服务。

10.XMPP Service(XMPP 服务)

提供Google Talk服务。

5.1.3 Libraries Android Runtime(库以及Android运行环境)

库和运行环境知识已经开始涉及底层了,这一层跟最上层的应用程序关系并不是很密切,所以,这里只会进行简单的介绍。大家大概了解一下即可。如果对这部分特别的感兴趣,则可以参考Android官方提供的API或者下载源代码学习。

Android包含一些C/C++库,这些库能被不同的组件使用,它们通过Android应用程序框架对开发者提供服务。以下是一些核心库(Libraries)。

(1)系统C库,一个从BSD继承来的标准C系统函数库(libc),它是专门为基于嵌入式Linux的设备制定的。

(2)媒体库(Media Framework),基于PacketVideo OpenCORE,该库支持多种常用的音视频格式回放和录制,同时支持静态图像文件。编码格式包括 MPEG4,H.264,MP3,AAC,AMR, JPG,PNG。

(3)Surface Manager,对显示子系统的管理,并且为多个应用程序提供2D和3D图层的无缝融合。

(4)LibWebCore,一个最新的Web浏览器引擎,用来支持Android浏览器和一个可嵌入的Web视图。

(5)SGL,底层的2D图形引擎。

(6)3D libraries,基于OpenGL ES1.0 APIs实现,该库可以使用硬件3D加速(如果可用),或者使用高度优化的3D软加速。

(7)FreeType,位图(bitmap)和矢量(vector)字体显示。

(8)SQLite,功能强大的轻型关系型数据库引擎。

运行时(Android Runtime):

(9)核心库(Core Libraries),该核心库提供了Java编程语言核心库的大多数功能。

(10)Dalvik虚拟机(Dalvik Virtual Machine),每个Android应用程序都在它自己的进程中运行,并拥有独立的 Dalvik 虚拟机实例。Dalvik 被设计成一个设备,可以同时高效地运行多个虚拟系统。Dalvik虚拟机执行(.dex)的Dalvik可执行文件,这种格式文件针对小内存使用作了优化。同时虚拟机是基于寄存器的,所有的类都经由Java编译器编译,然后通过SDK中的“dx”工具转换为dex格式,由虚拟机执行。

Dalvik虚拟机依赖于Linux内核的一些功能,例如,线程机制和底层内存管理机制。

5.1.4 Linux Kernel(Linux 内核)

Android是基于Linux 2.6内核,其核心系统服务如安全性、内存管理、进程管理、网路协议以及驱动模型都依赖于Linux内核。Linux内核同时也是作为硬件和软件栈之间的抽象层。

5.2 Android应用程序工程结构分析

5.2.1 应用程序工程结构组成分析

在基本了解了Android系统架构之后,我们接下来简单分析一下一个典型的Android项目工程是什么样子的。如图5-2所示。

结合图5-2,我们来大概分析一下项目里面的具体构成(从上至下)。

HelloWorld:就是整个Android项目的工程名,相信大家一看就懂。

src 文件夹:整个项目的源文件目录,图 5-2中的源文件就只有HelloWorldActivity.java。

gen 文件夹:这个文件夹下有两个文件,BuildConfig.java 以及R.java 文件。这两个文件都是系统自动生成的,BuildConfig.java 的作用是检查你的代码,并不断运行调试。R.java 文件则是对项目资源的全局索引(比如在下面将介绍到的res文件中添加了内容,那么R.java文件则会自动重新编译,同步更新,之后在项目中,你就可以通过R.java中的索引来正确找到对应的资源)。这两个文件在开发中,开发人员不必对其进行修改。

Android2.2:这是应用运行的Android库,如图5-2所示,项目用的是Android 2.2的库。

▲图5-2 Android项目工程结构

Android Dependencies:这个是Android项目的依赖包,在开发应用时,如果你需要引用第三方的包,则只需要在工程目录下新建libs文件夹(注意,是libs而不是lib)。然后将第三方jar包复制进去,eclipse会自动将这个jar包添加到Android Dependencies文件夹中,而不必手动去BuildPath。

assets文件夹:assets主要放置多媒体或其他不需要进行索引的资源文件,上面提到过res文件夹下放置文件时会在 R.java 中生成索引的,那么有些你觉得不必要索引的资源文件则可放置在assets文件夹中。

bin文件夹:这个文件夹主要存放编译后的一些资源信息,比如生成的项目apk文件等。

res文件夹:res下的drawable-hdpi,drawable-ldpi,drawable-mdpi,drawable-xhdpi文件夹主要用来存放图片类型资源,当然也可以存放与样式相关的XML文件,比如selector(这个后期在项目实战中会有讲到)。而这几个文件夹的命名也区分了它们的不同作用,hdpi结尾的,主要存放高分辨率图片,ldpi放置中等分辨率图片,mdpi放置低分辨率图片,xhdpi则是放置高清分辨率图片(比高分辨率更加清晰)。之所以不同的分辨率要放置在不同的文件夹中,是因为系统会根据手机或者平板设备自身的分辨率到不同的文件夹中寻找最合适的图片,以达到更好的显示效果。

res文件夹下的layout的文件夹则是用来放置XML格式的布局文件的。values文件夹存放字符串(strings.xml)、颜色(colors.xml)、数组(arrays.xml)资源等。值得注意的是,整个res文件夹下的内容改变,都会在上面介绍到的R.java文件中自动生成索引。

5.2.2 AndroidMainfest文件分析

AndroidManifest.xml是每一个Android应用程序必须拥有的全局配置文件,该文件描述了应用程序中用到的组件、权限、第三方引用等。比如我们需要的Activity、Service等组件都需要在该配置文件中配置。接下来我们分析一下该配置文件的基本配置元素。

<manifest>:该标签是AndroidManifest文件的根元素,它必须包含一个<application>元素,并指定xlmns、package属性。xlmns指定Android的命名空间,默认值为http://schemas.android.com/apk/res/android。package则是应用包名,也是一个应用进程的默认名称。在创建Android项目的时候,通常会让你填写一个包名,而你填写的那个包名默认就是这个package的属性值。另外还有常用的属性,versionCode,是给设备程序识别版本用的,必须是一个整数值,代表当前程序更新过多少次。versionName则是给用户查看版本的。

<uses-permisson>:该标签是用来指定权限的,在 Android 系统中,需要指定相应的权限才能使用相应的功能,例如,我们需要访问网络,则必须配置android.permisson.INTERNET。

<permisson>:该标签用来指定给<uses-permission>标签使用的具体权限。如果你的应用程序需要提供一些数据或者可调用的代码,你就可以使用该标签指定访问你程序的权限。

<instrumentation>:该标签声明了一个 Instrumentation 类,这个类能够监视应用程序与系统的交互,并且Instrumentation会先于应用程序中的其他组件被实例化。

<uses-sdk>:该标签用来声明应用程序中需要使用的SDK版本。

<uses-configuration>:该标签用来指明应用程序需要什么样的硬件和软件功能。例如,程序可能指定需要一个物理键盘或者特定的导航装置,比如轨迹球。这个规范就是用来避免安装到设备上的程序不能运行(因为,如果应用程序需要轨迹球才能工作,而你的设备没有轨迹球,那么安装了这个应用是无法工作的)。

<uses-feature>:声明程序需要用到的单一硬件或软件功能。Google Play就是通过检查程序Manifest文件中的<uses-feature>元素,然后根据用户的设备来决定显示或隐藏应用程序给用户。例如,某个程序需要蓝牙支持,但是你的设备不支持蓝牙,那么在Google Play中,这款应用就不会显示给你。

<uses-library>:指定了程序必须链接的共享库,该标签告诉系统将包含在库中的代码用加载器加载。

<supports-screens>:指定你应用程序所支持的屏幕大小。主要的属性有 android:resizeable(屏幕自适应),android:smallScreens(小屏),android:normalScreens(中屏),android:largeScreens(大屏)等。

<applicaiton>:该标签为应用程序配置的根元素,位于<manifest>标签下级。它包含了与应用相关的配置元素,常用的属性有,应用名android:label,应用图片android:icon等。

<activity>:该标签用来声明应用中用到的 Activity 组件,每一个程序中的 Activity 都必须在manifest文件中进行声明,否则系统识别不了Activity。常用的属性有android:name,Activity的对应类名。另外Activity还可以包含<intent-filter>标签。

<service>:该标签用来声明Service组件。主要属性有android:name:Service类名。

<receiver>:该标签为Broadcast Receiver组件的声明标签,用来定义一个具体的广播接收器。主要属性有android:name,具体的类名。

<provider>:该标签是Content Provider(内容提供者)的声明标签。主要属性有android:name,具体类名,android:authorities,对指定URL授予权限标识。

由于AndroidManifest配置文件中涉及到的标签和属性非常多,这里篇幅有限不能为大家一一讲解,所以简单讲解一下基本的标签后,我们再来新建一个 HelloEoe 的项目,并分析它的AndroidManifest文件,具体代码如下。

    <?xml version="1.0" encoding="utf-8"?>
    <manifest
    1xmlns:android="http://schemas.android.com/apk/res/android"
    2package="com.eoeAndroid.helloeoe"
    3android:versionCode="1"
    4android:versionName="1.0" >
    5<uses-sdk android:minSdkVersion="10" />
    6<application
    7  android:icon="@drawable/ic_launcher"
    8  android:label="@string/app_name" >
    9  <activity
    10   android:name=".HelloEoeActivity"
    11   android:label="@string/app_name" >
    12    <intent-filter>
    13     <action android:name="android.intent.action.MAIN" />
    14     <category android:name="android.intent.category.LAUNCHER" />
    15    </intent-filter>
    16   </activity>
    17 </application>
    </manifest>

代码解释

第1行:指定Android的命名空间。

第2行:指定package属性,com.eoeAndroid.helloeoe也是默认的进程名称。

第3行:给设备识别的版本号。

第4行:显示给用户的版本号。

第5行:指定当前最低Android版本为10。

第7行:代表当前应用程序使用的图标。

第8行:代表应用程序的名称。

第10行:指定具体的Activity名称。值得注意的是,原本我们是要写全路径的,但是这里为什么只写了.HelloEoeActivity呢?我们可以通俗理解为,这个路径跟上面manifest属性package是连在一起的,如果我们把 package 的值和.HelloEoeActivity 连起来,就成了 com.eoeAndroid.com. HelloEoeActivity,这样就是一个全路径了。

第12~15行:定义了一个Intent-filter,并且指定了一个action和category元素,这表明当前Activity是本应用的默认入口Activity,并且作为顶部程序显示在Launcher(Android系统中的程序列表)里。

5.3 本章小结

本章主要对Android系统的体系架构进行了简单的分析,让大家能够基本了解Android系统的构成,也为初学者提供了对Android进行深入研究的大致方向,最后又介绍了一个Android应用工程的组成,以及每个组成的意义。看完这一章,相信读者会对Android有一个大概的了解。从下一章开始,我们将讲解Android中的几个重要组件。后续章节都会有代码的加入,建议大家在看代码时,如果遇到某些代码和资源的放置问题,可以回头来看看这一章,这样才能更好地理解Android应用程序的构成以及如此设计的好处。