書名: Android游戲開發(fā)技術(shù)實戰(zhàn)詳解作者名: 褚尚軍 張加春編著本章字數(shù): 2031字更新時間: 2018-12-30 05:33:13
2.3 Android系統(tǒng)架構(gòu)剖析
“剖析”二字有“解剖分析”之意,是指對一個人或一件事做深入的分析,讓別人了解這個人或明白事情的來龍去脈。學習Android之路是一條不平坦的路,需要付出一定的時間和精力。為了更加深入理解Android的精髓,很有必要了解Android的系統(tǒng)架構(gòu),了解它的組成。這樣才能知道Android究竟能干什么、開發(fā)人員所要學的是什么。
2.3.1 Android體系結(jié)構(gòu)介紹
Android是一個移動設(shè)備的開發(fā)平臺,其軟件層次結(jié)構(gòu)包括操作系統(tǒng)(OS)、中間件(MiddleWare)和應用程序(Application)。根據(jù)Android的軟件框圖,其軟件層次結(jié)構(gòu)自下而上可以分為以下4層。
(1)操作系統(tǒng)層(OS)
(2)各種庫(Libraries)和Android運行環(huán)境(RunTime)
(3)應用程序框架(Application Framework)
(4)應用程序(Application)
上述各層的具體結(jié)構(gòu)如圖2-19所示。

圖2-19 Android操作系統(tǒng)的組件結(jié)構(gòu)圖
1. 操作系統(tǒng)層(OS)——底層
因為Android源于Linux,使用了Linux內(nèi)核,所以Android使用Linux 2.6作為操作系統(tǒng)。Linux 2.6是一種標準的技術(shù),Linux也是一個開放的操作系統(tǒng)。Android對操作系統(tǒng)的使用包括核心和驅(qū)動程序兩部分,Android的Linux核心為標準的Linux 2.6內(nèi)核,Android更多的是需要一些與移動設(shè)備相關(guān)的驅(qū)動程序。主要的驅(qū)動如下。
· 顯示驅(qū)動(Display Driver):基于Linux的幀緩沖(Frame Buffer)驅(qū)動;
· Flash內(nèi)存驅(qū)動(Flash Memory Driver):基于MTD的Flash驅(qū)動程序;
· 相機驅(qū)動(Camera Driver):基于Linux的v4l(Video for Linux)驅(qū)動;
· 音頻驅(qū)動(Audio Driver):基于ALSA(Advanced Linux Sound Architecture,高級Linux聲音體系)驅(qū)動;
· Wi-Fi驅(qū)動(Wi-Fi Driver):基于IEEE 802.11標準的驅(qū)動程序;
· 鍵盤驅(qū)動(KeyBoard Driver):作為輸入設(shè)備的鍵盤驅(qū)動;
· 藍牙驅(qū)動(Bluetooth Driver):基于IEEE 802.15.1標準的無線傳輸技術(shù);
· Binder IPC驅(qū)動:Android中一個特殊的驅(qū)動程序,具有單獨的設(shè)備節(jié)點,提供進程間通信的功能;
· Power Management(能源管理):管理電池電量等信息。
2. 各種庫(Libraries)和Android運行環(huán)境(RunTime)——中間層
本層次對應一般嵌入式系統(tǒng),相當于中間件層次。本層次分成兩個部分,一個是各種庫,另一個是Android運行環(huán)境。本層的內(nèi)容大多是使用C和C++實現(xiàn)的。其中包含的各種庫如下所示。
· C庫:C語言的標準庫,也是系統(tǒng)中的底層庫,C庫是通過Linux的系統(tǒng)調(diào)用來實現(xiàn)的;
·多媒體框架(MediaFramework):這部分內(nèi)容是Android多媒體的核心部分,是基于PacketVideo(即PV)的OpenCORE,從功能上本庫一共分為兩大部分,一部分是音頻、視頻的回放(PlayBack),另一部分則是音、視頻的記錄(Recorder);
· SGL:2D圖像引擎;
· SSL:即Secure Socket Layer,位于TCP/IP協(xié)議與各種應用層協(xié)議之間,為數(shù)據(jù)通信提供安全支持;
· OpenGL ES 1.0:提供了對3D的支持;
· 界面管理工具(Surface Management):提供了管理顯示子系統(tǒng)等功能;
· SQLite:一個通用的嵌入式數(shù)據(jù)庫;
· WebKit:網(wǎng)絡(luò)瀏覽器的核心;
· FreeType:位圖和矢量字體的功能。
Android的各種庫一般是以系統(tǒng)中間件的形式提供的,它們均有的一個顯著特點,就是與移動設(shè)備平臺的應用密切相關(guān)。
Android運行環(huán)境主要是指虛擬機技術(shù)——Dalvik。Dalvik虛擬機和一般Java虛擬機(Java VM)不同,它執(zhí)行的不是Java標準的字節(jié)碼(Bytecode),而是在Dalvik可以執(zhí)行的格式文件(.dex)。在執(zhí)行的過程中,每一個應用程序即一個進程(Linux的一個Process)。二者最大的區(qū)別在于Java VM是基于棧的虛擬機(Stack-based),而Dalvik是基于寄存器的虛擬機(Register-based)。顯然,后者最大的好處在于可以根據(jù)硬件實現(xiàn)更大的優(yōu)化,這更符合移動設(shè)備的特點。
3. 應用程序(Application)
Android的應用程序主要是用戶界面(User Interface)方面的,通常用Java語言編寫,其中還可以包含各種資源文件(放置在res目錄中)。Java程序及相關(guān)資源經(jīng)過編譯后,將生成一個APK包。Android本身提供了主屏幕(Home)、聯(lián)系人(Contact)、電話(Phone)、瀏覽器(Browser)等眾多的核心應用。同時,應用程序的開發(fā)者還可以使用應用程序框架層的API實現(xiàn)自己的程序。這也是Android開源巨大潛力的體現(xiàn)。
4. 應用程序框架(Application Framework)
Android的應用程序框架為應用程序?qū)拥拈_發(fā)者提供API,它實際上是一個應用程序的框架。由于上層的應用程序是以Java構(gòu)建的,因此本層次提供的首先包含了UI程序中所需要的各種控件。例如,Views(視圖組件),其中又包括了List(列表)、Grid(柵格)、Text Box(文本框)、Button(按鈕)等,甚至一個嵌入式的Web瀏覽器。
一個基本的Android應用程序可以利用應用程序框架中的以下五個部分。
· Activity(活動)
· Broadcast Intent Receiver(廣播意圖接收者)
· Service(服務)
· Content Provider(內(nèi)容提供者)
· Intent and Intent Filter(意圖和意圖過濾器)
本書的主要目的是講解Android游戲開發(fā)知識,介紹的是應用程序(Application)方面的知識。這些知識都是與Java開發(fā)相關(guān)的,當然也還需要掌握一些其他層的相關(guān)知識,如底層的內(nèi)核和驅(qū)動等知識。
2.3.2 Android應用工程文件組成
介紹完Android的整體結(jié)構(gòu)之后,接下來就介紹Android工程文件的組成。因為Android游戲項目是用Eclipse創(chuàng)建的工程,所以很有必要了解一個Android工程文件的結(jié)構(gòu)。
在Eclipse中,一個基本的Android項目的目錄結(jié)構(gòu)如圖2-20所示。

圖2-20 Android應用工程文件組成
1. src目錄——程序文件
在這里保存了程序員直接編寫的程序文件。和一般的Java項目一樣,“src”目錄下保存的是項目的所有包及源文件(.java),“res”目錄下包含了項目中的所有資源,例如,程序圖標(drawable)、布局文件(layout)和常量(values)等。不同的是,在Java項目中沒有“gen”目錄,也沒有每個Android項目都必須有的AndroidManfest.xml文件。
“.java”格式文件是在建立項目時自動生成的,這個文件是只讀模式,不能更改。R.java文件是定義該項目所有資源的索引文件。先來看看HelloAndroid項目的R.java文件,如下面的代碼:
package com.yarin.Android.HelloAndroid; public final class R { public static final class attr { } public static final class drawable { public static final int icon=0x7f020000; } public static final class layout { public static final int main=0x7f030000; } public static final class string { public static final int app_name=0x7f040001; public static final int hello=0x7f040000; } }
從上述代碼中,可以看到定義了很多常量,并且會發(fā)現(xiàn)這些常量的名字都與res文件夾中的文件名相同,這再次證明.java文件中存儲的是該項目所有資源的索引。有了這個文件,在程序中使用資源將變得更加方便,可以很快地找到要使用的資源,由于這個文件不能被手動編輯,所以當在項目中加入了新的資源時,只需要刷新一下該項目,.java文件便自動生成了所有資源的索引。
2. AndroidManfest.xml文件——設(shè)置文件
文件AndroidManfest.xml是一個控制文件,在里面包含了該項目中使用的Activity、Service、Receiver,看下面“HelloAndroid”項目中的AndroidManfest.xml文件。
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.yarin.Android.HelloAndroid" android:versionCode="1" android:versionName="1.0"> <application android:icon="@drawable/icon" android:label="@string/app_name"> <activity android:name=".HelloAndroid" android:label="@string/app_name"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> <uses-sdk android:minSdkVersion="5" /> </manifest>
在上述代碼中,intent-filters描述了Activity啟動的位置和時間。每當一個Activity(或者操作系統(tǒng))要執(zhí)行一個操作時,它將創(chuàng)建出一個Intent的對象,這個Intent對象能承載的信息可描述你想做什么、你想處理什么數(shù)據(jù)與數(shù)據(jù)的類型,以及一些其他信息。而Android能夠?qū)⒚總€intent-filter數(shù)據(jù)進行比較,找到最合適Activity來處理調(diào)用者所指定的數(shù)據(jù)和操作。下面來仔細分析AndroidManfest.xml文件,如表2-1所示。
表2-1 AndroidManfest.xml文件分析

3. 常量的定義文件——露臉的文件
下面看看資源文件中一些常量的定義,如String.xml,如下面的代碼:
<?xml version="1.0" encoding="utf-8"?> <resources> <string name="hello">Hello World, HelloAndroid!</string> <string name="app_name">HelloAndroid</string> </resources>
上述代碼很簡單,就定義了兩個字符串資源,請不要小看上面的幾行代碼。它們的內(nèi)容很“露臉”,里面的字符直接顯示在手機屏幕中,就像動態(tài)網(wǎng)站中的HTML一樣。
在Android中還有一個露臉的文件,那就是布局(layout)文件,這個文件一般位于“res\layout\main.xml”。雖然它里面的字符沒有“露臉”,但是里面的代碼能夠生成一個顯示界面,這個可以顯示人名和圖片的界面就“露臉”了。例如:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/hello" /> </LinearLayout>
在上述代碼中,有以下幾個布局和參數(shù)。
· < LinearLayout></LinearLayout>:線性版面配置,在這個標簽中,所有元件都是按自上而下的順序排列而成的。
· android:orientation:表示這個介質(zhì)的版面配置方式是“從上到下垂直地排列其內(nèi)部的視圖”。
· android:layout_width:定義當前視圖在屏幕上所占的寬度,fill_parent即填充整個屏幕。
· android:layout_height:定義當前視圖在屏幕上所占的高度,fill_parent即填充整個屏幕。
· wrap_content:隨著文字數(shù)量的不同而改變這個視圖的寬度或高度。
在上述布局代碼中,使用了一個TextView來配置文本標簽Widget(構(gòu)件),其中設(shè)置的屬性android:layout_width為整個屏幕的寬度,android:layout_height可以根據(jù)文字來改變高度,而android:text則設(shè)置了這個TextView要顯示的文字內(nèi)容,這里引用了@string中的“hello”字符串,即String.xml文件中的“hello”所代表的字符串資源。“hello”字符串的內(nèi)容“Hello World, HelloAndroid!”就是在HelloAndroid項目運行時看到的字符串。
注意:上面介紹的只是主要文件,在項目中需要自行編寫。在項目中還有很多其他的文件,這些文件很少需要編寫,所以在此就不進行講解了。
2.3.3 應用程序的生命周期
作為一個程序,也如同自然界的生物一樣,有自己的生命周期。開發(fā)一個程序的目的是為了完成一項功能,如銀行中計算加息的軟件。每當一個用戶去柜臺辦理取款業(yè)務時,銀行工作人員便啟動了這個軟件,當用這個軟件完成利息計算時,這個軟件當前的任務就完成了,此時就需要結(jié)束。肯定有讀者會提出疑問:“生生死死”多麻煩,就讓這個程序一直是“活著”的狀態(tài),一個用戶辦理完取款業(yè)務后,繼續(xù)等待下一個用戶辦理取款業(yè)務,這樣豈不是更方便?但是很不幸,不能這樣做。原因是計算機的處理性能是一定的,計算機能夠很輕松地完成與一個人、兩個人或三個人相關(guān)的存取款業(yè)務,但是我們開發(fā)的程序軟件需要每天處理成千上萬個存取款業(yè)務,如果每個任務都一直活著,一臺有限配置的計算機能承受得了嗎?
由此可見,應用程序的生命周期就是一個程序的存活時間,即在什么時間內(nèi)有效。Android是一構(gòu)建在Linux之上的開源移動開發(fā)平臺,在Android中,大多數(shù)情況下每個程序都是在各自獨立的Linux進程中運行的。當一個程序或其某些部分被請求時,它的進程就“出生”了;當這個程序沒有必要再運行下去且系統(tǒng)需要回收這個進程的內(nèi)存用于其他程序時,這個進程就“死亡”了。可以看出,Android程序的生命周期是由系統(tǒng)控制而非程序自身控制的。這和編寫桌面應用程序時的思維有一些不同,一個桌面應用程序的進程也是在其他進程或用戶請求時被創(chuàng)建,但是往往是在程序自身收到關(guān)閉請求后執(zhí)行一個特定的動作而結(jié)束進程。要想做好某種類型的程序或者某種平臺下的程序的開發(fā),最關(guān)鍵的就是要弄清楚這種類型的程序或整個平臺下的程序的一般工作模式,并且要做到熟記在心。在Android系統(tǒng)中,程序的生命周期控制就屬于這個范疇,開發(fā)者必須理解不同的應用程序組件,尤其是Activity、Service和Intent Receiver,了解這些組件是如何影響應用程序的生命周期的。如果不正確地使用這些組件,可能會導致系統(tǒng)終止正在執(zhí)行重要任務的應用程序進程。
一個常見的進程生命周期漏洞的例子是Intent Receiver(意圖接收器),當Intent Receiver在onReceive方法中接收到一個Intent(意圖)時,它會啟動一個線程,然后返回。一旦返回,系統(tǒng)將認為Intent Receiver不再處于活動狀態(tài),因而Intent Receiver所在的進程也就不再有用了(除非該進程中還有其他的組件處于活動狀態(tài))。因此,系統(tǒng)可能會在任意時刻終止該進程以回收占用的內(nèi)存。這樣進程中創(chuàng)建出的那個線程也將被終止。解決這個問題的方法是從Intent Receiver中啟動一個服務,讓系統(tǒng)知道進程中還有處于活動狀態(tài)的工作。為了使系統(tǒng)能夠正確決定在內(nèi)存不足時應該終止哪個進程,Android應根據(jù)每個進程中運行的組件及組件的狀態(tài)把進程放入一個“Importance Hierarchy(重要性分級)”中。
進程的類型多種多樣,按照重要程度主要有如下幾類進程。
1. 前臺進程(Foreground)
前臺進程是看得見的,與用戶當前正在做的事情密切相關(guān)的。不同的應用程序組件能夠通過不同的方法將它的宿主進程移到前臺。在如下的任何一個條件下“①進程正在屏幕的最前端運行一個與用戶交互的活動(Activity),它的onResume方法被調(diào)用;②進程有一正在運行的Intent Receiver(它的IntentReceiver.onReceive方法正在執(zhí)行);③進程有一個服務(Service),并且在服務的某個回調(diào)函數(shù)(Service.onCreate、Service.onStart或Service.onDestroy)內(nèi)有正在執(zhí)行的代碼”,系統(tǒng)將把進程移動到前臺。
2. 可見進程(Visible)
可見進程也是可見的,它有一個可以被用戶從屏幕上看到的活動,但不在前臺(它的onPause方法被調(diào)用)。例如,前臺的活動是一個對話框,以前的活動就隱藏在對話框之后,就會出現(xiàn)這種進程。可見進程非常重要,一般不允許被終止,除非是為了保證前臺進程的運行而不得不終止它。
3. 服務進程(Service)
服務進程是無法看見的,擁有一個已經(jīng)用startService方法啟動的服務。雖然用戶無法直接看到這些進程,但它們做的事情卻是用戶所關(guān)心的(如后臺MP3回放或后臺網(wǎng)絡(luò)數(shù)據(jù)的上傳與下載)。因此,系統(tǒng)將一直運行這些進程,除非內(nèi)存不足以維持所有的前臺進程和可見進程。
4. 后臺進程(Background)
后臺進程也是看不見的,只有打開之后才能看見。例如,迅雷下載,可以將其最小化,雖然桌面上看不見了,但是它一直在進行下載的工作。擁有一個當前用戶看不到的活動(它的onStop方法被調(diào)用)。這些進程對用戶體驗沒有直接的影響。如果它們正確執(zhí)行了活動生命周期,系統(tǒng)可以在任意時刻終止該進程以回收內(nèi)存,并提供給前面三種類型的進程使用。系統(tǒng)中通常有很多這樣的進程在運行,因此要將這些進程保存在LRU列表中,以確保當內(nèi)存不足時用戶最近看到的進程最后一個被終止。
5. 空進程(Empty)
不擁有任何活動的應用程序組件的進程。保留這種進程的唯一原因是在下次應用程序的某個組件需要運行時,不需要重新創(chuàng)建進程,這樣可以提高啟動速度。
系統(tǒng)將以進程中當前處于活動狀態(tài)組件的重要程度為基礎(chǔ)對進程進行分類。進程的優(yōu)先級可能也會根據(jù)該進程與其他進程的依賴關(guān)系而增長。例如,進程A通過在進程B中設(shè)置Context.BIND_AUTO_CREATE標記或使用ContentProvider被綁定到一個服務(Service),那么進程B在分類時至少要被看成與進程A同等重要。
例如,Activity的狀態(tài)轉(zhuǎn)換圖如圖2-21所示。

圖2-21 Activity狀態(tài)轉(zhuǎn)換圖
圖2-21所示的狀態(tài)的變化是由Android內(nèi)存管理器決定的,Android會首先關(guān)閉那些包含Inactive Activity的應用程序,再關(guān)閉Stopped狀態(tài)的程序。在極端情況下,會移除Paused狀態(tài)的程序。
- 物聯(lián)網(wǎng)之魂:物聯(lián)網(wǎng)協(xié)議與物聯(lián)網(wǎng)操作系統(tǒng)
- Learning QGIS 2.0
- 萬物互聯(lián):蜂窩物聯(lián)網(wǎng)組網(wǎng)技術(shù)詳解
- 網(wǎng)絡(luò)安全技術(shù)與解決方案(修訂版)
- 面向物聯(lián)網(wǎng)的嵌入式系統(tǒng)開發(fā):基于CC2530和STM32微處理器
- 大話社交網(wǎng)絡(luò)
- Yii Application Development Cookbook(Second Edition)
- 物聯(lián)網(wǎng)技術(shù)與應用
- Building RESTful Web services with Go
- TD-LTE無線網(wǎng)絡(luò)規(guī)劃與設(shè)計
- Getting Started with nopCommerce
- AIoT應用開發(fā)與實踐
- Learning Node.js Development
- 5G時代的大數(shù)據(jù)技術(shù)架構(gòu)和關(guān)鍵技術(shù)詳解
- Selenium WebDriver 3 Practical Guide