導言

Android應可說是科技界2009年第一大事。Android前身為一公司,被Google買下後繼續開發,以開放源碼的方式發行,還成立了Open Handset Alliance (OHA)作為支持Android的商業組織。其中成員如Qualcomm, TI, Wind River等在各自領域都赫赫有名,尚未上市就已經相當轟動。開放源碼(Open source)的手機作業系統,其實在此之前已經出現數個,例如Qtopia1以及其後雷聲大雨點小的Openmoko,再如當時以行動上網裝置(Mobile Internet Device, MID)為主的Maemo等等。不過,Qtopia與Openmoko的成熟度當時並未達到商業化需求,而日前Nokia雖然已經基於Maemo發表了新一代智慧型手機N900,但當時Maemo仍侷限於行動上網裝置,而非電話。

換言之,Android除了擁有眾多大廠支持,而且在開放之初就發表了T-Mobile G1,有產品可證明商品化能力。這意味著,長久以來受制於Windows Mobile,又無能力開發自有作業系統的手機廠商,看見了站在巨人肩膀上做出自有產品的可能性。從2008年底開放以來,2009年HTC, Samsung, Motorola, Acer等等都發表了Android手機,而看來2010年中還有更多。究竟 Android 有什麼特點,與以往根基於Linux的手機差別何在,以及面對其他手機作業系統的競爭有何優劣等等,本文嘗試做一介紹與探討。

技術面淺探

要談Android,就無法迴避技術面的討論,但在此會忽略細節以及犧牲一些語言精確度,試著做一簡介。

系統架構

Android作為一作業系統,其針對的硬體為智慧型手機,並在設計伊始就考慮到3G網路以及觸控螢幕、相機、GPS等現代應用。作業系統作為裝置與人之間的媒介,以及負責讓手機正常運作。與人接軌的那端,使用者介面、應用程式等,一般稱上層。而與機器接軌的部份,比如對打電話的控制、無線網路晶片、顯示圖形到螢幕上、接受觸控螢幕收到的手指觸摸等等,就是由底層來負責。在此我們先由下層開始介紹,再步步往上。

(http://developer.android.com/images/system-architecture.jpg)

Linux Kernel

必也正名乎:一般所稱Linux,其實是統稱,指根基在Linux kerne以及其他許多跟kernel不見得有關的軟體所組成的作業系統。最早,Linux一詞其實是專指kernel,它提供了系統底層與硬體間的基本核心,讓其他程式可以在上頭執行。其最早作者是Linus Torvalds,他用自己的名字,加上採用了與Unix系統相容的介面,將自己的作品命名為Linux。

如前所述,在Linux kernel上頭執行的程式,跟kernel本身不見得有關係。可以是自由軟體,也可以完全不是。把它加上一些自由軟體,例如基本的函式庫、工具、圖形介面,應用程式等等,所組成的一套完整作業系統,才是一般所稱的Linux。為了避免誤解,而且也為了正確傳達自身的貢獻,自由軟體基金會2 建議大家稱呼這樣的一套作業系統為GNU/Linux。其中的原因是,kernel提供底層機制,但系統中其他重要元件幾乎都是來自於GNU,也就是自由軟體基金會。

希望大家還沒被這些名詞搞混。要弄清這些不同的原因是,Android是在Linux kernel上頭運作的,但他並不是GNU/Linux。因為在一般 GNU/Linux裡面會有的東西,Android幾乎都沒有。

Linux kernel的版權是GNU General Public License version 2 (GPLv2)3,這又是什麼玩意呢?GPLv2是所謂的Copyleft4版權,簡單來說,就是為了確保智慧財產能夠繼續公開流傳,所以任何基於此創作的延伸創作,都自動採用了相同版權。GPL本身還有個特色,就是「共同運作」也算是延伸的一部分,意思是說你的程式沒直接改GPL的程式碼,但是連結了GPL的東西跟你的程式共同運作,那你的程式也必須採用GPL版權。

舉例來講,假定今天某公司覺得某GPL軟體不錯,拿來改了改,放在自己的產品裡頭拿出去賣,那某公司就一定要明確的一起散佈修改後的程式碼。如果沒有,那就是觸犯版權了。有個組織叫GPL Violations5,專門抓這種案例,國內公司如D-Link以及ASUS都上 過榜。這下問題來了:如果你是硬體廠商,希望你的硬體能在Linux kernel下運作,那麼就必須要有驅動程式。驅動程式就是按照硬體的規格寫的程式,用來告訴kernel怎麼操作這個硬體。如果驅動程式的程式碼公開,等於就是揭露了一些內部資訊。許多廠商不願意這麼做,所以就提供編好的驅動程式,但不提供原始碼。而kernel的版權所有者,也就是Linus Torvalds以及其他許許多多的kernel作者們,為了支援盡可能多的硬體,對這種行為是採取睜一隻眼閉一隻眼的態度,也就是目前這種編譯好的驅動程式,算是處在灰色地帶。

既然Android採用了Linux kernel,當然得照遊戲規矩來。但我們從前文可知,Android的重點就是商業應用,他們可不願意系統裡有什麼「灰色地帶」,於是採用了一些手法來繞過這問題。例如可以在 kernel這邊開個小通道,告訴大家說要控制這硬體就透過我吧,我只負責傳進傳出,但真正控制的指令都寫在某個不公開程式碼的Android函式庫裡頭。這樣一來,公佈的就只有那個通道,實際要怎麼控制,別人還是不知道。

走筆至此,可以看出Google的原則之一 “Do no evil” 是很有意思的。他們自己的確承諾,而且也願意公開Android的程式碼,但是他們給了其他人“Do evil”的選擇。這樣還算不算是 Do no evil 呢?當作哲學問題吧。

然而,Linux kernel已經發展了相當長的時間,擁有許多優秀的開發者以及廣大的使用者群,是非常穩定的系統核心。這為Android系統提供了相當穩定快速的基礎建設。

Libraries

這裡說的libraries是跑在系統裡頭的函式庫,採用的語言不是Java,他們提供了許多基礎建設。裡頭有幾個值得一提的元件:

Bionic:這是Android版的 libc。libc是 GNU/Linux以及其他類似Unix系統上最基礎的函式庫,一般最常用的是glibc,就是GNU做的libc。而在較小型的裝置上也可以用uclibc之類的。不論是glibc or uclibc,版權都是LGPL6(GPL的略為弱化版)。看到這大概可以猜到了吧,又是Copyleft問題。官方的說法是,除了版權問題以外,還考慮必須輕量以及快速,所以才做了自己的libc。不過輕量、快速,本來就是小型裝置用的uclibc一開始的目標,因此,最主要的恐怕還是版權問題。

Webkit:鼎鼎大名的Apple Safari瀏覽器背後的引擎就是Webkit,Android也包含進去了。支援可離線使用的html 5新發展,產生了各種有趣的可能,這部分值得另文介紹,這裡就不再贅述。

硬體抽象層(Hardware Abstraction Libraries, HAL):提供了操縱系統硬體的方法,上頭接上標準的Android framework,就可以讓使用者用一致的方式操作硬體。例如程式只要下令「拍照」,那麼雖然不同相機硬體拍照的指令下法不同,透過抽象層都可以包裝成一致的介面。HAL包含了Android對各硬體裝置例如顯示晶片、聲音、數位相機、GPS、3G 等等的需求,但他只是抽象的概念,事實上若要支援新的硬體,需修改的程式碼分散各處,要自行去尋找。這部份與系統廠商息息相關,後面會再談到。

Android Runtime

跨平台:Android最顯著的特徵之一,就是應用程式可以在不同的硬體上執行,而有同樣的行為。這聽起來沒什麼,一般我們用Microsoft Windows不就是如此嗎?其實並不那麼單純。可以想像,假定有一台Windows XP電腦,也有一隻Windows Mobile手機,那麼手機上的程式有沒有辦法拿到XP上面來跑,或者是相反呢?在電腦上,所有人跑的作業系統跟硬體,其實有很高的一致性,但是一旦到了小型裝置五花八門的世界,就不是那麼回事了。

一個程式的執行,牽涉到幾個元素:原始程式碼、編譯器、函式庫、CPU。Android的應用程式是採Java程式語言寫成,跨平台的方式也與Java類似。Java頗為普及,且之前在手機方面已有許多應用如遊戲等,稱為Java ME,由昇陽(Sun Microsystem)主導。一般所謂Java其實包含三個層面,其一是Java這個「電腦語言」,也就是像這樣的東西:

class HelloWorld
{
    public static void main(String [] argv)
    {
        System.out.println("Hello, world!");
    }
}

也就是用人比較容易看懂的語言(也許不那麼容易啦,但至少比一堆0跟1來得好)來叫電腦做事,比如上個例子是在螢幕上印一行字Hello, world。所謂程式的原始碼,就是一整篇這樣的文章,結合起來,可以叫電腦執行某些功能。這樣的語言比自然語言容易「翻譯」成電腦看得懂的「指令」,而負責翻譯的,就是「編譯器」。

電腦的核心CPU有很多不同種類。一般我們用的是Intel的產品,有些是32位元、有些是64位元。有些人用的可能是Power,例如以往蘋果電腦的使用者。還有一些小一點的電腦,可能就是用ARM架構。總之,不同的CPU具有不同的指令集合,是不能直接互通的。在此我們可以想像,同樣的程式碼,可以經由編譯器,翻譯成適合不同CPU架構的程式,而他們之間是不能互換的。例如編給ARM使用的程式,在Intel的CPU上頭就不能跑。要如何解決這個問題呢?

這裡引入第二層面:「Java 虛擬機器」(Java virtual machine)。虛擬機器可以想像成一虛擬的CPU,先設定一些共通的指令,然後針對各種不同的架構做個別轉換,如此只要是採用此「共同指令集」的程式,就可以在這虛擬機器上面執行,由虛擬機器負責轉換成目標CPU的指令集。如此一來,我們只需要把用電腦語言寫好的程式編譯成「虛擬機器」看得懂的就行了。Java使用的共通指令就稱做 “Java bytecode”。

最後則是Java runtime library,也就是一個「函式庫」,裡頭存了很多編譯好的現成程式,來讓開發者使用,這樣就可省下很多重覆的工作。比如上頭這例子裡頭的System.out.println就是函式庫提供的。那我們可以想像,如果在程式中我們用了很多某個函式庫裡頭的東西,但是用的人只拿到編譯好的程式,但沒有同樣的函式庫,那這程式還是不能用。比如說,Windows, Linux提供的基本函式庫就很不一樣,所以做同樣事情的程式,寫法可能完全不同。Java函式庫裡頭提供的工具,是有標準可循的,所以以上的程式,不管是要在Windows上頭跑,或是Linux上頭跑,都是一樣的寫法。

於是乎,我們可以把Java runtime library跟Java虛擬機器搭配起來,這樣我們只要用Java這個語言寫程式,裡頭呼叫Java runtime library裡頭的工具,用編譯器編成Java bytecode,交給虛擬機器去執行,就可以在各種平台上面跑一樣的程式了。這兩者的組合稱為「Java Runtime Environment, JRE」,只要針對某環境提供JRE,就可以執行Java應用程式了。雖然這聽起來很棒,但我們可以想像,由於隔了一層虛擬機器,程式跑起來容易比直接下命令來得慢,而且必須額外安裝JRE,用掉較多資源。

Java Runtime讓人們可以在不公開原始碼的情況下,發行編譯好的應用程式,在各種不同的平台上執行,相當適合商業應用。Android循著相同架構,也提供了Android Runtime,但有幾點不同。

Android使用的虛擬機器叫作Dalvik,原本並不是針對Java設計的。它認識的指令集並不是Java bytecode,而叫Dalvik executable,簡稱dex。Android裡頭提供了一個工具程式叫dx,可以把 Java bytecode再翻譯成dex,這樣Dalvik就可以執行它了。這虛擬機器為了適合在電話這種比較小型的平台上使用,而做了許多最佳化的處理,例如適用較慢的CPU、低記憶體使用量、減小應用程式的大小等等。

Android虛擬機器與函式庫合稱Android Runtime,在函式庫方面,提供了大部分的標準Java函式庫,讓Java工程師可以無痛的轉換,而關於手機的部份則提供許多諸如使用者介面、藍芽、GPS相關、網路、3D加速、影音、以及電話本身等等許多現成的函式可用。這些函式使得開發者可以直接取用基礎功能,進而專注於應用程式的開發。

Application Framework

提供應用程式執行環境,針對手機設計,許多觀念與一般個人電腦應用程式有相當不同。在此將開發者網站上的說明大略翻譯如下:

應用程式元件

Android的重要功能之一為,應用程式可在對方允許的情形下,使用其他應用程式的元素。例如,如果你的應用程式想要顯示一排可以捲動的影像,而另一應用程式已經開發出了適合的捲軸元件,並開放給他人使用,你可以直接呼叫這元件來使用,而不需自行開發。你的應用程式不需要包含他人的程式碼,也不需固定連結到某程式。反之,Android框架會在有需要時,自動啟動其他應用程式的相關功能。

要順利運行,系統必須能夠在需要其任一元件時,啟動一應用程式程序,並做出需要的Java物件。所以,與大部分系統上的應用程式不同,Android應用程式並沒有一個單一的「進入點」來使用所有功能。反而是,他們提供元件讓系統可以視需要使用。元件類別有四種:

Activities

Activity表示一使用者介面,用以完成某特定事務。例如,activity可呈現一選單列表,或是顯示相片跟標題。簡訊軟體可能包括一個列出所有傳簡訊對象的activity,一個讓使用者對選擇對象寫簡訊的,以及其他的activity來看舊訊息以及設定功能。他們雖然組成一個使用者介面,但各元件互相之間仍是獨立的,例如,其他軟體需要傳訊時給某人時,可能只需叫出「寫簡訊」的activity,而不需其他。

一應用程式可以只包含一個activity,也可以像剛才描述的簡訊軟體一樣,包含好幾個。當然,需要哪些,以及要多少,都是取決於應用程式的設計。一般來說,其中一個activity會被標為程式執行時第一個看到的畫面。由一個activity移動到另一個,是利用目前的來呼叫下一個。每個activity都分配到一個預設的視窗,可以在裡頭畫東西。一般說來,這視窗跟螢幕一樣大,但它也可以比螢幕小,並浮在其他視窗上。而activity也可以開多個視窗,例如跳出一個視窗來取得使用者回應,或者是針對使用者選擇顯示重要資訊。

視窗內部的視覺組成是由樹狀結構的”view”組成,每個view可以包含其他view,控制視窗中一塊長方形的區域,並可跟使用者互動。換句話說,view可組成activity與使用者互動的「實相」。Android系統中有許多現成的view可供取用,例如按鈕、文字欄位、捲軸、選單、勾選格等等。

Services

Service並沒有可見的使用者介面,而是在背景永久執行。例如,當使用者做其他事情時,service可能在播放音樂,或正從網路上抓取資料等等。

Broadcast receivers

唯一功能為收取以及回應「廣播訊息」。廣播經常來自Android系統本身,例如,手機所處的時區改變,電池快沒電了,或是剛照了一張照片,或是使用者剛改變了顯示介面的語言等等。應用程式也可以發出這類廣播,例如,讓其他應用程式知道某些資料已經下載完成,可以使用了。

一應用程式可以有任意數量的broadcast receiver來收取任何它認為重要的訊息。它沒有使用者介面,然而,他們為了回應廣播訊息,可以呼叫某個對應的activity,或者是發出一訊息通知來告訴使用者發生了什麼事情,以及震動、播放音效、閃爍軌跡球等等。

Content providers

負責對其他應用程式提供或收取資料。資料可存放在檔案系統中,或資料庫、或任何合理的方式。例如:通訊錄。

任何時候,當系統需要某一特別元件時,Android系統會先肯定擁有這個元件的應用程式正在執行,如果沒有,就啟動他。另外還會確認此元件是否已經存在於系統中,若視沒有,就製作一個。

啟動元件:intents

Content provider在有人需要存取時便會由系統啟動,而其他三類元件:activity, service, broadcast receiver都是由一種叫intent的訊息啟動的。一個intent表示的是一種「企圖」。例如,它可能是要求「顯示這張圖片」,或者是「編輯這段文字」,或「編一段訊息傳給這個人」。比如說,某應用程式想傳訊給通訊錄中的某一人,可先發出企圖「瀏覽通訊錄」,則系統中負責此事的元件便被啟動。選取對象後,便呼叫「編輯簡訊」的元件來編輯並接著發送出去。
關於應用程式運作,詳細情形可參考開發者網站上的說明7,在此就不詳述了。

Applications

要開發Android應用程式,並不需要下載整個平台的程式碼,只需要採用Google發行的軟體開發工具(Software Development Kit, SDK)即可。使用的電腦語言是Java,並內建模擬器,可直接驗證寫出的應用程式,而不需擁有實體手機。建議的開發環境為Eclipse,此軟體亦為開放源碼專案,不需付費即可使用,許多公司如IBM等亦根基於Eclipse推出了自有的工具,可說應用相當普遍。Google在這部份提供了Eclipse的一個延伸套件,與模擬器、除錯等等都有整合,並提供完整文件,進入門檻降得相當低。

延伸閱讀:

  1. http://www.betaversion.org/~stefano/linotype/news/110/ (Dalvik: how Google routed around Sun’s IP-based licensing restrictions on Java ME):關於 Android 如何繞過 Java ME
  2. http://blogs.sun.com/jrose/entry/with_android_and_dalvik_at (with Android and Dalvik at Google I/O):對 Dalvik 有興趣的話一定要看
  3. http://sites.google.com/site/io/anatomy–physiology-of-an-android (Anatomy & Physiology of an Android):Google 對 Android 平台內部架構的概觀介紹

notes

1 現已經多次改名,先改為 Qt Embedded,現通稱 Qt,讀音同cute。現已由 Nokia 收購。

2 http://www.fsf.org/

3 http://en.wikipedia.org/wiki/GNU_General_Public_License

4 http://en.wikipedia.org/wiki/Copyleft

5 http://gpl-violations.org/

6 http://www.gnu.org/copyleft/lesser.html

7 http://developer.android.com/guide/topics/fundamentals.html

 

資料來源:http://mmdays.com/2010/08/27/android-1/

創作者介紹
創作者 香醇咖啡 的頭像
香醇咖啡

香醇咖啡

香醇咖啡 發表在 痞客邦 留言(0) 人氣()