2009年8月7日 星期五

Browser download function in Android


最近在開發有關於檔案傳輸的Android程式,突然心血來潮去看Android Framework內建的瀏覽器下載功能是如何進行設計的,看過原始碼才知道,其完全遵守MVC原則,縱使只是一個單純的下載工具。

右邊的圖顯示了概略的關係,並沒有使用正規UML,請多多包涵。

現在就從DownloadService開始吧


一 - 下載工作執行 (Control)

classes:
com.android.providers.downloads.DownloadReceiver
com.android.providers.downloads.DownloadService
com.android.providers.downloads.DownloadService.UpdateThread
com.android.providers.downloads.DownloadThread

實際上執行檔案下載的邏輯,其並無包含scheduling,任何task進來都是立即開始。

瀏覽器藉由新增DB record來觸發下載工作,DownloadService使用UpdateThread去monitor DB,若發現DB有需要處理的download工作,就會立刻new 出新的DownloadThread去handle實際的下載工作,並存有一份ArrayList (mDownloads)作為local memory cache

---------------------infinite for loop--------------------

1. 比對mDownloads與DB中的record
1-1. 若DB的record比mDownloads還多,則代表有新的工作,立刻開始新的下載
1-2. 若DB的record比mDownloads還少,則代表有工作已經被使用者從UI刪除,立刻停止並刪除該下載
2. 通知Notification bar目前的狀態 (請參照四 - UI - 顯示狀態於Notification bar (View))

------------------------------------------------------------

DownloadThread並會把下載狀態透過ContentResolver/ContentProvider介面隨時 persistent至 SQLite DB (DownloadProvider) 裡


二 - 下載資訊persistence (Model, 橘色部分)

classes:
com.android.providers.downloads.DownloadProvider
(implements ContentProvider with SQLite DB)

儲存所有下載即時/歷史資訊的DB,其透過實作ContentProvider,可提供所有ap進行查詢

使用URI為 content://downloads/download
(android.provider.Downloads.CONTENT_URI)


三 - UI - 下載歷史資訊列表 (View)

classes:
com.android.browser.BrowserDownloadPage
com.android.browser.BrowserDownloadAdapter

當user點選menu中的下載歷史紀錄時,會顯示此Activity,其使用ListView + BrowserDownloadAdapter (繼承ResourceCursorAdapter,可方便透過Cursor介面撈DB中的資料並顯示於ListActivity中)

四 - UI - 顯示狀態於Notification bar (View)

classes:
com.android.providers.downloads.DownloadNotification

DownloadService內部有UpdateThread,其會定時更新Notification bar中的狀態 (ProgressBar, 下載百分比)


筆者之前寫過J2SE, J2ME BD-J等AP,在軟體架構上相較於Android可以發現,Android很重視 data persistence (Preferences, ContentProvider....etc)與XML modeling (UI, Animation, style....etc),這讓AP開發者可以花更多的時間在需要的事情上,而不用擔心資料儲存的複雜狀態與程序,以及UI或Animaiton等畫面細節的調整


2009年6月11日 星期四

讀後感: Android Dalvik VM vs. Java VM

在拜讀jserv大的此文章 Android Dalvik VM vs. Java VM 後,有一些感想

其實此專案點出一個重點,就是DalvikVM 的bytecode execution效能普遍沒有現有的CDC/CLDC VM來的好,
一方面是DalvikVM沒有JIT,一方面是發展的時間不夠久。

當初DalvikVM不做JIT的原因是手持式裝置記憶體過小,太多的native code反而會造成記憶體管理上的負荷。
但是他們也認知到未來若Android porting至小筆電,JIT的需求會越來越明顯,因此DalvikVM JIT的確有放在DalvikVM的roadmap中

但反觀此專案的本質,他們讓Android app能夠透過此另類的middleware在任何的JavaVM上執行,
我相信到後來他們一定會遇到一個困境:他們吸引不到大多數的programmer使用CLDC API撰寫Android app。

DalvikVM在整個Android system framework只是一個小小的部份,其他強大的系統特性與API才是重點,
  1. 所有的DalvikVM process皆由Zygote統籌管理並與DalvikVM合作,可以平行執行而不互相干擾
  2. 提供IBinder與AIDL方便撰寫IPC
  3. dex load進來後內容可以由各個process共享,而不像JavaVM每一個process有各自的class loader
  4. user可以一直開process而不需要提醒自己關閉,Low Memory Killer會主導與管理需要關閉的process,user永遠不會收到OOM (OutOfMemoryError)
  5. app可以在簡訊或來電時接到通知
  6. app可以控制手機上的 GPS, 發送簡訊, 甚至決定撥號與聯絡人操控介面
  7. app之間可以透過Intent 互通有無
Android能夠迅速在市場上竄紅,就是其系統化的思考,以及與AP層的緊密連結,
而這個部份JavaVM永遠不可能做到,因為JavaVM永遠只是user space process。

他們終究不可能把Android整個系統與API、或者類似的功能放到手機上,
而DalvikVM會實作JIT是可預見的未來。

一點淺顯拙見,供大家參考。

2009年6月9日 星期二

Android : Low Memory Killer

Android DalvikVM不會丟出OOM的密技:就是直接砍掉你 Low Memory Killer

user在手機上使用時,會開很多的process,當然每一段時間只會使用一個主process,所以其實LMK會砍掉的是不常被使用或是背景的process,所以不會影響到user experience

比起一般JVM會於heap不夠時立刻丟出OOM,其實LMK的方式對使用者的影響反而比較小,因為使用者再也不用"關閉程式",系統會使用LMK來砍掉(也可以說幫忙關閉)舊的或不常使用的process

Android是一個重視user experience的OS,這就是為什麼Android比J2ME更適合用於消費性電子的手機上