1.3.1 理解Android软件栈
图1-6 Android SDK软件栈详细结构 |
Android平台的核心是Linux内核版本2.6.29,它负责设备驱动程序、资源访问、电源管理和完成其他操作系统的职责。提供的设备驱动程序包括显示器、照相机、键盘、WiFi、闪存、音频和IPC(Inter-Process Communication,进程间通信)。尽管核心是Linux,但Android设备(比如T-Mobile G1或摩托罗拉Droid)上的绝大部分应用程序都是使用Java开发,通过Dalvik VM运行的。
我们看一下另一层,内核之上是许多C/C++库,比如OpenGL、WebKit、FreeType、SSL(Secure Sockets Layer,安全套接字层)、libc(C运行时库)、SQLite和媒体。基于BSD(Berkeley Software Distribution,伯克利软件套件)的系统C库针对嵌入式Linux设备进行了调优(大小约为原始大小的一半)。媒体库基于PacketVideo(http://www.packetvideo.com/)的OpenCORE。这些库负责录制和播放音频和视频格式的内容。一个名为Surface Manager的库控制对显示系统的访问,支持2D和3D。WebKit库负责浏览器支持,WebKit也是Google公司的Chrome和苹果公司的Safari使用的库。FreeType库负责字体支持。SQLite(http://www.sqlite.org/)是一个可在设备自身上使用的关系数据库。SQLite也是关系数据库的一项独立的开源成果,没有直接绑定到Android。适用于SQLite的工具也可用于Android数据库。
大多数应用程序框架都通过Dalvik VM访问这些核心库,Dalvik VM就像Android平台的入口。前面几节已经提到,Dalvik经过了优化,可以运行多个VM实例。访问这些核心库时,每个Java应用程序都会获得自己的VM实例。
Android Java API的主要库包括电话、资源、位置、UI、ContentProvider(数据)和包管理器(安装、安全等)。程序员使用此Java API开发最终用户应用程序。设备上的一些最终用户应用程序示例包括Home、Contacts、Phone、Browser等。
Android还支持Google公司一个名为Skia的自定义2D图形库,这个库是使用C和C++编写的。Skia也是GoogleChrome浏览器的核心组件。然而,Android中的3D API基于来自Khronos小组(http://www.khronos.org)的一种OpenGL ES实现。OpenGL ES包含OpenGL中面向嵌入式系统的子集。
从媒体角度讲,Android平台支持最常见的音频、视频和图像格式。从无线角度讲,Android拥有支持蓝牙、EDGE、3G、WiFi和GSM(Global System for Mobile Communication,全球移动通信系统)电话的API,具体取决于设备硬件。
1.3.2 Android应用程序架构
Activity Manager和Fragment Manager分别控制Activity和Fragment生命周期
View(视图)用来为Activity和Fragment创建界面
Notification Manager提供了一种一致的和非打断的机制来通知用户
Content Provider 让应用程序共享数据
Resources Manager 支持像字符串和图形这样的非代码资源的具体化
Intent 提供了一种在应用程序及组件之间传输数据的机制
1.3.3 Dalvik VM剖析
作为Android平台的一部分,Google公司花了大量时间思考针对低功耗手持设备的优化设计。与桌面设备相比,手持设备在内存和速度方面落后8~10年。它们的计算能力也有限,一个手持设备的总RAM可能只有64 MB,可供应用程序使用的空间可能只有20 MB。
说明 2008年年底发布的T-Mobile G1电话拥有192 MB RAM、一张1 GB的SD卡和528MHz Qualcomm MSM7201A处理器。摩托罗拉公司2009年年底发布的Droid拥有256 MB RAM、一张16 GB的microSD卡和550MHz Arm Cortex处理器。而戴尔公司最廉价的笔记本电脑都拥有2.1GHz双核处理器和4 GB RAM。
因此,手机的性能要求非常高,这需要手机设计人员优化一切要素。如果看一下Android中的包,将会看到它们完善而丰富。据Google公司介绍,即使使用经过优化的JVM,这些系统库也可能使用10 MB~20 MB RAM。
这些问题使Google公司在许多方面重新审视标准JVM实现。(Dan Bornstein对Google公司的这个JVM实现作出了重要贡献,他编写了Dalvik VM,Dalvik是冰岛一个小镇的名称。)首先,Dalvik VM获取生成的Java类文件,将它们组合为一个或多个Dalvik可执行文件(.dex)。它重用多个类文件中的重复信息,与未压缩的传统.jar文件相比,有效地将空间需求减少了一半。例如,Android中Web浏览器的.dex文件约为200 K,而对应的未压缩的.jar版本约为500 K。闹钟应用程序的.dex文件约为50 K,大约是其.jar版本的一半。
其次,Google公司在Dalvik VM中对垃圾收集进行了调优,但它在早期版本中选择了删除即时( Just-In-Time,JIT)编译器。2.0版的代码库似乎拥有JIT编译器的必要源代码,但也未在最终版中启用它。预计在未来的版本中将启用即时编译器。该公司支持这一选择是因为,Android的许多核心库,包括图形库,都是使用C和C++实现的。例如,Java图形API实际上是围绕本地代码的瘦包装器类,使用了JNI(Java Native Interface,Java本地接口)。类似地,Android提供了一个优化的C本地库来访问SQLite数据库,但这个库使用一种更高级的Java API封装。由于大部分核心代码都是使用C和C++编写的,所以Google公司推断JIT编译的影响不会很大。
最后,Dalvik VM使用了一种不同的汇编代码生成方法,它使用寄存器而不是栈作为主要的数据存储单元。Google公司希望这样能将指令减少到30%。应当指出,采用Dalvik VM的一个结果是,Android中最终的可执行程序代码不是基于Java字节码,而是基于.dex文件。这意味着无法直接执行Java字节码,必须首先得到Java类文件,然后将它们转换为可链接的.dex文件。
这种对性能的狂热追求还扩展到了Android SDK的其他部分。例如,Android SDK大量使用XML来定义UI布局。然而,所有XML数据必须编译为二进制文件,然后才能将这些文件存储在设备上。Android提供了一些专门的机制来使用XML数据。