Jollen's Blog「Android OS」裡的所有文章!
jollen 發表於 December 29, 2008 7:58 PM
Android 應用程式的模式(application model),可由以下幾個觀念講起。在真正進入 Android 程式設計前,必須先了解以下幾個名詞觀念。 1. Android package(.apk) Android 應用程式套件,包含應用程式本身,以及相關的資源檔案。將 apk 套件下載到 Android 手機後,即可安裝至手機上。Android Development Kit 可自動將 apk 套件下載至模擬器或實體手機。 2. task Task 就是「應用程式」本身,也就是 Android 手機上的圖示,使用者可點擊圖示啟動 task。從開發者的角度來看,task就是一個或多個 activities。 3. process Process 在作業系統的定義上,指的是「執行中的程式」,在 Android 的應用程式模式中,代表的是低階的執行程式,也就是系統層(kernel)的部份。一個 apk 套件裡的所有程式,都是在一個 process 裡執行。 4. 什麼是 Activity(android.app.Activity)...
jollen 發表於 December 29, 2008 8:04 PM
上一則文章介紹了 Activity 與 View 的觀念,若能再理解 Activity 與 View 的關係,就不難了解 Android 應用程式的整個模式了。請看以下的範例程式: package com.moko.hello; import android.app.Activity; import android.os.Bundle; import android.widget.TextView; public class HelloMoko extends Activity { /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) {...
jollen 發表於 December 29, 2008 8:13 PM
初步了解如何撰寫第一個 Android 應用程式後,接著就可以實際來建立我們的第一個 Android 專案了。Android Development Kit(ADT)使用 Eclipse 整合式開發環境,根據 Android SDK 裡的文件說明,先安裝 Eclipse 以及 ADT,然後建立一個新專案(File -> New -> Project),並選擇「Android Project」,如圖1。 圖1:建立 Android Project 接著輸入專案屬性: 1. Package name:Java 套件名稱,在這裡我們將應用程式的套件命名為 com.moko.hello。 2. Activity name:輸入應用程式的 Activity 類別名稱,建立一個繼承 Activity 的新類別。 3. Application name:輸入應用程式名稱,即應用程式標題。 圖2:輸入專案屬性...
jollen 發表於 January 4, 2009 10:22 PM
繼上一篇文章介紹了 View 的觀念後,接下來就要了解一下如何「安排」Android 應用程式的 layout。 Android 應用程式的 layout(UI 佈局)除了直接撰寫程式碼的方式外,也能使用 XML 檔案來做描述(XML-based Layout)。在 Android Development Kit 的「Package Explorer」視窗,點選「res -> layout」選擇 main.xml,可以看到 “Hello Moko” 應用程式的 XML layout 檔案,如圖1。 圖1:"Hello Moko" 的 XML layout 檔 以下這段 XML 用來描述「TextView」物件的 layout: <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/hello"...
jollen 發表於 January 4, 2009 10:49 PM
上一篇文章介紹了 XML-based layout 後,發現這是一個很方便,而且有用的 UI 安排方式。以圖1為例,我們現在想要做出一個應用程式,讓文字的超鍊結(hyperlink)可以被使用者點選,並自動呼叫瀏覽器連到該網站,這樣的應用程式該如何撰寫呢?請依以下步驟修改程式碼。 圖1:如何設計一個可點擊 URL link 的應用程式? View 的 XML 屬性 每一個 View 都有許多屬性,我們可以利用 XML 來描述每一個 View 的屬性,進而達到控制物件的效果。以 TextView 為例,有一個「android:autoLink」屬性可以控制「是否要自動將網址轉換為可點擊的 URL 文字」。 要怎麼知道每一個 View 都哪些屬性呢?這個時候就要祭出 Android SDK 的 documentation 了。以 TextView 為例,透過以下的說明,可以了解 TextView 有哪些屬性,以及該屬性的用途: http://code.google.com/intl/zh-TW/android/reference/android/widget/TextView.html#attr_android:autoLink 原來,只需要透過「autoLink」屬性,並將此屬性設定為「web」即可做出我們想要的功能。 修改...
jollen 發表於 January 5, 2009 11:08 PM
如果要繼續體驗 View 的樂趣,那麼「WebView」這個 View 無疑是最佳人選。android.webkit.WebView 是使用「WebKit」技術的 View,主要的用途是「顯示網頁」。使用 WebView,我們可以在 Android 應用程式裡顯示自已的 HTML 文件,或是線上的網頁。 接下來請依照以下步驟,建立我們的第二個 Android 應用程式「Hello Web」。 建立新專案: HelloWeb 建立一個新的 Android 專案,如圖1。 圖1: 建立 Hello Web 專案 並且撰寫 HelloWeb.java 程式如下: package com.moko.web; import android.app.Activity; import android.os.Bundle; import android.webkit.WebView; import com.moko.web.R; public...
jollen 發表於 January 8, 2009 4:51 PM
android.widget.TableLayout 是一個「排版」的類別,假設現在我們想要做出如圖1的文字排版效果,那麼使用 TableLayout 就是標準的做法。傳統寫程式排版的做法不是非常的方便,所以我們將採用 XML layout 方式來實作。 圖1: 文字並排顯示 建立新專案: HelloLayout 建立新的專案「HelloLayout」,並撰寫程式碼如下: package com.moko.layout; import com.moko.layout.R; import android.app.Activity; import android.os.Bundle; public class HelloLayout extends Activity { /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState)...
jollen 發表於 January 12, 2009 3:15 PM
到目前為止,我們都著重在 Activity 以及 UI 的介紹,在 Android 應用程式裡,有一種沒有 UI 的類別(android.app.Service),稱之為 Service。簡單來說,Service 是一個 background process(背景程序),透過背景程序,我們可以實作一些不需要 UI 的功能,例如:在背景撥放音樂。 以下是利用 Eclipse 環境自動產生的類別 'MokoService': import android.app.Service; import android.content.Intent; import android.os.IBinder; public class MokoService extends Service { @Override public IBinder onBind(Intent intent) { // TODO Auto-generated...
jollen 發表於 January 12, 2009 4:02 PM
上一個課程裡,我們實作了一個 Service 的類別稱為 MokoService,現在我們想要在 Activity 裡載入並啟動 MokoService 類別,讓它可以在背景執行,請依以下步驟完成這個任務。。 修改 AndroidManifest.xml 在 Package Explorer 視窗裡找到目前 Android 專案的資訊描述檔,檔名是 AndroidManifest.xml。這是一個用來描述 Android 應用程式「整體資訊」的檔案,每個 Android 應用程式專案都會有一個。在這裡修改 Androidmanifest.xml 的目的是為了「在我們的 Android 應用程式裡加入一個 Service 類別」,這樣才有辦法啟動 Service。修改後的內容如下,紅色的部份是新增的描述:。 <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.moko.hello" android:versionCode="1" android:versionName="1.0.0"> <application android:icon="@drawable/icon" android:label="@string/app_name" android:debuggable="true">...
jollen 發表於 January 19, 2009 10:45 AM
Activity 是一個有 UI 的類別,Service 則是一個沒有 UI 的類別。要知道 Activity 是否啟動,只要看看手機是否出現畫面即可;要知道 Service 是否有啟動,最容易的方式就是透過「除錯」的方式。以下我們實際以一個完整專案方式來對 Android 應用程式做除錯。 建立 MokoService 類別 點擊 Eclipse 的 File -> New -> Class 項目,利用 Eclipse 的自動新增功能,在先前的 HelloMoko 專案裡建立 MokoService 類別,如圖1。欄位「Superclass」應填入 android.app.Service。 圖1: 建立 MokoService 類別 修改 MokoService 實作 在新增的...
jollen 發表於 January 19, 2009 10:39 PM
AndroidManifest.xml 是一個用來描述 Android 應用程式「整體資訊」的設定檔。簡單來說,這是一個「自我介紹」檔,我們可以向 Android 系統「介紹」我們的 Android 應用程式,以便讓 Android 系統完整地了解我們的應用程式資訊。 在 [教學, #9] 中,我們提及:「在這裡修改 AndroidManifest.xml 的目的是為了『在我們的 Android 應用程式裡加入一個 Service 類別』,這樣才有辦法啟動 Service...」這個工作的目的是為了向 Android 系統做二項自我介紹。說明如下。 1. 應用程式「實作了一個 MokoService 類別」 <application android:icon="@drawable/icon" android:label="@string/app_name"> ... <service android:name=".MokoService"> ... </service> ... </application> 在 application 標籤裡加入...
jollen 發表於 April 12, 2009 11:46 AM
「Android Day Package -- Android 應用程式新手入門」整理了這陣子我在研討會的演講材料,包含: 簡報一份 Android 入門教學文件共11集 範例程式4例 因為研討會是一天的演講活動,因此這些內容很適合新手做為「學習 Android 應用程式」的入門教材,大約只需要一天的時間,就能初步了解 Android 的開發工具使用,並了解 Android 的應用程式模式,故取名為「Android Day Package」,期望能提供一個「Android 新手一天入門」的教學套件。請不吝指教。 簡報的部份是受零組件雜誌邀請,進行一天的 Android 演講活動,所特別製作的簡報;範例則是參考 Android SDK 所撰寫的實例,範例是配搭簡報進行實例講解所使用的程式碼。[下載 Android Day Package] 後,可搭配以下共11份教學文件學習;以下的教學文件是為製作簡報時的筆記,特別整理成一份教學文件與大家分享。 課程主題 Android Day Package 提供以下的課程主題。 1. 開放手機平台發展現況 (1hr) ‧開放手機平台陣營 ‧授權模式比較...
jollen 發表於 April 19, 2009 2:30 PM
LinuxDevices.com 報導了一則很酷的消息 [Android-based PMP to ship in October]。 一家名為 [GiiNii] 的公司,將在 10 月份開始銷售使用 Android 平臺的 PMP(portable media player);該公司在明年的 1 月份也會銷售 Android 平臺的 DPF(digital picture frame)。 (圖片來源:GiiNii) 這台名為 Movit Mini 的 PMP 實際上就是一個「MID」概念的產品,但 GiiNii 並不將 Movit Mini 稱為 MID,而是將它定位為 PMP。Movit Mini...
jollen 發表於 May 6, 2009 11:20 PM
上週六(5/2)舉辦「Android Day」訓練活動,上午的活動是「Android 的機會」議程,下午舉辦了一場免費的 Android 訓練課程。Android Day 訓練活動的目的除了希望可以認識朋友,並面對面與大家交換不同的想法外,也希望可以幫助對 Android 應用程式有興趣的朋友,能一天就入門 Android 應用程式設計。對於想初步了解 Android 應用程式設計方法的朋友相當有幫助;透過 Android Day 訓練課程希望能幫助大家節省一開始的自學時間。 上午的議程,由小弟我、高煥堂老師與 David(gOS 執行長)以自由論壇形式,與大家討論 Android 產品端與推廣方面的想法。由於 Android 的 middleware 技術(包含調校、移植等)對產品的發展是一個重要的技術能力,因此高煥堂老師提出一個 shared object(shared library)工作小組的計畫,此外,高老師也針對 middleware 的觀念做了一些說明;David 也從「授權」的角度來分析,為什麼採用 APL(Apache License)授權的 Android 平臺,比起過去以 GPL 授權為主的桌面 Linux 與...
jollen 發表於 May 10, 2009 9:58 PM
本週六將於北京舉行的「Android 技術大會」上發表有關「Android 移植」的技術演說,配合該演講,最近將陸續整理一些筆記以搭配講稿供與會朋友參考。 Android 的技術優點 Android 平臺的好處是「將開發者侷限在應用層(application level)」的開發,並透過一個設計良好的 application framework 將 library 層「包裝起來」。傳統 GNU/Linux 系統的「開源模式」是「從裡到外」全面開放,應用程式來自四面八方,每個應用程式底層使用到的 library 並不相同,這讓 Linux 平臺的軟體發展容易失控,造成 Linux distribution 上雖然收錄了豐富的應用程式,但相對的也要包山包海地納入非常多的 shared library。 Android 雖然也採用了其他 open source 的專案成果,但 Android 以很聰明的方式,解決傳統 Linux 開放手機平臺的「相依性」問題,這也是過去長久以來,匯整使用(leverage)開放源碼專案開發產品的大問題。Application framework 採用 Java 程式語言,並軟性的將開發者限制在 application level 是...
jollen 發表於 May 19, 2009 10:57 PM
中國版的 Android 系統 OMS 現身 (China's Android OS,OMS - Open Mobile System)。 日前一則新聞 [大陸OPhone商機 台商幕後推手] 以及 [中移動5月中下旬發佈Ophone手機 主介面已可上網流覽] 報導了中國移動(China Mobile)所推出的 OPhone 手機,採用 OMS 作業系統。本週在北京與 OMS(Open Mobile System)的開發商「播思通讯(BORQS)」人員餐敘,OMS 的開發者也拿出了 OMS 的參考設計(reference design)實機讓現場朋友實機操作。 OMS 採用的正是 Google 的 Android 作業系統,如同上述報導所提,OMS 是 BORQS 與...
jollen 發表於 May 22, 2009 10:55 AM
上週受邀至「首屆亞太區 Android 技術大會」發表演說,由於大會希望能多著重在技術層面的主題,因此整理了過去研究 Android/FreeRunner 的一些資料,並將「重點」部份做了一次概念性的說明。Android 的分支(branch)是以「產品」的概念做維護,因此若在目前 Cupcake 能支援的平臺(architecture)上做移植的話,是一個較簡單的工作,只需要在 vendor/ 裡新增自已的 product 並修改 AndroidBoard.mk、AndroidProducts.mk 以及 BoardConfig.mk 即可完成一個 Board/Product 的新分支。 關於底層的部份,以 armv4(如 s3c2443)的 architecture 為例,將重要的工作項目做了整理式的說明。在此提供簡報電子檔下載 [Android Porting Highlights]。...
jollen 發表於 June 3, 2009 5:21 PM
Android應用程式的UI可以使用XML來定義,這個部份在前面的教學裡介紹過。要定義Android應用程式的選單,我們同樣可以使用XML來做描述,請看以下的說明。 建立 Menu 步驟 1. 建立選單的XML檔 在Android專案的res/目錄下新增一個menu/子目錄,然後建立options_menu.xml文件。 圖1: 建立menu/目錄 圖2: 建立options_menu.xml文件 2. 以XML定義選單內容 在options_menu.xml檔案裡,定義我們想要的選單內容。以下是一個範例: <menu xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@+id/new_message" android:title="New Message" /> <item android:id="@+id/quit" android:title="Quit" /> </menu> 3. 將選單加入應用程式 要如何在應用程式啟動時加入我們定義好的選單呢?在onCreateOptionsMenu()事件裡以MenuInflater類別將定義好的選單加入應用程式: public boolean onCreateOptionsMenu(Menu menu) { MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.options_menu, menu);...
jollen 發表於 June 4, 2009 12:20 AM
Toast是Android提供「快顯訊息」類別,使用時請import以下套件: import android.widget.Toast; 這是一個很好用的類別,特別是在初步建立Android應用程式的控制或行為時,可以輔助我們進行初步的測試工作。 配合上述的選單範例,我們將onOptionsItemSelected()回呼函數實作修改如下: public boolean onOptionsItemSelected(MenuItem item) { int item_id = item.getItemId(); switch (item_id){ case R.id.new_message: Toast.makeText( this, "Please enter your message." + " Your message is at max 255 characters.", Toast.LENGTH_LONG).show(); break; case R.id.quit: Toast.makeText( this, "Going...
jollen 發表於 June 10, 2009 2:56 PM
最少的元件、最舒適的介面 自從有了圖形化應用程式之後,對話盒(dialog)一直是元老級的元件(widget);智慧型手機開始流行後,對話盒仍然是手機介面的重要圖形元件。 在Apple的iPhone問世後,觸控螢幕(touch screen)一直是智慧型手機的標準規格,因此傳統的滑鼠點擊(click)式介面,並不完全適合手指觸控的操作方式,再加上手機觸控螢幕尺吋較小,因此手機應用程式的介面設計,已經與傳統的桌面環境相當不同。 Android的元件庫考量了小尺吋的觸控螢幕,在基本元件的設計上,Android也為使用者做了很體貼的考量。以Android手機應用程式來說,經常使用的元件已經不再像過去的點擊式系統那麼多又複雜;以使用性的角度來看,常被使用的元件如下: * 選單(Menu) * 對話盒(Dialog) * 快顯訊息(Toast) 使用以上三個元件,以及其「變化形」,就能建構一個好用的應用程式介面;再加上Android針對上述的手機操作特性,對其元件庫做了很好的使用設計,因此使用很少的元件,也能提供使用者一個舒適好用的操作介面。 何謂對話盒? 對話盒,故名其思,是一個讓應用程式與使用者「對話」的元件。應用程式透過對話盒與使用者進行下述的對話: * 詢問問題:使用者回答 Yes/No * 詢問偏好:使用者選擇自已偏好的項目,可以是單選,也可以是複選 * 說明狀態:讓使用者知道應用程式目前的狀態,例如:顯示「處理中」、「載入中」等訊息 Android提供的對話盒物件為android.app.Dialog,實作上繼承自Dialog的AlertDialog物件是最基本的對話盒物件。使用AlertDialog對話盒,可以詢問使用者問題,也可以詢問使用者偏好。接下來介紹AlertDialog對話盒的設計方法。 建立AlertDialog對話盒 延續「HelloMenu」範例,現在我們想要加入以下的使用情境: * 使用者按下Menu鍵 * 使用者觸壓 “New Message” 選項 * 出現對話盒、詢問使用者 “Yes/No” 由以上的使用情境來看,應該在onOptionsItemSelected()裡判斷到R.id.new_message項目時,在UI上建立一個對話盒。以下是修改後的onOptionsItemSelected()完整程式碼,完整範例名稱為HelloAlertDialog: public boolean onOptionsItemSelected(MenuItem item) {...
jollen 發表於 June 17, 2009 10:46 AM
CNET ASIA上的一則報導[Android to replace Garmin-Asus' current Linux platform]指出,Garmin-Asus的nuvifone G60將改採Android作業系統。 (圖片來源:CNET) 2009年二月,Garmin與Asus正式宣佈策略聯盟,並以「Garmin-Asus」雙品牌策略進行行銷。nuvifone G60是Garmin-Asus雙品牌行銷策略下的第一個產物,nuvifone G60則是以導航功能為主軸的手機。 根據報導指出,Garmin-Asus現有的Linux平臺將只使用在G60裝置上,未來的裝置會採用Windows Mobile或者是Android作業系統。 如同Garmin的PND產品都是採用Linux作業系統一樣,原本nuvifone G60也計畫採用Linux作業系統,不久前,在engadget上的報導也出現實機照片;但是,隨著CNET這則報導的出現,整個開發計畫是否有了改變,頗令人好奇。 Android原本就對Google Map有很好的支援,再加上nuvifone G60是以導航以及地圖應用為主的手機,若是改採Android作業系統,也是一個合理的做法。 * Update: 2009/6/19...
jollen 發表於 June 18, 2009 11:15 PM
學會產生基本的UI後,接著就要學習UI的事件處理(UI Events),才能讓UI與使用者「互動」。 什麼是事件監聽器(Event Listener) UI的使用者事件處理,即View如何處理使用者的操作,是一個重要的課題。View是重要的類別,它是與使用者互動的前線;在Android框架的設計中,以事件監聽器(event listener)的方式來處理UI的使用者事件。 Android框架提供了非常良好的UI事件處理機制。先前的教學提到,View是繪製UI的類別,每個View物件都可以向Android框架註冊一個事件監聽器。每個事件監聽器都包含一個回呼函數(callback method), 這個回呼函數(callback method)主要的工作就是回應或處理使用者的操作。 Event Listener: 以Click Listener為例 以「使用者觸碰(touch)」的動作來說,當View要處理使用者觸碰的事件時,就要向Android框架註冊View.OnClickListener事件監聽器;當「touch」事件發生時,Android框架便回呼事件監聽器裡的回呼函數。 View.OnClickListener是click listener,故名思意,這是UI的「Click動作監聽器」;當使用者對View進行Click操作時(即觸控畫面上的UI元件),Android框架便會回呼這個View.OnClickListener的回呼函數。 View.OnClickListerner的回呼函數為OnClick()。 這裡所提到的監聽器泛指event listener,主要用來「監聽」使用者的各種動作。除了View.OnClickListener外,Android框架還有以下的event listener(及其callback method): View.OnLongClickListener: onLongClick() View.OnFocusChangeListener: onFocusChange() View.OnKeyListener: onKey() View.OnTouchListener: onTouch() View.OnCreateContextMenuListener: onCreateContextMenu() 另外一種處理UI事件的機制為事件處理器(event handler),event handler與event listener是不一樣的二種處理機制。在自訂Android component的教學裡,再介紹這個部份。...
jollen 發表於 June 18, 2009 11:18 PM
Event Listener的用法: 以Click Listener為例 以Android所提供的View.OnClickListener來說明程式實作方法。一個較為良好的實作方法是在我們的Acitivty類別裡實作View.OnClickListener介面,即: import android.view.View; public class HelloClickListener extends Activity implements View.OnClickListener { ... } 每一個View都可以註冊一個event listener,當Android框架收到「click」事件後,便回呼event listener的callback method。以Button類別(按鈕元件)為例,當我們想要處理使用者觸控按鈕的事件時,就要呼叫Button類別的setOnClickListener()方法來註冊click listener。上述的實作方方法是,直接在我們的Activity類別HelloClickListener裡實作View.OnClickListener,因此上述Button類別的click listener為「this」。 上述的實作觀念,可用圖1來表示。 圖1: HelloClickListener類別實作View.OnClickListener介面 註冊click listener的程式碼如下: public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); Button button = (Button)findViewById(R.id.btn); button.setOnClickListener(this);...
jollen 發表於 June 20, 2009 3:20 PM
在這篇教學裡,我們將用一個非常簡單的範例來初步體驗Android的「styles」功能。 什麼是樣式(Styles)? Android的樣式設計(style)是一個很重要的功能,因為它可以讓應用程式裡的元件(widget)「長」得跟別人很不一樣。樣式設計的使用規定如下: 在Android專案裡以XML資源檔來定義「樣式」 一個Android專案可以定義多個樣式 讓widget套用其中一個樣式 Android的styles功能,主要的對象是widget,樣式是為了套用到widget上;另外Android還提供佈景(theme)功能,可以做更大範圍的套用。 如何定義樣式 定義樣式的方式如下: 1. 在Android專案的「res/values」資料夾裡建立styles.xml樣式定義檔。如圖1。 圖1: 建立styles.xml 2.在styles.xml裡定義樣式,以下是一個範例: <?xml version="1.0" encoding="utf-8"?> <resources> <style name="myText"> <item name="android:textSize">18sp</item> <item name="android:textColor">#880</item> </style> </resources> styles.xml的寫法說明如下: 1. 在 <resource>標籤裡定義資源項目, <style>標籤用來定義樣式資源 2. <style>的name屬性定義此樣式的名字,widget使用此名字以套用樣式 3. <item>標籤定義此樣式的內容 4. <item>的name屬性為android:textSize時,表示定義此樣式的字體大小,在此設定字體大小為18sp 5. <item>的name屬性為android:textColor時,表示定義此樣式的字體顏色,在此設定字體顏色為#880(RGB) 6....
jollen 發表於 June 21, 2009 1:30 PM
上一節提到佈景(theme)是可以大範圍套用的UI美化功能,其套用範圍為「整個螢幕」,從程式碼的角度來看,佈景可以套用到以下二個範圍: 整個應用程式(application) 整個activity 接下來,我們以一個很簡單的例子,來說明如何套用佈景到application。在一些應用,我們可能不想要顯示視窗標題(title),怎麼做出這個功能呢?利用佈景設定的方式即可達成。以下是實作方法。 在styles.xml裡加入以下內容: <?xml version="1.0" encoding="utf-8"?> <resources> <style name="myTheme"> <item name="android:windowNoTitle">true </style> </resources> 修改AndroidManifest.xml,在標籤裡加上「theme」屬性: <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.moko.hellotheme" android:versionCode="1" android:versionName="1.0.0"> <application android:icon="@drawable/icon" android:label="@string/app_name" android:theme="@style/myTheme"> <activity android:name=".HelloTheme" android:label="@string/app_name"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity>...
jollen 發表於 July 10, 2009 5:46 PM
App Widget是Cupcake(Android 1.5)所提供的一個功能,這是一個很實用而且能有很大創意想像空間的功能。什麼是App Widget呢?請看底下的操作示範。 在Android桌面長壓約3秒,出現一個選單,如圖1。 圖1:新增項目至桌面 2. 選擇「Widget」,加入”HelloWidget” 圖2:加入自行設計的Widget 桌面上出現了一個「Widget」 圖3:在Android桌面上出現我們自已設計的App Widget 圖4:加入了音樂撥放器App Widget至桌面 這就是App Widget的應用,可以將一個小塊程式(program piece)嵌入到桌面上。App Widget也是一種UI組件,先前所介紹的TextView、WebView等也泛稱為Widget,二者在應用上的差異該怎麼思考呢?以下是幾點看法: 1. App Widget是有生命的UI組件,他會自動更新本身的內容 2. Widget是沒有生命的UI組件,它不會自我更新,只能等待使用者的操作 3. 應用上,App Widget能提供不斷更新的內容,很適合用來設計天氣、時鐘、新聞等主動式應用程式 4. Widget應用上只用來製作UI,而UI因為只能等待使用者來操作,所以過去我們所撰寫的Android應用程式都是屬於被動式應用程式 讓App Widget能「主動」更新自身內容的方法是透過一個「時間觸發裝置」,Android框架會根據我們設定的時間間隔,不斷地callback我們的App Widget。後續將再說明App Widget的做法,並解釋這個部份。...
jollen 發表於 July 10, 2009 6:00 PM
Android的ApiDemo範例庫提供了一個很不錯的App Widget範例;不過,對初學者來說,這個範例可能稍嫌繁瑣。在這裡另外提供一個HelloAppWidget範例如下: /* 範例:HelloAppWidget.java */ package com.moko.hellowidget; import android.appwidget.AppWidgetManager; import android.appwidget.AppWidgetProvider; import android.content.Context; import android.widget.RemoteViews; public class HelloAppWidgetProvider extends AppWidgetProvider { public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { final int N = appWidgetIds.length; for (int i=0; i<N; i++)...
jollen 發表於 July 11, 2009 11:46 PM
以下分別說明HelloAppWidget的實作,以及技術重點。 appwidget_provider.xml-描述App Widget屬性的資源檔 這個檔案主要描述App Widget的幾個屬性: 長度(width) 高度(height) 更新頻率 UI layout檔 以下是appwidget_provider.xml的完整內容: <?xml version="1.0" encoding="utf-8"?> <appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android" android:minWidth="85dp" android:minHeight="30dp" android:updatePeriodMillis="3000" android:initialLayout="@layout/main" > </appwidget-provider> 說明如下: 1. <appwidget-provider>標籤定義App Widget的屬性 2. android:minWidth定義寬度 3. android:minHeight屬性定義長度 4. android:updatePeriodMillis定義App Widget的更新頻率,Android框架每隔這段時間,會callback AppWidgetProvider類別的onUpdate()事件;此屬性的時間單位為1/1000秒,以上述的定義來說,等於3秒鐘的時間(3000/1000=3) 5. android:initialLayout屬性指定此App Widget的UI layout定義檔,”@”符號在Android的XML定義檔案,代表「目錄」之意,因此”@layout/main”表示「layout目錄下的main.xml檔案」 以上共四項屬性,是App Widget最基本的屬性,必須良好定義。其中android:updatePeriodMillis屬性可省略,代表不更新App...
jollen 發表於 July 11, 2009 11:52 PM
main.xml-描述App Widget的UI 這個檔案在前面的教學裡介紹過了,它的主要用途是描述UI。我們想要設計一個能嵌進桌面,並顯示文字的App Widget,因此必須使用Android的TextView類別。 以下是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="wrap_content" android:layout_height="wrap_content" android:id="@+id/appwidget_text" android:textColor="#ff000000" /> </LinearLayout> 我們的App Widget使用LinearLayout來安排佈局,而UI為一個TextView物件。在這裡,我們將此TextView物件的id定義為”appwidget_text”。...
jollen 發表於 July 11, 2009 11:54 PM
HelloAppWidgetProvider.java-實作App Widget供應者 程式碼已經在前面的教學裡展示過了,當時只提到一個很基本的重點:使用AppWidgetProvider類別。在這裡,我們先說明設計的部份,才能了解程式如何實作。程式碼的說明稍後再做補充。 圖1:設計App Widget 從圖1的設計裡可以知道(配合查詢Android Reference文件),當程式繼承了AppWidgetProvidr類別後,也繼承了二個主要的method: onUpdate() onDelete() App Widget使用AppWidgetProvider類別,即App Widget的「供應者」,供應什麼東西給誰呢?可以想像成是,我們的應用程式,供應App Widget給Android桌面。 到目前為止,我們知道只需要AppWidgetProvider即可實成一個很陽春的App Widget。而完整的App Widget應該包含三個單元(unit): 1. Provider:此處說明的「供應者」 2. Configure:App Widget的設定單元,用途是提供一個「介面」供使用者輸入資料 3. Receiver:繼承自BroadcastReceiver的單元,即廣播接收器,用來接收Android框架所送出的事件(event) 在後續的教學裡,我們會繼續說明configure與receiver單元的觀念與實作。...
jollen 發表於 July 11, 2009 11:57 PM
AndroidManifest.xml-加入App Widget的程式資訊 AndroidManifest.xml檔案的用途在前面的教學裡介紹過了。以下是其完整內容: <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.moko.hellowidget" android:versionCode="1" android:versionName="1.0"> <application android:icon="@drawable/icon" android:label="@string/app_name"> <receiver android:name=".HelloAppWidgetProvider"> <meta-data android:name="android.appwidget.provider" android:resource="@xml/appwidget_provider" /> <intent-filter> <action android:name="android.appwidget.action.APPWIDGET_UPDATE" /> </intent-filter> </receiver> </application> <uses-sdk android:minSdkVersion="3" /> </manifest> 說明如下: 1. 在<application>裡加入<receiver>標籤,指定android:name屬性為主要的provider類別,即”HelloAppWidgetProvider”,請注意,「.」表示後面的字串為一個「類別名稱」,不要忽略了這個重要的小數點 2. 在<receiver>裡加入<meta-data>標籤,指定android:resource屬性為App Widget的資源檔名稱,以我們的範例來說,就是「@xml/appwidget_provider」,即「xml目錄下的appwidget_provider.xml檔案」 3. 在<receiver>裡加入<intent-filter>標籤,讓我們的App Widget可以接收APPWIDGET_UPDATE事件(event)...
jollen 發表於 July 12, 2009 2:10 PM
HelloAppWidgetProvider.java 程式碼說明 圖1: HelloAppWidgetProvider的設計 圖1是目前我們的HelloAppWidget範例設計,說明如下: onUpdate(): 收到ACTION_APPWIDGET_UPDATE廣撥時,框架會callback此method onDelete(): 收到ACTION_APPWIDGET_DELETE廣撥時,框架會callback此method AppWidgetManager: 管理App Widget的類別 先前,在AndroidManifest.xml裡我們讓HelloAppWidgetProider類別可以接收ACTION_APPWIDGET_UPDATE廣撥事件;ACTION_APPWIDGET_UPDATE是最主要的App Widget事件,當AppWidgetProvider被要求為App Widget提供”RemoteView”時,就會收到這個事件。 什麼是RemoteViews? 什麼是RemoteView呢?先看一下框架的設計,如圖2。 簡單來說,「RemoteViews」就是表示UI的類別。res/layout/main.xml描述了應用程式的UI,UI裡當然包含許多組件(Widget),而在先前的教學裡講到了一個觀念「Android應用程式的UI就是一個View tree」,view tree就是「View Hierarchy」。 總結來說,RemotViews是一個用來表示View Hierarchy的類別。透過RemoteViews可以找到UI裡的每一個組件。 圖2: RemoteView的設計(點擊看全圖) 程式說明: HelloAppWidgetProvider.java onUpdate()的程式實作: public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { final int N...
jollen 發表於 July 16, 2009 12:27 PM
什麼是Intent(意圖)? 強大的事件處理「Intent」(意圖)是Android很強大的一種機制。 在 Android 應用程式框架中,有一個非常聰明的事件處理機制,稱之為「Intent」。Intent(意圖)的作用與事件(event)很像,但與傳統的事件處理仍然有些差異。傳統的事件處理,講求的是「處理者(handler)的觸發」,當一事件發生時,便callback讓事件的處理者,或是直接將該事件轉送(forward)給應用程式,由應用程式決定處理方式。 在「Intent」這樣的事件處理觀念裡,Android 試圖將事件解釋為「應用程式的意圖」或是「使用者的意圖」,並試著去解釋該意圖的目的,若 Android 系統本身能理解應用程式的意圖,便會「自行」去處理該意圖所應執行的工作。 Android的做法是,讓每個意圖(Intent)都帶有一個動作(action),並根據不同的動作去行動。 關於前述教學提到的Intent 在前面的教學裡,我們用到二次Intent如下: 1. 自行定義一個Intent、設定Service可接收此Intent,並透過「送出Intent給框架」的方式,請框架啟動該Service 2. 使用Android內部定義的動作「ACTION_VIEW」,來「檢視」(view)一個「URL」資料,當框架看到內部定義的ACTION_VIEW動作時,便「自行」處理該Intent;處理的方式是啟動WebView並連上網站 以前述的教學為例,使用內建的動作“ACTION_VIEW”就可以很容易做出一個「啟動瀏覽器(WebView類別)上網」的應用程式。 透過這二個例子我們知道,Intent的動作可以是自行定義與框架內部定義二種。Android框架的Intent有很多方便實用的「內建動作」,以下我們說明Android內建Intent的美麗之處。 Android內建的Intent Action Android的框架確實是讓每個Intent都包含了一個動作,就稱為action。 為了讓大家更容易了解Intent的基本觀念,我們採用「體驗」的方式來說明如何使用內建的Action。現在,我們列舉以下三個情境,並分別實作其範例: HelloIntentDialer: 啟動撥號器(dialer)並撥號 HelloIntentMusic: 使用者按下「Select Music」後,可以由音樂清單裡選擇音樂並撥放 HelloIntentWallpaper: 啟動Android內建的「背景圖選擇器」,讓使用者更換背景 第二個範例”HelloIntentMusic”其實是ApiDemo裡的範例,而且是很容易能了解Intent內涵的好程式。 除了action外,Intent還可以包含另外一項資訊「data」。 Intent的action指定這個Intent的「動作」是什麼,框架會依指定的動作進行處理;有些action可以附帶一筆資料,這個資料是以Uri的格式撰寫,在HelloIntentDialer的範例會再做說明。 內建的Intent有哪些呢?請參考Android Reference Guide中的Intent類別說明。上述三個範例分別使用以下三個action: 1. ACTION_CALL: 撥號 2. ACTION_GET_CONTENT:...
jollen 發表於 July 17, 2009 3:13 AM
前言 能取得Android OS原始碼,並修改裡頭的內容,有時候也頗有樂趣。最近和幾位朋友聊到「Android框架的改造」,以及如何吸引對Android框架技術有興趣的同好一起交流的議題;我個人認為,一開始如果能丟出一個比較有樂趣的議題,或許可以有拋磚引玉的效果。 上週在北京進行Android培訓課程時,與eoeAndroid社群也進行了想法的交流,由於大家都體認到Android底層技術的重要性及其價值,而且eoeAndroid社群裡也有許多技術好手,所以就和eoeAndroid的創辦人靳岩兄有了一個共同主持研究Android底層技術「同好小組」的想法,希望能透過社群的方式,集合大家的智慧,一起把底層技術研究清楚。 因為要讓大家能有焦點,所以「發題」很重要,這個工作就由落在我身上了。由於第一次希望題目能簡單,並且有趣一點,至少要能達到發球的效果,吸引大家開始關心Android底層技術,所以原則是:希望能用最簡單的方式、讓大家體驗修改底層的樂趣。 題目說明: Launcher 第一次的題目是「Launcher」的修改。 Launcher就是Android的應用程式啟動器,Launcher的功能還包含:桌面的切換、應用程式快捷(shortcut)功能、背景圖(Wallpaper)功能等等。因此,修改Launcher可以改變一些很深層的UI功能。 在Android的桌面最下方,有一個圖示,按下後可以拉出應用程式圖示清單,這是Launcher提供的功能。這一次,因為我們覺得這個Launcher的圖示太製式化了,越看越不好看,所以想要修改一下,換張圖,要怎麼做到呢? 範例展示 例如,圖1是原始的圖示;圖2是修改後的圖示。 圖1: 原始圖示 圖2: 幫Launcher妝扮一下 實作說明 1/4: 取得Android原始碼與EeePC移植 這個功能並不難做,事實上,完全不用寫程式。只要把圖檔重做就可以了。只不過前提是,要知道: 1. 如何取得Android OS原始程式碼 2. 如何編譯Android OS 最簡單的做法是: 1. 下載Android原始碼後、取得EeePC的移植(product) 2. 編譯「TARGET_PRODUCT」為eee_701 3. 由於Launcher都是用Java語法寫成的,所以不會有架構(ARM/x86/...)的問題,編譯後可以取得Launcher.apk;APK套件是不分處理器平臺的 先學會如何由Android原始碼編譯出eee_701的image,才有辦法繼續進行。 實作說明 2/4: 修改圖檔 在Android原始碼的 packages/apps/ 目錄裡,存放了Android內建的應用程式原始碼,Launcher是Android的一個應用程式,所以從這裡找到它的原始碼,並進行修改工程。...
jollen 發表於 August 7, 2009 11:25 AM
HelloIntentDialer是一個自動撥號程式,執行時會自動撥號到指定的電話。這樣的程式要怎麼寫呢?先看到HelloIntentDialer.java的完整程式如下: package com.moko.hellointentdialer; import android.app.Activity; import android.content.Intent; import android.net.Uri; import android.os.Bundle; public class HelloIntentDialer extends Activity { /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); Intent dial =...
jollen 發表於 August 7, 2009 11:13 PM
上一篇教學提到如何利用Intent實作「自動撥放」程式。而另外一個較具代表性的Intent應用就是「內容選擇器」。例如,要怎麼實作一個音樂撥放機呢?先說明音樂撥放器HelloIntentSelect範例的使用情境如下: 1. 執行HelloIntentSelect後,出現一個「撥放音樂」的按鈕 2. 按下按鈕後,選擇一個音樂檔撥放 實作「選擇音樂檔」的做法是使用Intent的「chooser」觀念。程式做法如下: 1. 建立action為ACTION_GET_CONTENT的Intent: Intent intent = new Intent(Intent.ACTION_GET_CONTENT); 2.設定Intent的mime type,例如:設定Intent的mime type為聲音檔案: intent.setType("audio/*"); 3.建立內容選擇器並送出Intent: startActivity(Intent.createChooser(intent, "Select music")); 以上的程式是根據Android的Reference Guide寫出來的。當Intent action為ACTION_GET_CONTENT時,表示要根據mime type來「取得內容」(get content),因此呼叫setType()方法,來定義內容的mime type。 定義好mime type後,再呼叫createChooser()方法來產生能取得此mime type內容的「選擇器」,簡單說,就是一個「檔案選取程式」。 利用Android的Intent觀念,我們以不到十行的程式碼實作了一個音樂撥放器。 Action的屬性寫法與常數寫法 Intent的action寫法有二種。第一種寫法是屬性(attribute)寫法,例如第一個HelloIntentDialer範例: dial.setAction("android.intent.action.CALL"); 在「android.intent.action」套件(package)裡,定義了action的屬性。第二種寫法是常數寫法,例如第二個HelloIntentSelect範例: Intent intent = new Intent(Intent.ACTION_GET_CONTENT);...
jollen 發表於 August 22, 2009 10:52 PM
Android提供「SET_WALLPAPER」的內建Intent,當框架收到這個Intent時,就會啟動「背景圖選擇器」,讓我們選取新的背景圖。送出SET_WALLPAPER intent的程式寫法如下: Intent intent = new Intent(Intent.ACTION_SET_WALLPAPER); startActivity(Intent.createChooser(intent, "Select Wallpaper")); 根據Reference Guide的說明,SET_WALLPAPER會啟動一個內容選擇器,所以同時地,我們先呼叫createChooser()方法建立一個內容選擇器後,再送出Intent。 完整程式碼: HelloIntentWallpaper.java package com.moko.hellointentwallaper; import com.moko.hellointentwallaper.R; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.widget.Button; public class HelloIntentWallpaper extends Activity implements View.OnClickListener { /**...
jollen 發表於 August 22, 2009 11:05 PM
什麼是NinePatch圖檔 NinePatch是一種「可延展」的PNG圖檔。NinePatch圖檔的用途是製作「可隨文字大小縮放」的圖片,如圖1。 圖1: 文字背景可隨著文字大小縮放 NinePatch是很有用的圖片格式,可做為widget的「背景圖」。如圖1的範例,其應用程式的設計如下: 文字部份使用TextView元件 使用TextView的XML attribute來設定文字大小 使用TextView的XML attribute來設定一張背景圖 使用NinePatch圖片做為背景圖,如此一來背景圖就可以隨著文字大小縮放 首先,第一個工作就是「製作NinePatch圖檔」,方式如下。 Step 1. 準備一張原始的PNG圖檔,如圖2。 圖2: 原始PNG圖檔(arrow.png) Step 2. 啟動Android提供的draw9patch工具,直接執行Android SDK tools/目錄下的draw9patch執行檔即可,如圖3。 圖3: Android SDK提供的draw9patch工具(點擊看原圖) Step 3. 開啟原始PNG圖檔,編輯圖檔,如圖4。 圖4: 開始編輯圖檔(點擊看原圖) 如何編輯NinePatch圖檔 NinePatch圖檔的製作方式是「繪製二條線」,分別在原始圖檔的上方與左方繪出二條「黑線」,黑線所交集的區域即為「可延展」區域。如下圖的粉紅色區域。 圖5: 定義延展區 「可延展區」是Android框架用來擺放文字的區域,換句話說,文字(TextView)只會被放置在粉紅色區域,並且擺放的原則是「對準粉紅區域的中心點」,即上下置中、左右也置中。非「可延展區」,即綠色部份,並不會隨著文字的大小縮放延展。所以: 1. 綠色區域是固定大小區域 2. 粉紅色區域是可延展區域、文字擺放於此 圖中的「二條黑線」是怎麼畫出來的呢?方式如下。...
jollen 發表於 August 29, 2009 11:36 AM
Android校園計畫 產學官三界過去在Android的發展做了很多腦力激盪的工作,這是一個很好的現象,有助於Android熱潮的延續,以及各界對Android作業系統的重視。提到Android研發能量的建立,最根本的治理方式是「深耕校園」。 因此,現階段要務是「深耕校園」。實際做法建議是「建立種子」。建立種子師資或種子學生,透過導入課程至大學課程的方式,讓大一與大二的學生「認識」並「開始接觸」Android作業系統;種子學生的建立,可以鎖定大三以上、研究生或是以實驗室為單位,做為培訓對象。這個階段的做法,可以建立採取「種子培訓營」的方式進行。 學生如果能被適當的訓練,就能將把創造力,或是想像力,轉換成「具體」的成果。一個實際的例子是,如果能訓練非資訊本科系的學生撰寫Android應用程式,學生才能有能力把想法轉換成「程式原型」、才能展現創意。因此「深耕校園」的目標應該是要更「普及」,而不是只導入本科系。 活動詳情可參閱嵌入式軟體聯盟網站,以下是課程資訊。希望藉由自已在教育訓練方面的經驗,貢獻棉薄之力。 課程簡介 本課程的目的是培訓大專校院之Android種子教學師資。課程針對Android系統,由底層框架、驅動程式、移植、到應用開發,做一完整的介紹,並利用OpenMoko FreeRunner手機為實驗平臺,實際動手實作。整個課程設計以符合業界實際需要為重點,藉由本課程之培訓,讓學校能充實Android研發能量,未來達到產學結合的效果。 時間:98年9月7日 (星期一) 至9月10日 (星期四) 地點:清華大學資訊電機館資工系3F 328室 資格:國內各大專校院教師或學生,對Android系統之教學及開發有濃厚興趣者 名額:40人 費用:NT$ 2,500 (含午餐、設備使用費、講義;報名後通知繳費) 主辦單位:教育部顧問室嵌入式軟體聯盟、清華大學電腦與通訊科技研發中心、清華大學資訊工程學系 協辦單位:Jollen’s Consulting、清華大學OpenLab 聯絡人: 吳少文小姐 Tel: 03-5742410 E-mail: swwu@mx.nthu.edu.tw...
jollen 發表於 September 8, 2009 1:58 AM
第一天的「Android種子培訓課程」以應用開發為主軸,介紹了Android應用程式入門的課程。現場有許多大學的老師,因此在課程進行中,特別給了一些建議。針對Android應用程式入門教學來說,做「API走訪式」的教學比較無法切中正題,而且也讓課程顯得乏味。因此,我給了二點小建議: 1. Android應用的教學,以「應用程式的模式」為重心,因為Android應用程式的入門重點在於Activity/Service、R.java、XML layout、XML attributes、View(UI)、Intent等「模式」的觀念,所以最好不要採取API介紹式的教學方法 這裡的所提的「模式」即「撰寫程式」的方法。 2. 透過Android應用程式建立對框架(Framework)的基本認識。Android作業系統的一大重點在於「框架的設計」,而對應用程式進行較深度的分析,是了解框架設計的一個好方法。 例如,今天在課堂中所提到的「應用程式向框架取得(get)物件(object)」,而不是「應用程式自行建立物件("new"一個object)」的觀念。另外一個觀念,則是「應用程式要避免建立物件」,這是Android Dev Guide提到的「為效能而設計」的第一個條文。 第二天的課程將會開始介紹Android開發平臺,並展示一些「Lab」範例。...
jollen 發表於 September 20, 2009 10:39 PM
上一篇日記介紹了「如何製作NinePatch圖檔」,因此有讀者問到「如何寫程式」,因此特別補上這篇教學。 開始寫程式: HelloNinePatch 範例HelloNinePatch的實作方式如下。 Step 1. 建立一個新的Android專案,命名為HelloNinePatch。 Step 2. 將arrow.9.png托曳(drag)到HelloNinePatch專案裡的「res/drawable」目錄下。如圖1。 圖1: 將arrow.9.png放進res/drawable資料夾 Step 3. 修改UI(res/layout/main.xml),設計出上一篇教學(#30)裡的圖2畫面。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" > <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="small world" android:textSize="12sp" android:background="@drawable/arrow" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="big world" android:textSize="24sp" android:background="@drawable/arrow" />...
jollen 發表於 October 8, 2009 2:05 AM
Android 的 HAL(硬體抽像層)是 Google 因應廠商「希望不公開源碼」的要求下,所推出的新觀念,其架構如下圖。雖然 HAL 現在的「抽象程度」還不足,現階段實作還不是全面符合 HAL 的架構規劃,不過也確實給了我們很好的思考空間。 圖1:Android HAL 架構規劃 這是 Patrick Brady (Google) 在2008 Google I/O 所發表的演講「Anatomy & Physiology of an Android」中,所提出的 Android HAL 架構圖。從這張架構圖我們知道,HAL 的目的是為了把 Android framework 與 Linux kernel 完整「隔開」。讓 Android 不至過度依賴 Linux kernel,有點像是「kernel independent」的意思,讓...
jollen 發表於 October 14, 2009 6:17 PM
在上一篇日記裡,我們介紹了Android HAL的大概念。接下來,將慢慢地進行細部的分析與研究。首先,我們先針對HAL的現況先做討論,後續再針對HAL的設計提出觀念。 圖1:採用Service架構與不採用Service架構 如圖1,應用程式存取驅動程式的過程,可區分為以下二種: 採用Service架構方式 不採用Service架構方式 採用Service架構方式是比較標準的做法,即圖上藍色線的部份;紅色線的部份為非Service架構式的做法。先前,在「Android 驅動開發關鍵技術:HAL及移植要領」演講中最後所提出的一個LED範例,即是一種非架構式的做法,簡報上有一段範例程式碼,歡迎下載參考。 Android HAL Introduction: libhardware and its legacyView more documents from Jollen Chen. 採取Service架構的方式,是建議的做法,當然因為這是標準架構,也應該採用。 Service在Android框架裡的角色是「存取底層硬體」,往上層的話,可以和應用程式溝通。因此,採用標準的Service做法,好處是在資料存取(data communication)的處理較為系統化。這方面,Android提供了標準的處理架構,後續再進行討論。 圖上的「core libraries」即是Service程式碼的實作,也就是,Android應用程式透過JNI(Dalvik)來到Service這一層,再透過Service載入*.so檔;而非標準做法則是讓應用程式直接透過JNI來載入*.so檔。 不使用Service架構 紅色的過程,因為不使用Service架構,因此「框架整合」的工作量比較小,甚致大部份的實作都不需要改動框架本身。這樣的做法,就有點像是「跳過framework」的方式;相對的,此時應用程式開發者需要考慮的設計議題就比較多。 例如,當遇到block operation時,是否需要獨立的Java thread來處理?...
jollen 發表於 November 27, 2009 1:59 AM
前二篇教學提到「採用Service架構整合HAL的做法」。這裡再針對HAL如何採用Service架構與框架整合做一個概念的介紹。 Android的Service分為二種:Android Service與Native Service。 Android Service Android Service又稱為Java Service,是實作在框架層(framework)裡的「Server」。這裡所講的「Service」是System Service,又稱為Server,與應用程式設計上所討論的Service(android.app.Service)不同。Android Service以Java撰寫。 Native Service Native Service則是實作在Runtime層裡的Server。架構設計上,我們有二個選擇,一個是實作Android Service、再透過JNI與HAL stub溝通;另一個選擇是,跳過Android Service,讓Application(Manager API)直接與Native Service溝通。 未來的Android發展趨勢,應會以第二種做法為主,即Manager API直接與Native Service溝通,以達到更好的效能表現。 延伸閱讀 * 2009.10.14: Android 的 HAL 技術, #2: 採用Service架構方式 * 2009.10.08: Android 的 HAL 技術, #1: 簡介與發展現況...
jollen 發表於 November 28, 2009 9:56 PM
目前為止,我們提了「HAL Stub」的觀念,了解到 stub 是一種代理人的觀念,架構設計上,採取「provide operations」與「callback」機制,而不是採用「module」即 library 的 direct function call 做法。 接著,又提到「採取Service架構的方式」。在講解HAL stub的實作細節前,需要大略了解一下Android Service與HAL stub的關係;因為,架構設計上是「透過Android Service取得HAL stub提供的operations」。 取得HAL stub operations的程式碼實際上是實作在Native Service裡,相關的實作細節留待後續再做說明。 Android Service與HAL stub的關係 應用程式(Application)使用了Manager API,Manager API經由Android Service來到Native Service層,最後Native Service層再引用(invoke)HAL stub。這個過程,總共經過了以下3個介面,如下圖。 1. 這是一個 remote interface,應用程式與Android Service在不同的 process 上執行。 2. 這是...
jollen 發表於 December 1, 2009 10:09 PM
撰寫 HAL stub 除了要具備系統程式(systems software)的觀念外(這是基礎),「思考方式的改變」也是重要的一堂課。 思考方式哪裡不同? 實作 HAL stub 的首要工作是「繼承 struct hw_module_t 抽象型別」。Class(類別)屬於一種抽象型號(ADT)。 首先,引入最重要的標頭檔(header file): #include <hardware/hardware.h> 接著,再定義一個「MODULE ID」。這個 mdoule ID 將會被 HAL 層用來尋找 HAL stub。我們舉最簡單的裝置類型「LED」來做為範例: #define LED_HARDWARE_MODULE_ID "led" 繼承 HAL 的 struct hw_module_t 抽象型別(即 base class 的概念),並取名為 struct led_module_t(即...
jollen 發表於 December 26, 2009 11:36 PM
延續上一則日記的介紹,在完成HAL Stub的實作後,緊接著的工作就是撰寫Native Service。 談了許多「Android Service」以及「HAL Stub」,這裡再補充一點。Android作業系統啟動時,會執行一個process稱為servicemanager。Servicemanager process負責管理、提供並保存「Android Service」。Android Service為Java層,因此接下來會透過JNI來呼叫C/C++層的Native Service。 廣義來說,Native Service也提供Runtime的功能,即Core Library層。Runtime的重要工作之一為「取得HAL Stub所提供的API」,因此這是撰寫完整Native Service的前哨站。 什麼是 Proxy Object? Native Service呼叫HAL的hw_get_module() API取得stub物件,即HAL_MODULE_INFO_SYM。 HAL會去尋找HAL Stub檔案,HAL Stub是以*.so檔的形式存在,並佈署於/system/lib/hw目錄下。HAL會根據module ID以及”ro.product.board”去尋找相對應的*.so檔,以我們的LED範例來說,HAL會回傳回led_module_t結構的物件(an instance of led_module_t class)給Native Service。 我們把HAL回傳給Native Service的資料稱為「Stub Object」或是「Proxy Object」,即先前所提及的「代理人」觀念。Native Service透過代理人與 Linux 驅動程式溝通。這個過程的觀念如圖1所示。 圖1:取得Proxy Object hw_get_module(),這是HAL所提供的API,也是實作HAL...
jollen 發表於 January 2, 2010 11:31 PM
承日記「Android 的 HAL 技術, #6: 小結 HAL stub 實作步驟」與「Android 的 HAL 技術, #7: 取得 Proxy Object」。在了解基本的觀念,以及架構上的設計後,接著就可以開始實作 HAL Stub 了。以下是 LED Stub 的實作範例,將程式碼儲存為 led.c: static struct hw_module_methods_t led_module_methods = { open: led_device_open }; const struct led_module_t HAL_MODULE_INFO_SYM = { common:...
jollen 發表於 January 26, 2010 12:22 AM
從去年就開始構思的「Jollen 的 Android Framework in a Nutshell」演講,終於在上週六正式完成講題規劃了。初版講稿也開始進入檢查階段,第一場演講預估在二月底或三月初舉行,詳細的時間與地點,稍後將發佈於演講活動官網 [Jollen's Android Framework in a Nutshell 演講]。 「In a Nutshell」是本演講的核心理念,也是規劃講稿時所依循的精神;關於堅果殼精神,可參考先前日記 [「Jollen 的 Android Framework in a Nutshell」演講] 的說明。 講題的規劃將以一個實例「揭開」Android 框架的黑盒子、將 Android 結構做展開的動作,並分別介紹每個層面的技術重點;希望藉由這個精心規劃的演講活動,能幫助對 Android 框架與系統底層有興趣的朋友,有效率地掌握技術重點。...
jollen 發表於 February 1, 2010 11:58 PM
Android Framework 技術的重要性日漸提高,研究 Android Framework 架構或是內部結構成為一項重要的工作。明天(2/2)受邀至鴻海土城民生廠進行一場訓練課程,主題是「Android Framework Introduction」;議題雖然是「introduction」,但突然有個想法,希望能做更深入的 introduction。正好近期在整理研究資料,所以把抓出的議題也和大家分享。計畫介紹的技術主題(Features)如下: 1. Android Framework Features SystemServer & ServerThread Main Thread android.app.Activity 與 android.app.Service Android Process 模式 ServiceManager 與 getSystemService API JNI & Native Method Blocking & Long Operations VMThread & Thread Zygote...
jollen 發表於 February 8, 2010 10:55 PM
為了能在「Jollen 的 Android Framework in a Nutshell 演講」上搭配範例做講解,因此「特製」了一個 LedManager 範例;此範例原來是「Android 框架與驅動程式整合: HAL 原理與實作訓練」培訓課程的實作範例,目前計畫以此範例的部份內容做為演講材料。歡迎有意參加 Jollen 的 Android Framework in a Nutshell 演講的朋友,事先下載 Mokoid 程式碼。 Mokoid 提供一個 LedTest 範例程式,同時,LedTest 也是 Mokoid 專案目前所提供的第一個「近乎完整」的範例。請大家參考 apps/LedTest/src/com/mokoid/LedTest/ 裡的程式碼。Mokoid 專案的第二個範例,計畫是「MotorManager」,目前仍處於測試階段,預計在《台北場》演講時釋出。 Mokoid 的目的是提供「教學開發板」一套完整的 architect code 供實驗課程使用,或是搭配正課做原理教學,當然,首要目的是應用在自已的培訓課程上。主要的理念是「去除使用 dirty code...
jollen 發表於 February 9, 2010 3:46 PM
在 [Mokoid] 的 LedTest 範例裡,找到 [AndroidManifest.xml] 檔案。這個檔案為應用程式的「交貨清單」;在開發 LedTest 的過程中,我們加入了一個屬性如下: <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.mokoid.LedTest" android:sharedUserId="android.uid.system"> 原來,ServiceManager 會去檢查應用程式的權限;Android 作業系統會根據 UID 做權限管制,這裡所講的 UID 就是 Linux 系統管理面所討論的 User ID,即使用者 ID。在 [frmeworks/base/cmds/servicemanager/service_manager.c] 裡,找到這段實作: int svc_can_register(unsigned uid, uint16_t *name) { unsigned n; if ((uid == 0)...
jollen 發表於 February 26, 2010 10:12 PM
Context.getSystemService() 是一個很重要的 API,也是「Android 應用程式控制硬體」的起點。在一個開發項目中,如何擴展 getSystemService() 的實作成為一個重要的課題。 幾天前與客戶進行技術討論時,適巧討論到這個議題,因此在這裡做一個簡單的紀錄與大家分享。應用程式要存取手機上的 Sensor 裝置時,須取得 SensorManager 物件,程式寫法如下: public class mokoidSensor extends Activity { /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); SensorManager sensor = (SensorManager)getSystemService(SENSOR_SERVICE); sensor.getSensors();...
jollen 發表於 March 2, 2010 10:45 PM
經由 [Mokoid] 範例,我們可以學習到擴充(Extent)Android 框架的做法。搭配 Product Tree 的方式,我們將 LedManager 與 LedService 二個類別編譯成獨立的 jar 檔(mokoid.jar),mokoid.jar 會被 Android build system 自動佈署到 system.img 裡(system/framework/mokoid.jar)。 因為 mokoid.jar 裡的類別沒有做 preload,並不是「preload class」,所以需要額外的系統設定,才能讓 Android 作業系統找到 LedManager 與 LedService 二個類別。在 Mokoid 範例中,找到一個名為 com.mokoid.server.xml 的設定檔,內容如下: <?xml version="1.0" encoding="utf-8"?> <permissions> <library...
jollen 發表於 March 17, 2010 10:52 PM
近期進行有關 MokoidBoard 的平臺開發,MokoidBoard 的目的是打造一個「Android 框架與底層」專用的學習平臺,主板的部份是基於 Samsung S3C6410 處理器。目前除了計畫以 S3C6410 打造手機方案外,還有一個一直很想實現的理念:教育訓練方面,提供品質良好、架構完善的範例程式碼。一些 dirty code 對於初步學習,並了解硬體是很有幫助的;但入了門,總是要持續進步、精益求精,研讀架構完善的高品質程式碼,就是煅煉火候的好方法。 目前在 MokoidBoard 上提供的 LedTest 範例,是透過 ServiceManager、LedService 以及 HAL Stub 等觀念所設計的「LED 控制程式」。如圖,LedTest 執行時,會出現一個巨大按鈕,按了後,便會將開發板上的第一個 LED 燈點亮。 範例程式碼並不難讀,比較難懂的是 Android 框架與 HAL 架構的觀念,還有一些設計原理。這些觀念,在上週的 Android Framework in a Nutshell 演講做了一個整體性的介紹。 在開發階段,「如何測試 HAL...
jollen 發表於 April 5, 2010 3:14 PM
Android 作業系統開機時,會經由 init.rc 來啟動許多外部程式,其中有一個最重要 process 稱為 Zygote。Zygote 是 Android 的 monitor process,它主要負責二項工作: 1. 啟動 system server 2. 執行 Android 應用程式 「System Server」是由 Zygote 所建立的另外一個 process,建立 system server 的方式是使用典型的 Linux system call - fork()。當 Zygote 成功建立 system server 後,便進入 socket listening...
jollen 發表於 April 24, 2010 9:57 PM
今天在上海進行「Android Framework & HAL 軟硬整合」培訓課程,課程中提到 init.rc 的用途,因此在此做一個紀錄。init.rc 是 Android 作業系統的 initial script,在開機時由 init 讀取並執行 init.rc 裡的命令。Android 的 init.rc 使用的的語法稱為 Android init language,有別於傳統 Embedded Linux 採用 shell script 的方式。 在 init.rc 裡找到類似以下的命令片斷: on boot setprop ro.FOREGROUND_APP_ADJ 0 setprop ro.VISIBLE_APP_ADJ 1 setprop...
jollen 發表於 May 11, 2010 12:24 PM
MokoidBoard 是基於 DMA-6410L (S3C6410) 的一款開發板,目前使用在仕橙3G教室的大部份訓練課程裡,目前已經將 Android 2.1 (Eclair) 移植至 MokoidBoard 上。開發板使用者或是課程學員,同樣請使用 [Mokoid] product tree 即可編譯。 升級 Android 2.1 步驟如下 以下步驟提供給 MokoidBoard 使用者參考。依此步驟即可將您的 MokoidBoard 升級 Android 2.1。 圖一:Android 2.1 圖二:Home Screen 1. 準備 Android 1.6 原始碼 請備妥 MokoidBoard CD,將 Android 1.6...
jollen 發表於 May 21, 2010 6:19 PM
上一則日記提到 Android property 的設定。在 Android 作業系統裡,取得 property 是很重要的工作。不管是 Android 框架層(使用 Java 語言),或是 Native 層(使用 C/C++ 語言),都可以看到讀取 property 的程式碼。 以下是一段簡單的範例程式,用以說明如何用 C 來讀取 Android 系統的 property: /* * Copyright (C) 2010 The Mokoid Open Source Project * * Licensed under the Apache...
jollen 發表於 June 30, 2010 11:46 PM
最近有關 Android 的大新聞,大概就是 Froyo 的發佈消息了。有在關心 Android 部落格的朋友應該都已經都看到這則消息了,Android 2.2(Froyo)的程式碼已經正式發佈,除了釋出大家最關心的 Dalvik JIT Compiler 外,也加入了 V8 Javascript Engine。又有工作要做囉。 小弟也順勢發佈一張即將推出的一款 Android 樣機照片,目前這款樣機已進入試產階段,不過,這是一個解決方案平臺,並不是正式發行的終端產品。 未來,使用這個平臺,將可以達到一些快速開發的需求。在這款平臺上,也會進行一些 Enhanced API 的開發,以協助廠商開發自有特色的應用軟體。目前正在持續進行產品的規劃,以及後續的開發準備工作。希望能加速技術面的發展,未來才能繼續和大家分享最新進展。...
jollen 發表於 July 28, 2010 2:20 PM
Android 開機流程,是一個很值得詳細討論的主題;近期,也正在進行相關的技術工作,因此簡單整理一些相關資料,和大家分享。了解「整體開機流程」,是最重要的第一門課。我們將開機劃分為三大階段: 1. OS-Level,由 Bootloader 載入 Linux kernel 後,開始進行 kernel 本身的初始化,並載入 built-in 的驅動程式。Kernel 完成開機後,載入 init process,切換至 user-space 後,結束 kernel 的循序過程(sequence),進入排程模式(process scheduling)。 2. Android-Level,由 init process 開始,讀取 init.rc 並啟動重要的外部程式,例如:servicemanager、Zygote 以及 SystemServer。 3. Zygote-Mode,Zygote 啟動完 SystemServer 後,進入 Zygote Mode,在 Socket 等候命令。隨後,使用者將看到一個桌面環境(Home Screen)。桌面環境由一個名為...
jollen 發表於 July 29, 2010 9:12 PM
針對「開機過程」的評估,可以採取個別擊破的方式;針對三個不同的開機階段,分別進行開機過程的評估。評估開機過程的典型做法,當然是測量「開機時間」。 確認訴求 費勁進行開機時間的評估,最首要的目的當然是「快速開機」,想辦法讓開機速度加快。策略上,因為手機是一種重視使用者經驗的產品,所以「儘早顯示桌面環境」就是一個好想法。採用「一大堆」非同步的做法,可以達到很不錯的效果。簡單來說,儘速顯示桌面環境的目的,就是造成開機很快的「假象」。 因此,快速開機在智慧型手機產品端,也可以歸類到 User Experience 主題。 確認方向 OS-Level 的部份,包含 Linux kernel 本身的開機時間測量,在此先行略過。針對 Android-Level 的開機時間測量,可以採用廣受歡迎的工具 [Bootchart] 來製作;對使用者來說,進入 Zygote Mode 時,已經是處於桌面環境下了,因此理論上也能先略過這個階段。 關鍵部位 (Critical Parts) 圖一:由 Android-Level 切入、尋找議題 如圖一。綜合上述,對 Android-Level 的開機過程進行評估,就是我們的首部曲,也是第一個研究方向。傳統的評估方式,是測量其開機時間;接下來,將會以知名的 Bootchart 來進行這項工作。...
jollen 發表於 August 2, 2010 1:25 PM
執行 Android 2.1 的智能手機「長江二號」開機囉。目前使用起來還算順暢,雖然 Engineering Build 的開機時間有點長,不過能看到 Linux 小企鵝,是一件興奮的事情。 長江二號(CJ-2)是使用 Rockchip RK2808 的 Android GSM 智能手機,目前正在測試中的「長江三號」是令人更興奮的版本。長江二號的團隊(Zinn.Mobi)正在很努力地催生三號中,希望 3G 版本也能儘快與大家見面。...
jollen 發表於 August 3, 2010 11:15 AM
前一則日記提到的 Bootchart 是典型的開機量測工具,主要能進行開機過程以及開機時間的量測。由於 Bootchart 的原理是取代 init process 或是內建在 init process 裡,所以只能取得 initial script 的開機過程報告。不過,這已經很有幫助了。 關於 Android Bootchart 以下是一份使用 Bootchart 所製作的 Android 開機流程圖。過去有一些以 C 重寫 Bootchart 的專案,而 Android 也有一份 C re-implementation,放置於 [system/core/init/bootchart.c]。由此可知,Android init 已經內建一份 C re-implement 的 Bootchart。 圖一:使用 Bootchart 製作的...
jollen 發表於 August 10, 2010 11:55 PM
Nexus One 雖然在日前停止網路銷售,不過,根據幾天前在的 Android Developer Blog 上的一則新聞來看,Nexus One 榮獲「Android Developer Phone」頭銜。也就是,雖然 Nexus One 下架了,但改以 ADP3(Android Developer Phone 3)的名稱對開發者進行銷售。第一代 Android Developer Phone 就是由 T-Mobile G1(aka HTC Dream)換名而來,並且做了解鎖動作;Android Developer Phone 2(aka G2 or HTC Magic)於去年 11 月推出,同樣也是 Unlocked Phone。ADP3 則是將 Nexus One...
jollen 發表於 September 13, 2010 12:32 AM
Android Telephony 以及 RIL 是一個重要的議題,內容主要在談論 Android 的電話系統框架,以及 RIL (Radio Interface Layer) 的實作。由於 Android 提供的 RIL 幾乎沒有實作 Modem 端的功能,也缺乏像是 Data Multiplexer 的實作,因此,研究 Telephony 以及實作 RIL 成為了 Android 手機開發的關鍵技術。 在經過一段相當長時間的規劃與調整後,終於在日前成功開設「Android Telephony & RIL: 通訊系統架構與實作」課程,本程也在9月12日順利結訓。這是截至目前為止,在參與過的課程規劃案中,技術複雜度較高的題目。 課程內容除了採集過去開發 Android 手機的經驗外,也將 Telephony & RIL 做了很完整的研究,目標是以深入淺出方式,介紹這個有意思的主題。希望這門課程,能協助學員開發 Android...
jollen 發表於 September 18, 2010 11:49 PM
深圳特產再一樁,道地的 Android 平板電腦。外觀不錯,使用起來還算及格。這款 Android Pad 的使用手感仍不及 iPad,但是從 Android 的技術角度來看這個板子,還是很有趣的。這是在深圳出現的 Android 平板電腦,左邊是真正的 iPad,右邊則是 Android 平板電腦的包裝。 包裝盒已經說明這款產品的身世了,這是「Android 平板電腦」,外觀有點像 iPad,事實上根本是一模一樣的。 Android 平板電腦比 iPad 更小巧,經過一天的隨身使用,發現其實攜帶性很不錯,放在背包裡頗為方便,而且重量較輕。最重要的面板與觸控面板部份,不需要再多說了,明眼人一看就知道囉。iPad 深邃鳥黑的顯示屏,帶來的是最佳的視覺表現,這不是 Android Pad 這個有點白汒汒的白內障顯示屏可以抗衡的。 正版 iPad 的 LED 背光顯示可以說是它最不可或缺的特色。9.7 吋的 LED 背光 IPS 顯示屏,支援超廣視角,以及 multi-touch,讓 iPad 的視覺與操作達到很棒的同步。iPad 讓大腦、視覺與手指操作達到一種匪夷所思的同步,Android 平板大概還要花很長一段時間,才能達到這個境界。...
jollen 發表於 November 25, 2010 8:41 PM
近期為客戶進行 Android Camera 的顧問服務,主要的任務是改善 Android 在拍照方面的效能,撰寫了一些相當基本的觀念介紹,在此與大家分享。Android 的 Camera 系統大概念上可分成三大區塊: 1. android.hardware.Camera 2. Camera Service 3. Camera HAL + videodev 其中最核心的 Camera Service 預設是實作在 SystemServer 裡。控制 Camera 硬體的 HAL 部份,目前大多採用 Linux 的 videodev 介面來擷取視訊。以下簡介 Android Camera 的三大功能區塊。 1. android.hardware.Camera 屬於 Java...
jollen 發表於 December 8, 2010 6:31 PM
Android 2.3 這次終於如傳聞中的日期釋出了,許多重要的新特色也出現在這個重要的版本裡了。官方網站上有完整的 [Android 2.3 Platform Highlights],網路新聞也有不少的介紹;在這裡簡單聊一下一些看法。 Android 2.3 已經來到 API Level 9,有許多有趣的更新,像是加入了 VoIP、NFC 與 Download Manager,還有強化了遊戲開發的功能。多媒體框架部份也有重要的更新。新的 Multimedia Framework 已經可以完全取代 OpenCore。新產品開發上,已經能去除 OpenCore 並使用 Android 2.3 的 VP8/WebM 新技術,理論上,多媒體的效能以及應用將有大幅度的進展。 在遊戲開發部份,因為有不少的 native code 開發需求,這次 Android 2.3 也加入了 android.app.NativeActivity 幫助遊戲開發者撰寫 native code,例如:存取 OpenSL...
jollen 發表於 January 3, 2011 4:45 PM
近期在進行 Android 2.3 的新框架程式碼研究,Android 2.3 在 Platform (Framework) 部份包含了許多重大的更新,其中一個部份就是 SensorService 改寫成 Native Service 形式。在 Android 2.2 以前的框架,SensorService 包含在 SystemServer 裡,實務上,可能也會對 SensorService 做小幅度改寫,以增進效能,或是將 SensorService 獨立成為一個 process。 在 Android 2.3 裡的 SystemServer 已經找不到 SensorService 了,這個重要的 Android Service 被改寫成 Native Service。「如何將 Android Service...
jollen 發表於 January 4, 2011 10:34 AM
Android 2.3 框架源碼釋出後,開始有必要對 Dalvik VM 做深入的研究。建議可以由 Dalvik VM 與 Java VM 的差異起步。Dalvik VM 與 Java VM 雖然字面上都是「Java 虛擬機」,但內部設計並不完全相同,存在一些差異。最中最重要的差異,就是 Dalvik VM 加入了 Zygote 的設計。 在過去許多的演講場合,不斷提到 Zygote 的觀念,在 [Jollen 的 Android 觀念解析, #1: Zygote Mode] 日記裡也曾簡要提及。Zygote 負責幾項重要的工作: 1. Listening Socket (Forking child...
jollen 發表於 January 10, 2011 3:20 PM
設計音樂撥放器應用程式時,如何正確地進行「Play Music」的動作?在按下 Button 後立即進行音樂撥放,是可行 (work) 的做法,但卻不建議這樣設計。在類似 onButtonPressed() 的 event callback 裡直接撥音樂會有「UI 成本」產生,意思是可能對 UI 反應造成不利影響。 設計一個簡單的 Music Player 界面如下: 圖一:Music Player 以 Android SDK 2.3 為例,我們可使用 android.view.View.OnClickListener 以及 android.media.MediaPlayer 設計出「不建議」的音樂撥放器。 圖二:Bad Design: Music Player v1 以下以 pseudo code 呈現圖二的實作: public class...
jollen 發表於 January 11, 2011 7:05 PM
根據先前所討論過的觀念,我們把 "play" music 的功能設計在 secondary thread 裡。Android SDK 使用 java.lang.Thread 來建立 thread,使用 secondary thread 來產生 MediaPlayer 的 instance,並撥放音樂。Music Player v2 設計圖如下: 圖一:Music Player v2 設計 針對 Music Player 個案,因為 MediaPlayer.create() 是以同步 (Synchronous) 方式準備 MediaPlayer,所以有出現 ANR 的機會。在早期 (2008 年) 的 MediaPlayer...
jollen 發表於 February 21, 2011 9:15 PM
一年多前,「Android 的 HAL 技術」系列日記闡釋了 Android HAL 的觀念與基本設計方法;在小弟的「Android HAL & Framework: 軟硬整合實作訓練 」訓練規劃中,也對 Android Service 與 HAL 做了完整的介紹。 現在,再度回到 Android HAL 的主題;主要是 Android 2.3 在部份硬體單元(Component)做了一些架構調整。隨著 AOSP 程式碼的大幅進步,硬體廠需要加強對 Android HAL 的技術掌握度,這是十萬火急的工作了。因為,硬體廠唯有具備發展高品質軟硬整合程式碼的能力,才能在 Android 產品開發工作上具備競爭力。 「Native 化」 過去在「Android 的 HAL 技術, #3: 小探Android Service與Native...
jollen 發表於 May 1, 2011 10:36 PM
這是 Android 官方「Dev Guide」裡提到的重要級觀念,但經常被忽略,因此在這裡做個簡單的說明。 許多 Android 應用程式經常發生「undefined」與「unexpected」的錯誤,很多錯誤的起因都是違反了這個觀念。在 Android Dev Guide 裡提到,每一個 Android process 都有一個「UI thread」負責處理 UI 事件,為了避免 ANR,應用程式開發者應該建立 Java thread 來執行像是 long operation 等的工作,由應用程式自行產生的 thread,稱為「worker thread」。Worker thread 有時也稱為 secondary thread 或 child thread。但問題發生了,一些應用程式在 woker thread 裡操作 Android UI toolkit。 所謂的...
jollen 發表於 May 29, 2011 11:56 PM
在 Dev Guide 裡還有另外一個重要的觀念:避免產生不必要的物件。這個觀念真的很重要,如果要讓程式的效能更好,不斷在 Main Thread 裡產生物件是 bad idea。原因是 Garbage Collection。 Android 的 Dalvik 虛擬機在初始化時,會建立 Main Thread。Main Thread 負責眾多任務,其中之一是 Garbage Collection,也就是負責做資源回收,把用不到的物件回收再利用。如果我們不斷在 Main Thread 裡產生物件,Main Thread 很可能忙著幫我們收拾垃圾,當 Main Thread 花費太多心思幫我們撿垃圾,處理其它工作的效率就會變差,例如:UI 事件處理。 所以,這告訴我們一個重要的觀念:「不要產生不必要的物件」,難怪 Dev Guide 在講「Designing for Performance」時,把這個觀念放在首位。有些 Class 在設計時,提供了多種 instantiate(實例化)方法,以 android.os.Message...
jollen 發表於 July 11, 2011 6:42 PM
上週五受台北科技大學資工系的邀請,發表了一個小時的演講,講題是「淺談 GNU/Linux 與 Android/Linux 的差異」,如同題目所要表達的,「Android+Linux」並不是「GNU+Linux」。傳統的 Embedded Linux 系統是基於 GNU/Linux 開發,因此在這次的演講裡,也做了一個「Embedded Linux 不等於 Android+Linux」的結論。 這個題目相當有趣,因為涉及非技術面的議題。在真槍實彈開發 Android 產品前,認識我們使用的 Android/Linux 系統是很重要的前置作業。這次的講題涉及層面較廣,細節也很多,小弟特別從二個層面切入:技術面談 Android/Linux Toolchain、非技術面談 FLOSS 授權。 Android 的商業模式需要 Permissive License 在 FLOSS 授權方面,並不是「不同授權的 FLOSS 軟體」都能「任意合併使用」,在了解各授權的特性與「合併使用」議題前,有必要先了解現有授權的類型。現今較廣為使用的 FLOSS(Free and Libre Open Source Software)授權有:GPLv2、GPLv3、LGPL 系列、Apache 2.0、BSD 系列、MIT...
jollen 發表於 October 21, 2011 12:30 PM
經過漫長的等待,AOSP (Android Open Source Project) 終於回來了。這次 kernel.org 被駭事件,導致 AOSP 伺服器中斷服務近三個月,Google 終於帶來好消息。 正好 Android 4.0 (Ice Cream Sandwich) 產品發佈。根據 Google 官方說明,Ice Cream Sandwich 的源碼將在三星 Android 4.0 手機 (Nexus Prime) 上市後公開。由於社群不斷在郵件列表裡發問,這次 Google 官方為大家釋疑,讓社群開發者總算放下一塊大石;Android 4.0 確定會發佈到 AOSP,時間大約在 11 月底前。正確時間還是要看 Nexus Prime 的出貨時間而定。 AOSP...
jollen 發表於 November 11, 2011 4:11 PM
關於Java virtual machine的Thread object model,理論上的做法是「一個Thread object連繫(Binding)到一個native thread」。從multi-core的角度來看,這是一個很理想的做法,實務上是否有採用這種Thread object model的Java virtual machine呢?答案是,有的;這取決於virtual machine與作業系統的設計。 JDK6搭配Ubuntu 8.04的環境,以及Android 2.3搭配MagicLego的kernel來看,都是上述的thread model。當然,這裡只是以我自已目前使用中的開發環境當例子,不僅只於這二個環境。 為什麼一個Thread object連繫一個Native thread是比較好的做法,適合應用在multi-core的場合,這涉及到多核心的kernel scheduling技術,在後續的文章裡再做討論。基本上,只要您的系統是屬於上述的Thread object model,未來都能提供一個良好的多核心軟體開發環境。 應用程式到框架,框架透過JNI來到C/C++底層,Thread object與Native thread是一對一關係時,作業系統再將指定的Native thread指派到另外一個處理器,接下來就可以得到這樣的效果:Thread object被指派到另外一個處理器了。這就是為什麼應用程式的設計,以及底層的軟體系統,決定了系統是否能實現「多核心運算」的原因。...
jollen 發表於 December 5, 2011 4:18 PM
Google 將 Android 4.0 釋出後,製造了一波移植運動。Linaor 或是 xda-developer 上,都已經發佈 Ice Cream Sandwich 的移植成果。一些大家手邊常見的開發板,像是 PandaBoard 等,也都能運行最新的 Android 4.0 系統了。 在 Android 4.0 AOSP 上線後,手邊也開始了一個移植專案;經過一個多禮拜的努力,就在大有斬獲時,開發板就被 Porting 到壞掉了。不過,Ice Cream Sandwich 移植是一個令人熱血沸驣的工作,怎麼能這樣就休息呢。於是把在上課使用的 devkit8000 開發板拿出來「試試看」,這是我手邊現有的唯一開發板。 雖然 devkit8000 的硬體配置不算頂級(Cortex A8 600MHz 處理器、256M 記憶體),但因為 Linaro 發佈的 Release 11.11...
jollen 發表於 December 23, 2011 3:44 PM
2011歲末時刻,要好好為自已上一堂「Lessons Learned」課程。 今年度有幾個 Android 專案,特別令人印象深刻,其中一個是有關於 Android 瀏覽器與 webkit 的計畫。因為開發專案的需要,修改了 Android 瀏覽器 (Browser) 的程式碼,也對 Webkit 做了些研究,沒想到這整個過程,倒是有點出乎我的意料之外;原本以為這是一個簡單,且能輕易結案的計畫,沒想到踩到 AOSP 的地雷。在這個瀏覽器開發專案接近尾聲時,在這裡分享一點甘苦談。 Google 採用 Webkit 做為 Android 內建瀏覽器的 HTML 引擎,Webkit 是相當知名的 HTML 引擎,由 Apple 公司做了早期的開發,現在則是成為了一個開源計畫,由社群開發者,以及部份公司,共同貢獻程式碼。 這個開發專案需要基於現有的 Android 2.2/2.3 瀏覽器,加入一些功能,並能整合伺服器端的服務,其中一個功能,需要使用到瀏覽器的 Copy/Selection 功能。就如同大家所知道的,Android 2.2 的 WebView 並沒有...
jollen 發表於 January 19, 2012 8:33 PM
文/Jollen Chen(原文刊載於 CTimes零組件雜誌2012年2月號) HTML5標準將開始大舉進入行動裝置市場,這是今年的手機技術重頭戲。撰寫手機App現在有二種選擇了。第一種做法是典型的做法,也就是Native App的開發方式,採用Java或C程式語言撰寫App,在編譯後安裝至手機運行。這種做法的主要缺點是,不跨平臺,也就是,針對Android手機、iPhone機等,都必須各自發展一份程式碼。 第二種做法就是HTML5的做法,採用HTML5標準開發App,有點像是在設計網頁,或是撰寫Web應用程式。可以想像,以後只要把網頁或Web應用程式封裝成App後,就能直接安裝至手機運行。這種做法解決了Native App不能跨平臺的缺點。 我們可以這樣解釋,不管使用什麼作業系統或瀏覽器,都可以瀏覽網頁,所以網頁與Web應用程式本身,都是跨平臺的。同樣地,不管你是使用什麼手機,也不管手機使用的是什麼作業系統,都可以運行同一份HTML5的手機App。 HTML5將要在手持裝置域,呈現大爆發式的成長;因此,有三項關鍵技術,不可不知。 第一、使用HTML5+CSS+JavaScript撰寫Web應用。HTML5是網頁標籤語言的標準,當然,單單使用HTML5並不能開發應用程式,必須搭配CSS與JavaScript來使用。因此,HTML5+CSS+JavaScript就是「HTML5 App」的基礎建設。有些網頁上面有很棒的特效,例如:轉場效果,這些都可以透過JavaScript來完成。 另外,jQuery也是不可或缺的技術。jQuery已經相當的有名,就不必再多說了。直接撰寫JavaScript可能有時很麻煩,這時可以使用jQuery以及眾多的jQuery plugins來完成。 第二、JavaScript引擎的成熟度是關鍵。要在手機上運行HTML5的App,因為將會使用到許多JavaScript程式碼,所以JavaScript的引擎成熟度,以及它的效能是主要關鍵。安裝在手持裝置上的JavaScript 引擎,將成為手持裝置的重要技術。 Android系統早期使用的 JavaScript 引擎稱為 JavaScriptCore (JSC),JSC 包含在 webkit 中。因為一些原因,Google 也決定開發自已的 JavaScript 引擎,稱之為 V8。技術上,新一代的 V8 引擎效能比 JSC 引擎更好。最新的 Ice Cream Sandwich 已經全面採用 V8 引擎了。V8 引擎的編譯基礎技術稱為 Crankshaft,這項技術可以很有效地改善JavaScript應用程式的效能。 第三、PhoneGap潛力驚人。目前,已經有非常多的App開發者,使用知名的開放源碼專案...
jollen 發表於 March 17, 2012 12:36 AM
就用 Jollen 的 AFC 當做 Android 研究工作的段落吧。在 2007 年底接觸 Android 時,還沒有很用心去投入研究工作,記得當時還在 Openmoko 公司,負責教育市場的推展。到了 2008 年底,Openmoko 社群將 Android 移植到 Neo FreeRunner 後,便開始對 Android 的框架研究產生了興趣。當時,花費比較多時間其實還是在移植(Porting)的層面,除了改改一些小東西,寫點移植手冊外(為了學校推廣、後來沒有發表),還是很零星地在 Android Framework 研究工作上。 離開 Openmoko 公司後,便創辦 Moko365 公司,給新公司的定位是 Research Company。當時心想,台灣未來勢必走向軟體開發之路。了解軟體的人,一定知道技術研究工作的重要性。畢竟,技術研究工作,是技術開發之母。再加上 Android 龐大又複雜的架構,如果可以有一家公司,專職做「技術研究」,為產業提供研究成果,勢必能對產業有所貢獻。就是這個想法,所以自已做下去了。 術業有專攻。我來做研究與發展(Research and Development),硬體公司做工程(Engineering),大家分工把最後的工作,也就是「產品」做好。 在成立 Moko365...
jollen 發表於 April 3, 2012 12:47 PM
自從完成「Jollen 的 Android Framework Complete (框架大全) 課程」後,對於軟體設計領域有了更深一層的認識,並且發現許多軟體設計的美麗之處。接下來的工作,除了過去近十年的系統程式領域,也打算在軟體設計領域繼續提升。系統程式(systems software)的技術工作,除了需要大量的經驗累積外,還需要「手感」;這點相信有經驗的系統程式高手,都有同感,所以必須保持不斷的接觸程式碼。系統程式領域廣大,包含:kernel、device drvier等,這些都是筆者過去相當有興趣的主題;所謂的「手感」就像是寫文章,需要偶而一點靈感才行。 系統程式領域,主題與範圍一般都較為明確,例如:kernel。軟體設計領域,範圍更大,所涉及的知識也更多,例如:網路、使用者。無論是系統程式,或是軟體設計,都會有共同的背景知識,例如:物件導向(Object-oriented, OO)。 初學 kernel 或 device driver 的開發者,或許不會知道 kernel 本身就是物件導向的設計;實務上,如果專注在工程面(Engineering),其實也不太需要深入了解 kernel 與物件導向的關係。所以在 kernel 與 device driver 領域,物件導向是 implicit,隱性的。 在軟體設計方面,例如:Android framework,如果不了解 subsystem 的物件導向設計,以及設計模式(Design pattern),並不太容易看懂其程式碼(Source code),並且幾乎影響了後續工程工作的進行。所以在 Android framework 領域,物件導向是 explicit,顯性的。 這就是過去幾年為企業進行相關教育訓練時,有些主題我會特別強調 Object-oriented 與...
jollen 發表於 April 3, 2012 1:23 PM
將View與Control切割是軟體設計的根本。這個觀念非常的好懂,也是學習軟體設計的基本功。View被解釋成UI等可見物,Control則是控制功能,例如:關機。一般來說,控制功能由控制者提供,所以經常被稱為View/Controller模式。 這個觀念真的簡單不過,把畫面與控制功能分開。這個觀念的發展始於 1980 年代,當時為了開發圖形介面的電腦,電腦科學家於是想到「 Separated Presentation」,也就是從事視覺(Presenetation)的程式碼就只做視覺(例如:Drawing),把其餘的切割(separated)出來。後來形成今天家喻戶曉的軟體設計模式 - MVC(Model-View-Controller)。 把View與Controller切割的觀念被一直沿用到今天,所以先想清楚View/Controller為什麼切割,原因何在?才是重點。「Model」是擴充出來的觀念(Concept extending),所以,可以先將「Model」是什麼放著不談。 將View與Controller切割是為了不讓控制的動作影嚮到畫面(View),根本原因是希望有更好的使用者體驗。做法很簡單,從現今的分時多工作業系統(Time-sharing & multi-task operating system)角度來看,只要切割成獨立的process即可。如圖1.1。 二個process就使用訊息(message)傳遞的方式溝通,也就是我們所熟悉的IPC(Inter-process communication)。 切割 View & Control Android 系統將 View & Control 切割,因為這樣可以設計出 UI 使用性更好的軟體。同時還有二個好處。第一、讓程式碼更容易維護,第二、軟體架構更清楚。為什麼將 View 與 Control 切割成獨立的 process,可以讓 Android 系統有更好的 UI 使用性呢?...
jollen 發表於 April 8, 2012 12:11 PM
Linux 核心是 implicit of object-oriented 的典型實例。例如,在開發驅動程式的過程中,雖然不需要特別了解驅動程式的物件導向架構,但其架構則是依循嚴謹的物件導向觀念。Linux 核心與驅動程式,都是以 C 語言實作。 另外一個例子,就是筆者在 Android Framework & HAL 課程中所提到的 HAL Stub 觀念。HAL Stub 可採用 C 語言實作,編譯後以 *.so 形式佈署,但它不是程式庫(Library),而是一個物件(Object)。 圖1.2 HAL Stub 架構 HAL 的模組稱為 Stub,Stub 是一種物件。Stub 在軟體工程領域代表「樁」的角色,也就是整體架構中的一小段基礎程式碼,這段程式碼有著以下二個特色: 1. 符合架構的程式碼(打地基) 2. 一段程式碼範本,最終的實作 (final implementation) 是代理人...
jollen 發表於 April 15, 2012 1:18 PM
最經常使用的物件導向觀念就是繼承(Inherit),使用C語言如何實作繼承?最實用的例子就是 Android HAL。以下圖為例,這是一個標準的 HAL Stub 設計。這個例子試圖在原有的 Android 作業系統裡加入一個「LED Stub」,透過 LED Stub 來控制底層的 LED 硬體。 圖1.3是一個標準的繼承設計,也就是說,在設計 HAL Stub 時,需要重用 hw_module_t 設計。從架構設計的角度來看,我們進行設計重用的工作,以擴充出 LED Stub;錯誤做法是,直接修改原有的 hw_module_t 設計,以達到原本的要求。上述觀念,就為設計重用(Design reuse),這是軟體工程領域相當重要的知識。  圖1.3 HAL Stub設計重用 在開發 Android 系統時,會不斷地 reuse 原有的設計,以擴充出想要的功能。 以標準 C 語言實作圖1.3的方式如下: 1. 以資料結構(Data structure)來描述類別(Class)...
jollen 發表於 July 12, 2012 1:33 AM
CPU Ondemand 並非萬能。最重要的例子就是 Android 4.1 的 CPU input boost (Touch Event),在接收 Touch Event 時,提高 CPU 的運算效能。 延伸 Android 4.1 的 CPU input boost。我們也可以讓應用程式享用 CPU Boost 功能。根據使用者目前的操作,將 CPU Boost,讓使用中的應用程式,衝到最高的效能。Boost 有點像是「猛衝」的感覺,可以在這個時刻讓使用者享受高效能的應用程式。 筆者目前參與開發中的 Phonesmpd 軟體,符合了這樣的設計想法。 CPU On-Demand 到處都適用嗎? 由於 Android Process Model 與典型的...
jollen 發表於 August 4, 2012 3:09 PM
[Phonesmpd] 目前正和 Jelly Bean 整合當中,並且也開始加入 Linux 3.2 的一些特性。Jelly Bean 新增許多與多核心有關的特色,Phonesmpd 考慮了其中幾個新特色: 1. 整合 Jelly Bean 新的 Thread Group 功能 2. Jelly Bean 修改了 Cgroup 的設定,除了 fg_boost 外,還有一個 app group 3. 針對 Vsync 整合一些多核心功能,目前測試結果顯示能提昇 UI 的使用效能 4. 整合 Cpuset ,並支援 Linux...
jollen 發表於 October 19, 2012 11:48 AM
Android 內建瀏覽器不支援 WebSocket Client 端,導致使用 HTML5 開發的 Apps 無法使用 WebSocket 與 Server 建立連線。主要的問題在於 WebView 元件沒有實作 WebSocket 協定。Android SDK + PhoneGap 所製作 HTML5 Apps 是將 WebView 封裝至 APK 裡,所以 WebSocket 無法正常工作是正常的。 不過這個問題也沒有那麼難解決,在等待 WebView 加入 WebSocket 以及更多 HTML5 功能前,我們只能暫時自行實作。還好,現在有很多 Open source 的...