顯示具有 Intent 標籤的文章。 顯示所有文章
顯示具有 Intent 標籤的文章。 顯示所有文章

2016年3月25日 星期五

在 Android 中,有哪些 IPC 方法?

前不久在我的 Facebook 上,問了底下這個問題:

在 Android 中,當 process A 要向 process B 索取動態 parcelable 資料 (動態資料指,資料是經由計算所產生) 時,你會用甚麼方式來做?

1. 最常見的方法是 Service + AIDL (http://developer.android.com/guide/components/aidl.html)。

還有誰要貢獻其他方法?

最後找出將近十種方法,還有範例與文件,有興趣的自行點下面連結參考。

https://www.facebook.com/samlu128/posts/10204283071555842


繼續閱讀全文...

2013年7月17日 星期三

APP定期與SERVER同步資料應該要注意的事

今天一位國外開發者遇到他的應用在定期與 server 同步資料時,因為 2x Battery 會將網路斷開,而造成他的程式始終無法抓到資料,來信問我是否有解法。其實就算使用者沒裝 2x Battery, 手機上的網路還是隨時會處於無法連線的狀態。因此,真要寫一個定期 polling (or post) 的 app。我建議還是要寫個 broadcast receiver 監聽android.net.conn.CONNECTIVITY_CHANGE intent。如果上次同步沒成功,就可在連線恢復時,繼續上次的同步工作。

有興趣知道細節的,可先閱讀底下資料:

原先這文章是發佈在我的 facebook, 有位網友加入討論,我覺得值得在這分享我們的討論給大家。底下就是我們的後續討論:


Julian Shen: 這Intent使用上要稍微小心, 網路有變化就會收到(像是3G<->Wifi),在網路不穩定的環境下就很容易頻繁收到, 在這份 document : http://developer.android.com/training/monitoring-device-state/connectivity-monitoring.html 有特別提到"it's good practice to monitor this broadcast only when you've previously suspended updates or downloads in order to resume them."


盧育聖: Julian Shen 你說的沒錯。

Android's DownloadManager 就是靠 CONNECTIVITY_CHANGE 來恢復網路下載的工作。想深入研究的開發者,可參考底下 Android 原始碼的實作。

  • packages\providers\DownloadProvider\src\com\android\providers\downloads\DownloadReceiver.java
  • packages\providers\DownloadProvider\src\com\android\providers\downloads\DownloadService.java

盧育聖: 另外補充 Julian Shen 提到的會頻繁收到 CONNECTIVITY_CHANGE intent 問題的解法。實務上,這個 receiver 預設是處於 disabled (加 android:enabled="false") 狀態的,只有當你上次同步失敗時,才 enable 這個 receiver,同步好後,記得要 disable 該 receiver。

如何動態 enable/disable receiver,請見:

http://developer.android.com/training/monitoring-device-state/manifest-receivers.html


看到這,你是否有不同的想法或解決方法?也歡迎在此一起討論。


繼續閱讀全文...

2012年2月27日 星期一

How to install/uninstall app with PackageInstaller?

How to install/uninstall app with PackageInstaller?
Reference: http://android.amberfog.com/?p=98
==============================
String fileName = Environment.getExternalStorageDirectory() + "/myApp.apk";
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(new File(fileName)), "application/vnd.android.package-archive");
startActivity(intent);
==============================
Uri packageURI = Uri.parse("package:com.android.myapp");
Intent uninstallIntent = new Intent(Intent.ACTION_DELETE, packageURI);
startActivity(uninstallIntent);
==============================
int result = Settings.Secure.getInt(getContentResolver(), Settings.Secure.INSTALL_NON_MARKET_APPS, 0);
if (result == 0) {
// show some dialog here
// ...
// and may be show application settings dialog manually
Intent intent = new Intent();
intent.setAction(Settings.ACTION_APPLICATION_SETTINGS);
startActivity(intent);
}
==============================

繼續閱讀全文...

2011年3月4日 星期五

讓癮科技 Android 應用登上榜首的秘密

How do I make my Engadget(Chinese Version) app to become the most popular app?

經過將近一個月的測試,2011/2/6 首次發行 癮科技 Android app 到 Android Market 上。六天後的今天 (2011/3/3),這個應用很快地爬到「新聞與雜誌」類別排行榜中的第一名位置,同時也是所有應用程式排行榜的第四名。在目前 Android Market 已有 16 萬個 Android 應用 一起激烈競爭的情況下,新的應用能這麼快登上排行榜,真的是一件很不容易的事。這中間,癮科技寫的「不要再叫我們蘋科技!癮科技新聞訂閱程式也有Android版了」這篇介紹文,當然有很大的幫助。

除此之外,到底有什麼樣的秘訣,才能讓我的應用程式登上排行榜呢?這是我最常被兩岸開發者問到的問題之一。

要讓應用程式登上排行榜,可以分成非技術面與技術面兩個面向來談。非技術的部份,我早在 2009/10 一場研討會的「發現 Android 熱門應用程式的秘密」的講座中,分享給大家。只不過這場演講主要的對象是對岸的開發者,對於台灣的開發者,只好等下次有人邀請我演講時,我再分享給大家。

技術面的部份,最主要的除了不能讓你的應用程式輕易當機之外,當然就是要讓使用者用起來很順暢才行。「使用的很順暢」這句話講起來很輕鬆,不過卻是得花最多時間與人力去調整各項細節,才能做到的地方。

這些細節,使用者當然不會注意到,也不會告訴你。就看你是否知道使用者的痛苦(需求),以及你如何深入了解這些痛苦的解決方法是甚麼。在這裡我就拿我最近開發的癮科技 app 來當案例。說明我們在技術的層面上,做了哪些努力。

第一:這不是一個單純的 RSS reader。一般這樣的應用程式開發者,可能都會以 RSS reader 的架構來開發這樣的應用。為了讓這個應用能跑得更順,我們決定走不一樣的路,在 server 端提供專屬的 APIs,在手機端也做了一些一般 RSS reader 做不到的功能。例如,你可以往下一直看過去的 N 篇文章。

第二:所有抓下來的文章與圖片,都存到 SD 卡上,以節省手機儲存空間的使用。多數的手機,內部儲存空間都是有限的,這造成使用者常要刪除舊的應用,以增加多餘的空間來裝新應用。這從我的 App 2 SDaCCleaner 應用受歡迎的程度,就可以了解使用者在這方面的需求很大。如果你的應用佔的空間太大,在這點就吃虧很多。看到這,你可能會說這有什麼,大家都有這功能。不對,細節就在這裡。如果你有使用其他的新聞閱讀軟體,就可以觀察到他還是吃了不少 data/cache 空間。這原因就在你應用所建立的 Sqlite database 以及 WebView 所建立的 database/cache 都還是存在內部儲存空間。要將這些完全移到 SD 卡上,這可花了我好幾天追蹤原始碼,才知道要怎麼解決這個問題。目前,我只將 preferences 存在內部儲存空間中,其他都移到 SD 卡上。

第三:自動縮放文章中的文字與圖片大小。水平捲動對手機使用者來說,是一件很痛苦的事,這是千萬要避免發生的事。自動縮圖片,就是要解這問題。另外,多數的新聞閱讀應用的字體大小都太小了,行距也不對。這對要長時間閱讀文章的人,是一種折磨。你現在看到文章中的預設字體大小與行距,可是我們花了好多時間才調校出來的。你說,這不又是一個要在細節下功夫的地方?

第四:離線也能閱讀文章。離線閱讀的功能,對於這樣的新聞應用是一個很重要的功能,這樣使用者才真的能隨時隨地都可以看文章。文章與圖片都存到 SD 卡上,不是就能實現這個功能了嗎?不對,這只做了一半。另外一半就是你還要實現自動預下載文章的功能,有了這功能使用者才能隨時隨地有「新」文章可看。寫網路程式可算是手機程式中一件非常有挑戰的事,因為手機的 CPU 會進入 sleep 模式,網路可能隨時會中斷,速度可能掉到 GPRS 的速度等等各式各樣的問題都會出現。這些種種你必須要面對的問題,你都得處理,才能讓你的應用跑得很 solid。

雖然我們做了這麼多的努力,這個應用還有一些沒做好的部分。我們還會繼續在這個應用中奮戰好一段時間,在接下來的新版本中,我們會陸續解決這些問題,敬請期待!


繼續閱讀全文...

2009年9月21日 星期一

Android 原始碼徹底研究系列 - 鬧鐘程式, Alarm Reminder (4)

Android Source Code Internals - Alarm Clock, Alarm Reminder (4)

在了解鬧鐘程式各個功能是如何實現後,這次我們要來追蹤『提醒鬧鈴時間到達』這個功能是如何實現的。

要追蹤應用程式的原始碼,先觀察 AndroidManifest.xml 通常是最好的方式。

首先,我們先打開 AlarmClock 的 AndroidManifest.xml 檔案。注意看 #52~#64 這兩個 broadcast receivers。

AlarmReceiver 應該就是當鬧鈴時間到達時,要執行的程式。而 AlarmInitReceiver 則是當手機重開機,時間被重新設定,或是時區改變時,所要執行的程式。

讓我們先打開 AlarmInitReceiver.java 看看。#31~#42 這個 onReceive() 內的程式就是關鍵。

從其呼叫的函式名稱,不難理解出這段程式的主要工作,就是重新設定下一個鬧鈴。在這裡的 Intent.ACTION_BOOT_COMPLETED ,就是手機重開機時,所發出的系統 Intent。

接著,我們打開 Alarms.java 看看 setNextAlert() 這個函式到底在做些甚麼事。

看起來,enableAlert() 就是負責設定下一個鬧鈴的主要函式。

從程式中,我們了解到他先透過 AlarmManagerset() 函式,設定鬧鈴時間,以及鬧鈴時間到達時,所要喚起的程式。由於是透過 PendingIntent.getBroadcast() 取得 PendingIntent 的 instance,因此我們知道這個被喚起的程式應該是個 broadcast receiver。

那到底是那個 broadcast receiver 會被喚起呢?從程式看來,應該就是喚起會接收 ALARM_ALERT_ACTION action 的 broadcast receiver。在此的 ALARM_ALERT_ACTION 就是 "com.android.alarmclock.ALARM_ALERT" 字串。

讓我們再翻開 AndroidManifest.xml 瞧瞧,會接收 com.android.alarmclock.ALARM_ALERT 的 broadcast receiver,不就是 AlarmReceiver?!

打開 AlarmReceiver.java。仔細研讀一下,不難理解這段程式的主要工作就是:

  1. 先喚醒可能正在沉睡中的 CPU 與螢幕
  2. 暫時解開鍵盤或螢幕鎖
  3. 執行 AlarmAlert 這個 Activity,也就是你最終看到的鬧鈴提醒對話框。

最後,你有沒有發現,一般我們設定的 notification icon 都是出現在 status bar 的左手邊。而 AlarmClock 的鬧鈴 icon 卻是出現在右手邊的系統 icon 區?想要知道他是如何做到的?再回頭看 Alarms.java 中的 enableAlert(),其最後會呼叫 setStatusBarIcon() ,我想答案應該就在其中。

打開 setStatusBarIcon(),其內容如下:

竟然是透過送出 ACTION_ALARM_CHANGED Intent,來設定 notification icon 的。看來,這是個未公開的用法。了解這些特別的用法,這不就是你研讀系統原始碼的好處之一嗎?


繼續閱讀全文...

2009年7月13日 星期一

Android 原始碼徹底研究系列 - 鬧鐘程式, AnalogClock (1)

Android Source Code Internals - Alarm Clock, AnalogClock (1)

鬧鐘的原始程式碼在 這裡

PS: 請不要向我要原始碼,所有Android原始碼都可已自行下載,詳情請見 https://source.android.com/source/building.html

一執行這個鬧鐘程式,畫面上第一眼看到的,就是一個大大的時鐘。因此我們今天,就先從這個時鐘下手。讓我們一探究竟,看他是如何實現的。

要了解這個時鐘,是用什麼元件做出來的。有兩個方法,第一個就是用 SDK 內自帶的 Hierarchy Viewer 工具;另一個,就是直接觀察 res/layout 中的畫面設計檔。這次,我們直接用第二個方法。

翻開 AlarmClock/res/layout 目錄的內容,你會發現有好幾個 clock_xxx.xml 的檔案。打開其中的 clock_droid2.xml 檔。內容如下所示:

嗯,看起來,這個時鐘就是用 android.widget.AnalogClock 這個元件直接實現的。只要透過 android:dial, android:hand_hour, android:hand_minute 這三個 XML 屬性,指定鐘面,時針與分針的圖檔,一個完整的時鐘,就會顯現出來。最上方的圖片,就是這個時鐘顯示的樣子。

都不需要任何額外的設定,這個時鐘元件就會自己依照目前的時間,將時、分針顯示在正確的位置,那他是如何定時更新時、分針位置?另外,注意到了嗎,時、分針的圖檔,只有一份。從這就猜到,這個時鐘還會自動將時、分針圖旋轉至正確的角度,貼在螢幕上。讓我們來看看,這個 AnalogClock 元件是如何實現這些功能的。

打開 AnalogClock 元件原始碼,扣掉最前面的註解不算,整個原始碼也才不到 230 行。這麼少的程式碼,卻能將這個時鐘功能做得這麼完整。這也是我常最推薦,一定要看的元件原始碼之ㄧ。

這次,我們要看的重點有兩個。

  1. 在元件程式中,要如何隨時都知道時間的改變?
  2. 在 Android 中,要如何將圖片做任意角度的旋轉,並貼在螢幕上?

在元件程式中,要如何隨時都知道時間的改變?

原來在 onAttachedToWindow() 中,AnalogClock 透過 registerReceiver() 註冊了三個由系統發出的 Actions,ACTION_TIME_TICK, ACTION_TIME_CHANGEDACTION_TIMEZONE_CHANGED

在 Android 中,系統會透過 Intent 傳送某些系統通知訊息,這些通知訊息又稱為 Action。在 Intent 類別的說明中,你可以找到所有的 Action 定義。

在你的程式中,想要收到這些系統通知訊息,有兩個方法。第一個方法就是在 AndroidManifest.xml 中定義 receiver 的類別,這個方法在日後的介紹中會提到。第二種方法就是利用 registerReceiver(),向系統註冊接收的類別。由於 AnaloClock 是以元件的方式存在,如果每次使用這個元件,都還要在 AndroidManifest.xml 中定義,那就太麻煩了。因此, AnaloClock 採用的是第二種方法。

其中,ACTION_TIME_TICK,就是由系統在每分整,傳送出來的 Action。ACTION_TIME_CHANGED 則是當使用者更改系統時間時,所送出的 Action。當你的手機跨越時區,系統則會送出 ACTION_TIMEZONE_CHANGED 給有註冊的程式。

一但這些 Actions 發生時,他會呼叫在程式最後 new 出來的 BroadcastReceiver 物件, mIntentReceiver,中的 onReceive() 回呼函式。

首先,在 onReceive() 中,先檢查如果是時區有改變的話,當然你要重新設定 mCalendar 變數。

onTimeChanged() 函式,只是重新抓出最新的時、分資料。

在 onReceive() 的最後,再呼叫 View.invalidate()。這個動作,會觸發 View.onDraw() 函式的呼叫,並在螢幕上畫上最新的時,分針。

在 Android 中,要如何將圖片做任意角度的旋轉,並貼在螢幕上?

Android 的 2D 繪圖功能,其實是很強的,尤其是 matrix 這部份。透過 matrix,你就可以輕易地,控制整個繪圖座標體系的位移、旋轉、傾斜,放大等功能。舉個例子來說,如果你要將圖片旋轉 30 度後,再貼在螢幕上。傳統的作法,都是直接先將圖片的內容,逐點旋轉 30 度。但是在 Android 平台上,你不用這麼麻煩。你只要將整個座標系統轉個 30 度,之後不管你是畫線,還是貼圖,最後呈現在螢幕上的都是轉 30 度的效果。

想要了解 AnalogClock 是如何選轉時、分針圖片,那看 onDraw() 這個函式就對了。我將 onDraw() 中,和這部份選轉時、分針圖片相關的,列在下面。其中的 canvas.rotate() 是關鍵,這個函式就是在將座標系統轉個角度。看完這個例子,有沒有發覺要在 Android 上旋轉、放大或縮小圖片,其實都是只要兩三行程式,就可搞定的事。

AnalogClock 就剩 constructors,與其他 onMeasure(), onSizeChanged(), onDetachedFromWindow() 等函式還沒提到,我想這部份就留給你自己去發掘。


繼續閱讀全文...

2008年12月29日 星期一

Intent 用法大公開

How to use Intent to send an email, SMS, open a web browser, show map, etc.?

Intent 應該算是 Andorid 中特有的東西。你可以在 Intent 中,指定要應用程式執行的動作 (view, edit, dial),以及應用程式執行該動作時,所需要的資料。都指定好後,只要透過 startActivity(),Android 系統會自動尋找,最符合你指定要求的應用程式,並喚起執行該應用程式。

不過,這部份的文件還不是很完整。Reference of Available Intents 有列一些。底下是我收集的一些用法,分享出來給有需要的你。有些還沒有實際驗證過,如果發現有錯誤,或有新的用法,也請告訴我。

顯示網頁

顯示地圖

路徑規劃

撥打電話

傳送 SMS/MMS

傳送 Email

顯示聯絡人清單

顯示某個朋友的詳細資料

播放多媒體

從圖庫中回傳選到的圖片

啟動照相機,並將相片存在指定的檔案中

Market 相關

Uninstall 應用程式

安裝 APK 檔


繼續閱讀全文...