首先枫浙,簡(jiǎn)單介紹一下Android的體系結(jié)構(gòu)
LINUX KERNEL:Linux核心语泽,Android系統(tǒng)是基于Linux系統(tǒng)修改過(guò)來(lái)的徐勃,Android底層都是Linux的東西窒百,大多都是操作硬件的一些驅(qū)動(dòng)熟丸,如Display?Driver症杏、Audio?Drivers等等装获。
LIBRARIES:用C語(yǔ)言編寫(xiě)的完成Android核心功能的一些類(lèi)庫(kù),如:OpenGL|ES(圖形圖像引擎簡(jiǎn)化版)厉颤、WebKit(瀏覽器內(nèi)核)穴豫、SQLite(輕量級(jí)數(shù)據(jù)庫(kù))、Surface?Manager(界面管理器)逼友、Media?Framework(多媒體框架)精肃、FreeType(字體類(lèi)庫(kù))潘鲫、SGL(另一個(gè)圖形圖像引擎)、SSL(基于TCP的安全協(xié)議)肋杖、libc(零散的類(lèi)庫(kù))溉仑。
APPLICATION?FRAMEWORK:應(yīng)用框架層,全部是用Java語(yǔ)言編寫(xiě)的状植,供開(kāi)發(fā)人員調(diào)用浊竟。
APPLICATIONS:應(yīng)用層,我們安裝的所有應(yīng)用都屬于這一層津畸,如振定,微信,植物大戰(zhàn)僵尸肉拓。
ANDROID?RUNTIME :Core?Libraries:核心類(lèi)庫(kù)后频。????????Dalvik?Virtual?Machine:Android底層是Linux系統(tǒng),使用C暖途、C++語(yǔ)言編寫(xiě)的卑惜,所以Android程序(Java語(yǔ)言編寫(xiě))要在Linux上運(yùn)行就需要虛擬機(jī),也就是DVM驻售。
舉例:鬧鐘應(yīng)用露久。
鬧鐘應(yīng)用的功能實(shí)際上就是定時(shí)播放音樂(lè)。鬧鐘應(yīng)用調(diào)用APPLICATION?FRAMEWORK層的MediaPlayer欺栗,MeidaPlayer訪問(wèn)LIBRARIES層中的Media?Framework毫痕,Media?Framework再使用C語(yǔ)言操作Andio?Drivers去播放音樂(lè)。
接下來(lái)迟几,重點(diǎn)認(rèn)識(shí)Framework層
一消请、framework功能
Framework其實(shí)可以簡(jiǎn)單的理解為一些API的庫(kù)房,android開(kāi)發(fā)人員將一些基本功能實(shí)現(xiàn)类腮,通過(guò)接口提供給上層調(diào)用臊泰,可以重復(fù)的調(diào)用我們可以稱Framework層才真正是Java語(yǔ)言實(shí)現(xiàn)的層,在這層里定義的API都是用Java語(yǔ)言編寫(xiě)存哲。但是又因?yàn)樗薐NI的方法因宇,JNI用C/C++編寫(xiě)接口七婴,根據(jù)函數(shù)表查詢調(diào)用核心庫(kù)層里的底層方法祟偷,最終訪問(wèn)到Linux內(nèi)核。那么Framework層的作用就有2個(gè)打厘。
1.用Java語(yǔ)言編寫(xiě)一些規(guī)范化的模塊封裝成框架修肠,供APP層開(kāi)發(fā)者調(diào)用開(kāi)發(fā)出具有特殊業(yè)務(wù)的手機(jī)應(yīng)用。
2.用Java Native Interface調(diào)用core lib層的本地方法户盯,JNI的庫(kù)是在Dalvik虛擬機(jī)啟動(dòng)時(shí)加載進(jìn)去的嵌施,Dalvik會(huì)直接去尋址這個(gè)JNI方法饲化,然后去調(diào)用。
兩種方式的結(jié)合達(dá)到了Java方法和操作系統(tǒng)的相互通信吗伤。Android為什么要用Java編寫(xiě)Framework層呢吃靠?直接用C或C++不是更好?有關(guān)專(zhuān)家給出了如下解釋?zhuān)?/p>
C/C++過(guò)于底層足淆,開(kāi)發(fā)者要花很多的經(jīng)歷對(duì)C/C++的語(yǔ)言研究清楚巢块,例如C/C++的內(nèi)存機(jī)制,如果稍不注意巧号,就會(huì)忘了開(kāi)啟或者釋放族奢。而Java的GC會(huì)自動(dòng)處理這些,省去了很多的時(shí)間讓開(kāi)發(fā)者專(zhuān)注于自己的業(yè)務(wù)丹鸿。所以才會(huì)從C/C++的底層慢慢向上變成了JAVA的開(kāi)發(fā)語(yǔ)言越走,該層通過(guò)JNI和核心運(yùn)行庫(kù)層進(jìn)行交互。
Activity Manager : 用來(lái)管理應(yīng)用程序生命周期并提供常用的導(dǎo)航回退功能靠欢。
Window Manager:提供一些我們?cè)L問(wèn)手機(jī)屏幕的方法廊敌。屏幕的透明度、亮度门怪、背景庭敦。
Content Providers:使得應(yīng)用程序可以訪問(wèn)另一個(gè)應(yīng)用程序的數(shù)據(jù)(如聯(lián)系人數(shù)據(jù)庫(kù)), 或者共享它們自己的數(shù)據(jù)薪缆。
View System:可以用來(lái)構(gòu)建應(yīng)用程序秧廉, 它包括列表(Lists),網(wǎng)格(Grids)拣帽,文本框(Textboxes)疼电,按鈕(Buttons), 甚至可嵌入的web瀏覽器减拭。
Notification Manager:使得應(yīng)用程序可以在狀態(tài)欄中顯示自定義的提示信息蔽豺。
Package Manager:提供對(duì)系統(tǒng)的安裝包的訪問(wèn)。包括安裝拧粪、卸載應(yīng)用修陡,查詢permission相關(guān)信息,查詢Application相關(guān)信息等可霎。
Telephony Manager :主要提供了一系列用于訪問(wèn)與手機(jī)通訊相關(guān)的狀態(tài)和信息的方法魄鸦,查詢電信網(wǎng)絡(luò)狀態(tài)信息,sim卡的信息等癣朗。
Resource Manager:提供非代碼資源的訪問(wèn)拾因,如本地字符串,圖形,和布局文件(Layout files )绢记。
Location Manager:提供設(shè)備的地址位置的獲取方式扁达。很顯然,GPS導(dǎo)航肯定能用到位置服務(wù)蠢熄。
XMPP:可擴(kuò)展通訊和表示協(xié)議跪解。前身為Jabber,提供即時(shí)通信服務(wù)签孔。例如推送功能,Google Talk惠遏。
Framework層提供的服務(wù)還有很多,就不一一列出啦骏啰。
二节吮、Activity Framework結(jié)構(gòu)及運(yùn)行框架
1.Activity的創(chuàng)建會(huì)創(chuàng)建PhoneWindow,PhoneWindow會(huì)創(chuàng)建DocerView判耕,DocerView會(huì)創(chuàng)建View和ViewGroup透绩。
2.應(yīng)用程序在Activity中添加和刪除窗口,是通過(guò)調(diào)用WindowManager類(lèi)的addView和RemoveView函數(shù)達(dá)成壁熄,具體實(shí)現(xiàn)是通過(guò)橋接模式實(shí)現(xiàn)的WindowManagerImpl來(lái)實(shí)現(xiàn)帚豪。進(jìn)而轉(zhuǎn)向調(diào)用ViewRoot類(lèi)的setView和removeViewLocked,然后通過(guò)IPC機(jī)制調(diào)用到WMS中的addWindow和removeWindow來(lái)完成草丧。
3.當(dāng)AMS(ActivityManagerService)通知ActivityThread銷(xiāo)毀某個(gè)Activity時(shí)狸臣,ActivityThread會(huì)直接調(diào)用WindowManager的removeView方法刪除窗口,實(shí)現(xiàn)在WindowManagerImpl類(lèi)昌执。
4.AMS調(diào)用WMS(WindowManagerService)烛亦,一般情況是告訴WMS一些消息,比如某個(gè)新的Activity要啟動(dòng)了懂拾,從而WMS會(huì)保存一個(gè)該Activity記錄的引用煤禽,有時(shí)也會(huì)直接調(diào)用WMS的接口,比如切換窗口時(shí)岖赋,啟動(dòng)切換窗口是直接調(diào)用WMS的setAppStartingWindow檬果。
5.WMS內(nèi)部是全權(quán)接管了輸入消息的處理和屏幕的繪制,輸入消息的處理是借助于InputManager類(lèi)完成唐断,InputManger類(lèi)會(huì)生成兩個(gè)線程InuptReaderThread和InputDispatcherThread选脊,InuptReaderThread循環(huán)地從EventHub讀取輸入消息,對(duì)于非大數(shù)據(jù)是通過(guò)channel方式(InputChannel會(huì)生成serverChannel和ClientChannel)派發(fā)消息脸甘,對(duì)應(yīng)大數(shù)據(jù)則是通過(guò)共享緩存ShareMemory分發(fā)消息恳啥;InputDispatcherThread會(huì)從Channel或者ShareMemory獲取消息并派發(fā),派發(fā)是通過(guò)InputPublisher斤程,應(yīng)用層客戶端通過(guò)InputConsumer不斷從Channel或者ShareMemory獲取派發(fā)的消息角寸,進(jìn)而交由ViewRoot處理菩混。其中InputPublisher忿墅,InputPublisher和InputConsumer是由InputMoniter生成扁藕。
所以InuptReaderThread和EventHub是生產(chǎn)者,InputDispatcherThread是消費(fèi)者疚脐,InputMoniter是消費(fèi)渠道亿柑,ViewRoot是消費(fèi)者和生產(chǎn)者的橋梁,WMS和AMS是家庭夫妻雙管家棍弄。
三望薄、FrameWork啟動(dòng)流程
Android啟動(dòng)過(guò)程包含從Linux內(nèi)核加載到Home應(yīng)用程序啟動(dòng)的整個(gè)過(guò)程。整體流程如下:
Android是基于Linux內(nèi)核的系統(tǒng)平臺(tái)呼畸。啟動(dòng)時(shí)痕支,首先通過(guò)bootloader(系統(tǒng)加載器),加載Linux內(nèi)核蛮原。在Linux加載啟動(dòng)時(shí)卧须,與普通的Linux啟動(dòng)過(guò)程相同,先初始化內(nèi)核儒陨,然后調(diào)用init進(jìn)程花嘶。
Init進(jìn)程啟動(dòng)zygote:解析配置文件:init.rc(系統(tǒng)配置文件)及initXXX.rc(與硬件平臺(tái)相關(guān)的文件)的內(nèi)容執(zhí)行一系列的命令,包括創(chuàng)建mount目錄蹦漠,安裝文件系統(tǒng)椭员,設(shè)置屬性,啟動(dòng)屬性服務(wù)器笛园,啟動(dòng)Socket服務(wù)端口-》加載preload-classes和preload-resources(Framework大部分類(lèi)及資源)-》fork啟動(dòng)新的進(jìn)程Zygote(其實(shí)是由fork和execv共同創(chuàng)建)隘击。
Zygnote孵化第一個(gè)進(jìn)程SystemServer,SystemServer啟動(dòng)各種系統(tǒng)服務(wù)線程研铆。SystemServer進(jìn)程在Android的運(yùn)行環(huán)境中扮演了"神經(jīng)中樞"的作用闸度,APK應(yīng)用中能夠直接交互的大部分系統(tǒng)服務(wù)都在該進(jìn)程中運(yùn)行,常見(jiàn)的比如WMS蚜印、AMS莺禁、PackageManagerServer(PmS)等,這些系統(tǒng)服務(wù)都是以一個(gè)線程的方式存在于SystemServer進(jìn)程中窄赋。SystemServer的main()函數(shù)首先調(diào)用的是init1()函數(shù)哟冬,這是一個(gè)native函數(shù),內(nèi)部會(huì)進(jìn)行一些與Dalvik虛擬機(jī)相關(guān)的初始化工作忆绰。該函數(shù)執(zhí)行完畢后浩峡,其內(nèi)部會(huì)調(diào)用Java端的init2()函數(shù),該函數(shù)首先創(chuàng)建了一個(gè)ServerThread對(duì)象错敢,該對(duì)象是一個(gè)線程翰灾,然后直接運(yùn)行該線程缕粹,于是,從ServerThread的run()方法內(nèi)部開(kāi)始真正啟動(dòng)各種服務(wù)線程纸淮。
基本上每個(gè)服務(wù)都有對(duì)應(yīng)的Java類(lèi)平斩,從編碼規(guī)范的角度來(lái)看,啟動(dòng)這些服務(wù)的模式可歸類(lèi)為三種:模式一是指直接使用構(gòu)造函數(shù)構(gòu)造一個(gè)服務(wù)咽块,由于大多數(shù)服務(wù)都對(duì)應(yīng)一個(gè)線程绘面,因此,在構(gòu)造函數(shù)內(nèi)部就會(huì)創(chuàng)建一個(gè)線程并自動(dòng)運(yùn)行侈沪。模式二是指服務(wù)類(lèi)會(huì)提供一個(gè)getInstance()方法揭璃,通過(guò)該方法獲取該服務(wù)對(duì)象,這樣的好處是保證系統(tǒng)中僅包含一個(gè)該服務(wù)對(duì)象亭罪。模式三是指從服務(wù)類(lèi)的main()函數(shù)中開(kāi)始執(zhí)行瘦馍。無(wú)論以上何種模式,當(dāng)創(chuàng)建了服務(wù)對(duì)象后应役,有時(shí)可能還需要調(diào)用該服務(wù)類(lèi)的init()或者systemReady()函數(shù)以完成該對(duì)象的啟動(dòng)
當(dāng)以上服務(wù)線程都啟動(dòng)后情组,AMS以systemReady調(diào)用完成最后啟動(dòng),mMainStack.resumeTopActivityLocked(null)-》mService.startHomeActivityLocked啟動(dòng)第一個(gè)Activity扛吞。至此呻惕,F(xiàn)rameWorkd啟動(dòng)完成。