Wednesday, September 17, 2014

不要過度依賴Activity.onDestroy()去執行程式

文章攢寫時間︰2014/09/17 15:00

一、問題

今天遇到一個crash,
DVM由於Android背景執行的程式過多,
可執行app的記憶體不足,
直接將我服務進程砍掉(kill process),
然而我在Activity.onDestroy()裡做了很多值的還原或歸零(預設值)的動作,
因為這種方式,
導致所有該還原回預設值的動作,
通通沒做

二、解決辦法

這件事算是學了個經驗,
開發者無法預期使用者一定會使用返回鍵(Back button)將程式正常關閉,
因為可能有很多"外在"因素會造成你的程式被強制終止。

所以,
不要在Activity.onDestroy()做許多值還原或歸零(預設值)的動作,
因為你根本無法預期這些行為在低階手機裡是能被正確執行的。

三、其它

static變數在Android裡的生命週期

以下內容來源︰stackoverflow

Lets start with a bit of background: What happens when you start an application?
我們來談一些關於android背後的機制︰當你啟動了一個應用程式(application)後,背後究竟發生了些什麼事?

The OS starts a process and assigns it a unique process id and allocates a process table.A process start an instance of DVM(Dalvik VM); Each application runs inside a DVM.
在啟動了一個應用程式以後,作業系統開啟了一個進程(process),並同時給這個進程一個專屬進程id,並分配給進程一個進程資料表(process table,用來儲存該進程的所有相關資訊)。然後,這個進程會啟動一個DVM(Dalvik VM,Dalvik虛擬機)實體,每一個應用程式(application)都分別運作在各自的DVM裡。

A DVM manages class loading unloading, instance lifecycle, GC etc.
DVM管理著每個class是否要被載入(loading unloading)、生命週期、實體、資源回收(Garbage Collection)等等。

Lifetime of a static variable: A static variable comes into existence when a class is loaded by the JVM and dies when the class is unloaded.
static變數的生命週期︰當一個class被JVM載入後,static變數值就會被產生,當class被卸載後,static變數值就會被消毀。

So if you create an android application and initialize a static variable, it will remain in the JVM until one of the following happens:
1. the class is unloaded
2. the JVM shuts down
3. the process dies

Note that the value of the static variable will persist when you switch to a different activity of another application and none of the above three happens. Should any of the above three happen the static will lose its value.
所以,當你建立了一個android應用程式並且初始化了static變數後,這個static值就會被保留直到下列事件發生為止︰
1.class被卸載
2.JVM被關閉
3.進程(process)被消滅了
備註︰當你切換到不同的應用程式的Activity時,原Activity的static變數都會一直被保留,除非上述的事件被觸發。一旦被觸發後,static變數就會遺失原來的值。

You can test this with a few lines of code:
1.print the uninitialized static in onCreate of your activity -> should print null
2.initialize the static. print it -> value would be non null
3.Hit the back button and go to home screen. Note: Home screen is another activity.
4.Launch your activity again -> the static variable will be non-null
5.Kill your application process from DDMS(stop button in the devices window).
6.Restart your activity -> the static will have null value.
你可以用下列的方式試試上述的理論︰
1.在Activity onCreate()函式裡印岀未初始化的static變數值-->應該印岀null。
2.初始化static變數值-->印岀來的值應該就不是null值了。
3.點擊手機返回鍵並回到手機Home首頁(備註︰Home首頁就是另一個Activity)。
4.重啟你的Activity-->static變數值理論上不會是null。
5.從DDMS砍掉你的應用程式進程(在Eclipse ADT裡有一個Devices視窗,裡面有stop按鈕,見下圖)。
6.重啟你的Activity-->static變數值將會變成null。
Devices視窗裡的Stop按鈕。

如果看不到這個視窗,請在Eclipse工具列[Window]-->[Show View]-->[Other]-->[Android]-->選擇[Devices]即可岀現該Devices視窗。

Wednesday, September 10, 2014

使用adb螢幕截圖

adb工具除了快速安裝apk外,
還可以截圖
Terminal指令如下

將當下螢幕截取至手機的sdcard資料夾,並命名為screen.png
$adb shell screencap -p /sdcard/screen.png

將檔案從手機複製到電腦預設根目錄(以Mac來看是Users/youname底下)
$adb pull /sdcard/screen.png

刪除手機裡剛才存放的圖檔
$adb shell rm /sdcard/screen.png

Tuesday, September 9, 2014

使用ant產岀apk時遇到invalid resource directory name: crunch

文章攢寫時間︰2014/09/10 12:10

一、問題

今天在使用ant build apk時遇到
[aapt] invalid resource directory name: /Users/yourname/Android/adt-bundle-mac/sdk/extras/google/google_play_services/libproject/google-play-services_lib/bin/res/crunch
的問題。

二、解決辦法

這是因為ant無法處理crunch資料夾

1.先把Eclipse中[Project]-->[Build Automatically]關掉(否則crunch資料夾會一直被自動生成)
2.到google_play_service專案中,將bin/res/crunch刪除
3.重新下指令
$ant clean release
產岀專案
如果日後需要Build Automatically時,再將其選項打開

使用command line查岀apk包檔時用的signature

想要查岀apk包了哪個signature,
除了用Android的PackageManager查岀SHA1外,
還能在command line使用指令查看簽章的名稱。

指令為
$jarsigner -verify -verbose -certs 你的apk路徑