天天看點

《Android多媒體應用開發實戰詳解:圖像、音頻、視訊、2D和3D》——2.3節簡析Android安裝檔案

本節書摘來自異步社群《android多媒體應用開發實戰詳解:圖像、音頻、視訊、2d和3d》一書中的第2章,第2.3節簡析android安裝檔案,作者 王石磊 , 吳峥,更多章節内容可以通路雲栖社群“異步社群”公衆号檢視

2.3 android系統架構

android多媒體應用開發實戰詳解:圖像、音頻、視訊、2d和3d

本節将進一步分解android應用程式,詳細剖析android應用程式的核心構成部分,為讀者學習本書後面多媒體開發應用知識打下基礎。

2.3.1 android體系結構介紹

android作為一個移動裝置的平台,其軟體層次結構包括作業系統(os)、中間件(middleware)和應用程式(application)。根據android的軟體框圖,其軟體層次結構自下而上分為以下4層。

(1)作業系統層(os)

(2)各種庫(libraries)和android 運作環境(runtime)

(3)應用程式架構(application framework)

(4)應用程式(application)

上述各個層的具體結構如圖2-19所示。

《Android多媒體應用開發實戰詳解:圖像、音頻、視訊、2D和3D》——2.3節簡析Android安裝檔案

1.作業系統層(os)

android使用linux 2.6作為作業系統,linux 2.6是一種标準的技術,linux也是一個開放的作業系統。android對作業系統的使用包括核心和驅動程式兩部分,android的linux核心為标準的linux 2.6核心,android更多的是需要一些與移動裝置相關的驅動程式。主要的驅動如下所示。

顯示驅動(display driver):常基于linux的幀緩沖(frame buffer)驅動。

flash記憶體驅動(flash memory driver):是基于mtd的flash驅動程式。

照相機驅動(camera driver):常基于linux的v4l(video for )驅動。

音頻驅動(audio driver):常基于alsa(advanced linux sound architecture,進階linux聲音體系)驅動。

wifi驅動(camera driver):基于ieee 802.11标準的驅動程式。

鍵盤驅動(keyboard driver):作為輸入裝置的鍵盤驅動。

藍牙驅動(bluetooth driver):基于ieee 802.15.1标準的無線傳輸技術。

binder ipc驅動:一個特殊的驅動程式,具有單獨的裝置節點,提供程序間通信的功能。

power management(能源管理):管理電池電量等資訊。

2.各種庫(libraries)和android 運作環境(runtime)

本層對應一般嵌入式系統,相當于中間件層次。android的本層分成兩個部分,一個是各種庫,另一個是android 運作環境。本層的内容大多是使用c和c++實作的。其中包含的各種庫如下所示。

c庫:c語言的标準庫,也是系統中一個最為底層的庫,c庫是通過linux的系統調用來實作。

多媒體架構(mediaframeword):這部分内容是android多媒體的核心部分,基于packetvideo(即pv)的opencore,從功能上看,本庫一共分為兩大部分,一部分是音頻、視訊的回放(playback),另一部分則是音、視訊的紀錄(recorder)。

sgl:2d圖形引擎。

ssl:即secure socket layer,位于tcp/ip協定與各種應用層協定之間,為資料通信提供安全支援。

opengl es 1.0:提供了對3d的支援。

界面管理工具(surface management):提供了管理顯示子系統等功能。

sqlite:一個通用的嵌入式資料庫。

webkit:網絡浏覽器的核心。

freetype:位圖和矢量字型的功能。

android的各種庫一般是以系統中間件的形式提供的,它們均有一個顯著特點,就是與移動裝置平台的應用密切相關。

android運作環境主要是指虛拟機技術——dalvik。dalvik虛拟機和一般java虛拟機(java vm)不同,它執行的不是java标準的位元組碼(bytecode),而是dalvik可執行格式(.dex)中的執行檔案。在執行的過程中,每一個應用程式即是一個程序(linux的一個process)。二者最大的差別在于,java vm是基于棧的虛拟機(stack-based),而dalvik是基于寄存器的虛拟機(register-based)。顯然,後者最大的好處在于,可以根據硬體實作更大的優化,這更适合移動裝置的特點。

3.應用程式(application)

android的應用程式主要是使用者界面(user interface)方面的,通常用java語言編寫,其中還可以包含各種資源檔案(放置在res目錄中),java程式及相關資源經過編譯後,将生成一個apk包。android本身提供了主螢幕(home)、聯系人(contact)、電話(phone)和浏覽器(browers)等衆多的核心應用。同時應用程式的開發者還可以使用應用程式架構層的api實作自己的程式。這也是android開源的巨大潛力的展現。

4.應用程式架構(application framework)

android的應用程式架構為應用程式層的開發者提供api,它實際上是一個應用程式的架構。由于上層的應用程式是以java建構的,是以,本層提供的首先包含了ui程式中所需要的各種控件,例如,views(視圖元件),其中又包括了list(清單),grid(栅格),text box(文本框)和button(按鈕)等。甚至一個嵌入式的web浏覽器。

一個基本的andoid應用程式可以利用應用程式架構中的以下5個部分。

activity(活動)。

broadcast intent receiver(廣播意圖接收者)。

service(服務)。

content provider(内容提供者)。

intent and intent filter(意圖和意圖過濾器)。

2.3.2 android應用工程檔案組成

android的應用工程檔案主要由以下部分組成。

src檔案:項目源檔案都儲存在這個目錄裡面。

r.java檔案:這個檔案是eclipse自動生成的,應用開發者不需要修改裡邊的内容。

android library:這個是應用運作的android庫。

assets目錄:裡面主要放置多媒體等一些檔案。

res目錄:裡面主要放置應用用到的資源檔案。

drawable目錄:主要放置應用用到的圖檔資源。

layout目錄:主要放置用到的布局檔案。這些布局檔案都是xml檔案。

values目錄:主要放置字元串(strings.xml)、顔色(colors.xml)、數組(arrays.xml)。

androidmanifest.xml:相當于應用的配置檔案。在這個檔案裡邊,必須聲明應用的名稱,應用所用到的activity、service和receiver 等。

在eclipse中,一個基本的android項目的目錄結構如圖2-20所示。

《Android多媒體應用開發實戰詳解:圖像、音頻、視訊、2D和3D》——2.3節簡析Android安裝檔案

1.src目錄

與一般的java項目一樣,“src”目錄下儲存的是項目的所有包及源檔案(.java),“res”目錄下包含了項目中的所有資源。例如,程式圖示(drawable)、布局檔案(layout)和常量(values)等。不同的是,在java項目中沒有“gen”目錄,也沒有每個android項目都必須有的androidmanfest.xml檔案。

“.java”格式檔案是在建立項目時自動生成的,這個檔案是隻讀模式,不能更改。r.java檔案是定義該項目所有資源的索引檔案。先來看看helloandroid項目的r.java檔案,代碼如下所示:

從上述代碼中可以看到定義了很多常量,并且會發現這些常量的名字都與res檔案夾中的檔案名相同,這再次證明.java檔案中所存儲的是該項目所有資源的索引。有了這個檔案,在程式中使用資源将變得更加友善,可以很快地找到要使用的資源,由于這個檔案不能被手動編輯,是以當在項目中加入了新的資源時,隻需要重新整理一下該項目,.java檔案便自動生成了所有資源的索引。

2.androidmanfest.xml檔案

在檔案androidmanfest.xml中包含了該項目中所使用的activity、service、receiver,看下面“helloandroid”項目中的androidmanfest.xml檔案。

在上述代碼中,intent-filters描述了activity啟動的位置和時間。每當一個activity(或者作業系統)要執行一個操作時,它将建立出一個intent的對象,這個intent對象能承載的資訊可描述出你想做什麼,你想處理什麼資料,資料的類型,以及一些其他資訊。而android則會和每個application所暴露的intent-filter資料進行比較,找到最合适activity來處理調用者所指定的資料和操作。下面我們來仔細分析androidmanfest.xml檔案,如表2-1所示。

《Android多媒體應用開發實戰詳解:圖像、音頻、視訊、2D和3D》——2.3節簡析Android安裝檔案

3.常量的定義檔案

下面看下資源檔案中一些常量的定義,如string.xml,例如下面的代碼:

上述代碼很簡單,就定義了兩個字元串資源。

接下來分析helloandroid項目的布局檔案(layout),首先打開檔案“reslayoutmain.xml”,其代碼如下所示。

在上述代碼中,有以下幾個布局和參數。

< linearlayout>:線性版面配置,在這個标簽中,所有元件都是按由上到下的排隊排成的。

android:orientation:表示這個媒體的版面配置方式是從上到下垂直地排列其内部的視圖。

android:layout_width:定義目前視圖在螢幕上所占的寬度,fill_parent即填充整個螢幕。

android:layout_height:定義目前視圖在螢幕上所占的高度,fill_parent即填充整個螢幕。

wrap_content:随着文字欄位的不同而改變這個視圖的寬度或高度。

在上述布局代碼中,使用了一個textview來配置文本标簽widget(構件),其中設定的屬性android:layout_width為整個螢幕的寬度,android:layout_height可以根據文字來改變高度,而android:text則設定了這個textview要顯示的文字内容,這裡引用了@string中的hello字元串,即string.xml檔案中的hello所代表的字元串資源。hello字元串的内容“hello world, helloandroid!”這就是在helloandroid項目運作時看到的字元串。

注意

上面介紹的檔案隻是主要檔案,在項目中需要我們自行編寫。在項目中還有很多其他的檔案,那些檔案好的需要我們編寫,是以在此就不進行講解了。

2.3.3 應用程式的生命周期

程式也如同自然界的生物一樣,有自己的生命周期。應用程式的生命周期即程式的存活時間,即在啥時間内有效。android是建構在linux之上的開源移動開發平台,在android中,多數情況下每個程式都是在各自獨立的linux 程序中運作的。當一個程式或其某些部分被請求時,它的程序就“出生”了。當這個程式沒有必要再運作下去且系統需要回收這個程序的記憶體用于其他程式時,這個程序就“死亡”了。可以看出,android 程式的生命周期是由系統控制而非程式自身直接控制的。這和我們編寫桌面應用程式時的思維有一些不同,一個桌面應用程式的程序也是在其他程序或使用者請求時被建立,但是往往是在程式自身收到關閉請求後執行一個特定的動作(如從main函數中傳回)而導緻程序結束的。要想做好某種類型的程式或者某種平台下程式的開發,最關鍵的就是要弄清楚這種類型的程式或整個平台下的程式的一般工作模式,并熟記在心。在android中,程式的生命周期控制就是屬于這個範疇。

開發者必須了解不同的應用程式元件,尤其是activity、service和intent receiver。了解這些元件是如何影響應用程式的生命周期的,這非常重要。如果不正确地使用這些元件,可能會導緻系統終止正在執行重要任務的應用程式程序。

一個常見的程序生命周期漏洞的例子是intent receiver(意圖接收器),當intent receiver在onreceive方法中接收到一個intent(意圖)時,它會啟動一個線程,然後傳回。一旦傳回,系統将認為intent receiver不再處于活動狀态,因而intent receiver所在的程序也就不再有用了(除非該程序中還有其他的元件處于活動狀态)。是以,系統可能會在任意時刻終止該程序以回收占有的記憶體。這樣程序中建立出的那個線程也将被終止。解決這個問題的方法是從intent receiver中啟動一個服務,讓系統知道程序中還有處于活動狀态的工作。為了使系統能夠正确決定在記憶體不足時應該終止哪個程序,android 根據每個程序中運作的元件及元件的狀态把程序放入一個“importance hierarchy(重要性分級)”中。程序的類型按重要程度排序。

1.前台程序(foreground)

與使用者目前正在做的事情密切相關。不同的應用程式元件能夠通過不同的方法将它的宿主程序移到前台。在如下的任何一個條件下:程序正在螢幕的最前端運作一個與使用者互動的活動(activity),它的onresume方法被調用;或程序有一正在運作的intent receiver(它的intentreceiver.onreceive方法正在執行);或程序有一個服務(service),并且在服務的某個回調函數(service.oncreate、 service.onstart或 service.ondestroy)内有正在執行的代碼,系統将把程序移動到前台。

2.可見程序(visible)

它有一個可以被使用者從螢幕上看到的活動,但不在前台(它的onpause方法被調用)。例如,如果前台的活動是一個對話框,以前的活動就隐藏在對話框之後,就會出現這種程序。可見程序非常重要,一般不允許被終止,除非是了保證前台程序的運作而不得不終止它。

3.服務程序(srvice)

擁有一個已經用startservice方法啟動的服務。雖然使用者無法直接看到這些程序,但它們做的事情卻是使用者所關心的(如背景mp3回放或背景網絡資料的上傳、下載下傳)。是以,系統将一直運作這些程序,除非記憶體不足以維持所有的前台程序和可見程序。

4.背景程序(background)

擁有一個目前使用者看不到的活動(它的onstop方法被調用)。這些程序對使用者體驗沒有直接的影響。如果它們正确執行了活動生命周期,系統可以在任意時刻終止該程序以回收記憶體,并提供給前面3種類型的程序使用。系統中通常有很多這樣的程序在運作,是以要将這些程序儲存在lru 清單中,以確定當記憶體不足時使用者最近看到的程序最後一個被終止。

5.空程序(empty)

不擁有任何活動的應用程式元件的程序。保留這種程序的惟一原因是,在下次應用程式的某個元件需要運作時,不需要重新建立程序,這樣可以提高啟動速度。

系統将以程序中目前處于活動狀态元件的重要程度為基礎對程序進行分類。程序的優先級可能也會根據該程序與其他程序的依賴關系而增長。例如,如果程序a 通過在程序b中設定context.bind_auto_create标記或使用contentprovider被綁定到一個服務(service),那麼程序b在分類時至少要被看成與程序a同等重要。

例如activity的狀态轉換圖如圖2-21所示。

《Android多媒體應用開發實戰詳解:圖像、音頻、視訊、2D和3D》——2.3節簡析Android安裝檔案

圖2-21所示狀态的變化是由android記憶體管理器決定的,android會首先關閉那些包含inactive activity的應用程式,然後關閉stopped狀态的程式。在極端情況下,會移除paused狀态的程式。