2007年蘋果(Apple)推出首款iPhone,市場立即引爆「iPhone效應」,銷售屢創佳績下,使得智慧型手機一躍成為市場的主力商品。從整合電話、行動上網、行程規畫、生活娛樂等多功能於一機,到簡單的觸控式人性化操作介面,乃至於時尚外型設計,都已成為基本要求。而在產品差異化越來越不明顯時,價格上的競爭優勢,成了決戰市場的關鍵因素。
由谷歌(Google)號召電信、半導體、手機、軟體等領導品牌業者包括沃達豐(Vodafone)、英特爾(Intel)、英偉達(NVIDIA)、華碩、宏達電、三星(Samsung)、樂金(LG)、軟體銀行(Softbank)等共同成立的開放手機聯盟(Open Handset Alliance, OHA),並集體開發完成的行動裝置平台--Android,在2008年11月Google宣告免費開放Android手機平台後,激發更多業者表示高度興趣,進而投資設計生產,決定正面迎戰既有品牌,使市場正式進入白熱化競爭期,也讓過去由諾基亞(Nokia)的Symbian平台、微軟Windows Mobile平台、以及蘋果的iPhone平台壟斷的智慧型手機系統平台,呈現四強抗衡的態勢。
特殊架構設計有利軟體無縫整合
因Android完全開放特性,加上其底層結構完善,利於軟體開發商在最少成本、最短的時程下,設計出兼具價格競爭力與高品質的多媒體應用程式。以Android其獨特而完整的系統架構為例,可使軟體開發商各自開發的軟體進行完整的串連。舉例來說,使用者出外旅遊時會拍照或錄音,然後可能會想上傳到Picasa之類的網路相簿,或直接用MSN之類的即時傳訊軟體傳給朋友。這在其他行動裝置系統平台並不容易實現,因為個別軟體開發時並不清楚使用者還會用到什麼軟體,因此難以制定溝通機制,但Android由系統面解決了這個問題,讓使用者主導並決定喜歡的相機或影音錄製程式、安裝自己網路相簿提供的上傳程式或下載愛用的即時傳訊軟體。這些軟體的開發商在開發時事先不須溝通或協調,因此可減輕這方面的負荷,從而加速軟體的開發。
在多媒體相關的開發上,Android也有相當完整的支援。它內建多媒體資料庫,並可選擇定期或在需要時根據指示來掃描記憶卡的內容,自動建立索引、辨認媒體資訊,然後存到所有應用程式都可存取的共用資料庫中。只要讀取這個資料庫,開發者就可以迅速得到各種應用程式需要的多媒體資訊,又快又簡單。此外,Android採用的多層式架構以及OpenMAX/OpenCORE,也可簡化不同目的的軟體開發商間的溝通協調,而在的各層架構中,多媒體框架結構(Media Framework)更是實現無縫整合的關鍵。
分層架構各司其職條理清晰
Android架構由上而下可分為五大部分:應用層(Applications)、應用層框架(Application Framework)、函式庫(Libraries)、Android Runtimes、Linux核心(Linux Kernal)(圖1)。越上層表示越接近使用者,越底層則表示越接近手機硬體架構。
|
圖1 Android系統架構 |
最頂端的應用層是使用者唯一會接觸到的階層;一般俗稱的播放程式(Player)或錄影/錄音機(Recorder)就是指位在此層的應用程式(App)。應用程式以Java語言寫成,透過第二層的應用層框架(Application Framework)往下溝通。
Android平台的函式庫以C/C++撰寫並編譯,具有高效率的特點,舉凡編碼、解碼、解析檔案格式等對中央處理器(CPU)造成吃重負擔的作業都在此處理。另外,由於Java無法直接和硬體溝通,Android Runtime沒有處理到的硬體介面也可交由函式庫來實做。
介於上述兩者中間的應用層框架則實作JNI技術,把易於軟體開發商開發的上層Java應用程式中介層(API)及函式庫和便於進行繁重運算的下層原生C/C++函式庫(Native C/C++ Libraries)分開,讓不同領域的開發者可以在自己擅長的領域進行開發,而不用擔心被干擾。雖然開發者亦可修改或擴充本層,但由於這會破壞Android嚴分兩層的原則及降低可攜性,通常不建議應用程式開發者更動。
Google大力相挺 Andriod開發工具功能完整
為便利開發者的工作,Android Developer官方網站(http://developer.android.com/index.html)提供下載軟體開發套件(SDK),並有詳細的說明文件指引,清楚載明要如何從無到有寫出一個記事本軟體。
開發環境方面,Android有相當完善的Eclipse開發環境(圖2),並為Windows、Linux、Mac三種作業系統提供各種管理及除錯工具,如完整的模擬器,可在沒有實機的情況下實驗,還可任意更新韌體,或利用Logcat工具即時檢查包含Java自動生成的例外堆疊追蹤在內的各種Log訊息,或可在個人電腦(PC)端直接進入裝置主機(Console)內部操作,並可上傳或下載檔案的adb工具。
|
圖2 Eclipse開發環境 |
要將PC連結到實體裝置非常簡單,Android SDK內含Windows用的驅動程式,安裝後只要把手機和PC用USB接起來就連結完成。若使用者在Linux或Mac平台上進行開發,連接動作也非常簡單:Linux只須增加一行設定,Mac更毋須任何設定。
Android用自訂的apk檔案格式包裝應用程式,一個apk檔就包含一整套完整的程式,並可藉由SDK提供的開發工具輕易進行安裝或分析。為了安全起見,Android要求所有檔案皆須經過數位簽章才可發布及安裝,並在教學網頁中詳細解釋如何建立、簽署及發布應用程式。
目前谷歌官方提供Android Market作為上傳及下載程式的市集,並在美國及英國地區提供付費應用軟體的買賣。
善用Java框架 四行程式寫完媒體播放器
應用框架層提供Java API給上述應用程式層以利開發軟體,其中有供多媒體使用的類別,分別是負責播放的MediaPlayer類別,以及負責錄製的MediaRecorder類別。此外,還有VideoView這個更好使用的類別。
MediaPlayer本身即是已經包裝完善的播放器,只須簡單的設定便可完成讀取檔案、播放/暫停、片段搜尋、取得媒體資訊、建立Listener等功能。低階工作如影音同步、Parse、解碼、算圖(Render)等都由底部函式庫完成。MediaRecorder目前由於底層函式庫不提供影片編碼功能,故僅能用以錄音,檔案格式為amr。使用時一樣只需簡單的初始化步驟即可。
VideoView為可直接內含於XML Layout檔案(UI設計)的類別,它內含一個MediaPlayer,並實作所有MediaPlayer的方法。要播放影片時建議使用VideoView而非直接使用MediaPlayer。
關於Java框架更詳細的介紹將保留到下期再說明,在此先展示幾段程式碼讓讀者體驗使用應用框架層中的Java框架來開發的簡易度。只須撰寫如下四行程式碼,就能夠開始播放指定的影片。
//播放影片 _player=(VideoView) findViewById(R.id.videoplay); mURI=getIntent().getData(); _player.setVideoURI(mURI); _player.start(); |
除了播放媒體外,使用者可能會有多工需求,如想要一邊聽音樂一邊作其他事,故開發者在設計播放器時須能支援背景執行功能。在Android中,前景執行的程序叫做Activity,背景執行的程序叫做Service。兩者之間藉由ServiceConnection和AndRoid接口描述語言(AIDL)連結,達到複數程序同時執行的效果。
在處理多媒體時,由於編解碼消耗的CPU時間相當大,嚴重時甚至會影響到其他程式執行。有鑑於此,Service中最好是只處理最低限的作業,也就是不處理任何和使用者介面(UI)有關或跟影片相關的程序,而僅作聲音相關的處理,以確保較佳的執行效果及使用者經驗。
Native C/C++函式庫可支援多種Codec開發
至於Java無法處理的部分-CPU運算,主要都是由這層來處理。由於位於此層的函式庫皆由C/C++/ASM寫成,並支援硬體編解碼器(Codec),在效率方面不會輸給其他平台的多媒體框架。Android採用OpenCORE作為基礎多媒體框架,為基於PacketVideo產品「CORE」的開放源碼計畫,就如同Android開放計畫中Google占了很大的比例一樣,OpenCORE的主要支持者也是PacketVideo,整個函式庫原始碼開放,可在http://source.android.com/這個網站下載整分Android的原始碼,而OpenCORE則位於external/opencore這個資料夾下。
在Android和它的第一支實體機器G1中內建支援的影像編碼有:H.264/AVC、H.263/MPEG4、3GP/3GPP、WMV8。聲音編碼則支援:MP3、M4A、AAC、AMR、MIDI、WAV、MIDI、OGG、WMA8。而OpenCORE則可分為七大塊:PVPlayer、PVAuthor、Codec、PacketVideo Multimedia Framework(PVMF)、Operating System Compatibility Library(OSCL)、Common、OpenMAX。
PVPlayer和PVAuthor掌管音訊和視訊的錄製及播放,並透過Linux的硬體驅動程式直接和硬體溝通,當上層傳來控制要求時,這兩塊也須做出對應。此外,由於PVPlayer和PVAuthor使用的都是原始資料(Raw Data),所以須透過編解碼器來進行編碼或解碼;OpenCORE的編解碼器則可自由增加或抽換,只須和PVMF註冊即可。PVMF就是Android判斷檔案格式及編碼內容的框架,自動決定要用哪個Parser來解開或包裝檔案,並選擇適當編解碼器進行編碼或解碼,Common內部則存放有各種整體框架共通功能。
Android使用工具鏈(Toolchain)為Google自製的Bionic Libc,和GNU Libc不相容,並且不支援C++的標準函式庫。這套Toolchain有著速度快、體積小(不管是Lib本身或編譯出來的可執行檔)的優點,但沒有C++標準函式庫是否就代表所有C++程式都不能移植上來呢?事實上,OSCL提供如資料型態、記憶體管理、執行緒等基本函式,當要撰寫C++程式時即可使用此函式庫,當然也可以自製需要的C++函式庫,然後照正常方式連結即可。
編解碼器開發部分,Android採用Khronos所開發的OpenMAX。OpenMAX提供編解碼器開發者更簡易、直覺的開發框架,其中分為DL、IL、AL三種層級。DL掌管直接和硬體接觸的部分,包含對CPU、顯示晶片、數位訊號處理器等的最佳化和驅動程式接口。IL提供編解碼器函式庫介面,除了純軟體編解碼器外,硬體編解碼加速器亦可經由OpenMAX IL介面和上層連結。AL控制錄影、放影、各種感測器及顯示器等使用者介面的應用程式階層。
要將編解碼器移植到Android系統上時,最簡單的方法就是實做一個OpenMAX IL的介面,並藉由它來傳遞各種資料及訊息。在Android的原始碼中也含有OpenMAX部分,位在external/opencore/extern_libs_v2/ khronos/openmax。關於如何實作這些元件的詳細文件,則可參照external/opencore/doc內的pdf檔案。
Runtime層多媒體資料庫為播放器添加更多 高階功能
Android Runtime層中的多媒體資料庫對多媒體應用開發影響甚大,故在此特別提出說明。
Android的多媒體資料庫採用SQLite3資料庫系統,它的特點是效率高、體積小、支援大部分SQL查詢,相當適合行動裝置使用。在Android上資料庫又分為兩種:共用資料庫及私用資料庫。任何應用程式,包括系統的多媒體掃描器,都可以對共用資料庫進行存取;私用資料庫則只有建立該資料庫的應用程式可進行存取。多媒體資料庫屬於共用資料庫。
Android內建三塊多媒體資料庫,分別管理音訊、視訊及圖片。開發者可透過ContentResolver類別(Column)來得到共用資料庫,並利用MediaStore類別來告訴系統需要哪一塊資料庫的什麼資料。
如表1所示,MediaStore的三個子類別分別定義了三種資料型態,其下為該資料型態具有的資料類別。Media為三者共通,代表實際上的多媒體檔案,而音訊檔另有專輯、歌手、類別、播放清單四種子類別,分別具有各自的資料欄位,至於圖片則具有擺放縮圖用的子類別。
表1 多媒體資料庫query用常數 |
項目\資料型態 |
音訊 |
視訊 |
圖片 |
MediaStore子類別 |
MediaStore.Audio |
MediaStore.Video |
MediaStore.Images |
資料類別 |
Media
Albums
Artists
Genres
Playlists |
Media |
Media
Thumbnails |
確定需要的資訊後,下一步就是從資料庫裡實際取出,首先要取得控制資料庫的ContentResolver物件,須使用Context類別之中的getContentResolver()方法。每個Activity和Service都實作Context,不過官方建議使用應用程式內部共通的getApplicationContext(),以避免浪費記憶體。在Activity或Service類別內可使用以下程式碼,其他類別則須傳入Context物件。
ContentResolver resolver=getApplication Context().getContentResolver(); |
有了ContentResolver後,我們就可以對他下查詢指令來實際取得資料。比如說,以下程式碼可指定某音樂檔的路徑並取得歌手名:
Cursor cursor= resolver.query(MediaStore.Audio.Media. EXTERNAL_CONTENT_URI, new String[]{MediaStore.Audio.Media.ARTIST }, MediaStore.Audio.Media.DATA+"=?", new String[]{“/sdcard/music.mp3”}, null); if (cursor.moveToFirst()) { String artistName=cursor.getString(cursor. getColumnIndexOrThrow(MediaStore.Audio. Media.ARTIST)); } cursor.close(); |
查詢指令的第一個參數代表要在資料庫的哪一塊區域找資料,本例為指定“Audio”,代表要求查詢方法函式到音樂檔資料的存放處去搜尋。第二個參數代表要搜尋的資料欄位,本例為指定歌手名字(ARTIST)。第三個參數代表搜尋條件,本例為指定路徑(DATA)。DATA後面的「=?」代表實際上的限制條件,寫在第四個參數,本例為“/sdcard/music.mp3”代表要搜尋SD卡中的music.mp3這個音樂檔,第五個參數是排序方式,在本例中不使用。
查詢方法函式會回傳一個cursor物件,讓程式可以在大量資料間迅速移動,先呼叫moveToFirst()方法讓cursor指向有效資料列,接著再把指定欄裡面的資料取出便大功告成。至於建立這些資料則不需開發者操煩,Android在有檔案被拷貝到記憶卡上時就會去解析檔案,然後立刻更新資料庫,開發者只要負責使用即可。
開放易用特性廣受青睞 軟體開發事半功倍
Android是一個開放的手機軟體開發平台,內建多媒體支援並擁有廣大的擴充性、且內含功能強大的多媒體資料庫,使撰寫應用程式、開發編解碼器的程式設計師不會互相干擾而分工合作。隨著愈來愈多廠商投入Android終端設備的製造,加上其易於設計的特性,必能吸引軟體製造商積極投入以Android為基礎的行動多媒體應用研發上,設計出更符合消費者需求的多樣化應用程式,也為市場創造無限商機。如圖3即為資策會工程團隊的開發成果--Meridian Player在模擬器上執行的畫面,該模擬器亦可在G1手機上實際執行。
|
圖3 在模擬器上執行的Meridian Player |
(本文作者任職於資策會網路多媒體研究所)