透過Ant跟一些Android SDK的工具,就可以手動產生APK檔案,出處裡頭有張流程圖,很有價值喔~
Archive for 研究與資訊
TelephonyManager
Class Overview
Provides access to information about the telephony services on the device. Applications can use the methods in this class to determine telephony services and states, as well as to access some types of subscriber information. Applications can also register a listener to receive notification of telephony state changes.
如果要傾聽手機的狀態的話,可以透過下面這個函式辦到
listen(PhoneStateListener listener, int events)
Registers a listener object to receive notification of changes in specified telephony states.
| listen(PhoneStateListener listener, int events)
Registers a listener object to receive notification of changes in specified telephony states.
|
ActivityUnitTestCase & ActivityInstrumentationTestCase2
ActivityUnitTestCase
Class Overview
This class provides isolated testing of a single activity. The activity under test will be created with minimal connection to the system infrastructure, and you can inject mocked or wrappered versions of many of Activity’s dependencies. Most of the work is handled automatically here by setUp() and tearDown().
If you prefer a functional test, see ActivityInstrumentationTestCase.
It must be noted that, as a true unit test, your Activity will not be running in the normal system and will not participate in the normal interactions with other Activities. The following methods should not be called in this configuration – most of them will throw exceptions:
- createPendingResult(int, Intent, int)
- startActivityIfNeeded(Intent, int)
- startActivityFromChild(Activity, Intent, int)
- startNextMatchingActivity(Intent)
- getCallingActivity()
- getCallingPackage()
- createPendingResult(int, Intent, int)
- getTaskId()
- isTaskRoot()
- moveTaskToBack(boolean)
- setPersistent(boolean)
The following methods may be called but will not do anything. For test purposes, you can use the methods getStartedActivityIntent() and getStartedActivityRequest() to inspect the parameters that they were called with.
The following methods may be called but will not do anything. For test purposes, you can use the methods isFinishCalled() and getFinishedActivityRequest() to inspect the parameters that they were called with.
ActivityInstrumentationTestCase2
Class Overview
This class provides functional testing of a single activity. The activity under test will be created using the system infrastructure (by calling InstrumentationTestCase.launchActivity()) and you will then be able to manipulate your Activity directly.
Other options supported by this test case include:
- You can run any test method on the UI thread (see UiThreadTest).
- You can inject custom Intents into your Activity (see setActivityIntent(Intent)).
This class replaces ActivityInstrumentationTestCase, which is deprecated. New tests should be written using this base class.
If you prefer an isolated unit test, see ActivityUnitTestCase.
我把兩者的差異性較大的地方用粗體字標出來。
ActivityUnitTestCase的範例在SDK的Sample code裡頭可以找到,ActivityInstrumentationTestCase2則在android source code裡頭有
Android AsyncTask 的怪異行為
AsyncTask是個好物,尤其使用handler 來處理Thread 與 UI thread間畫面的呈現後,回頭看看自己雜亂不堪的程式,更能體會AsyncTask的好~
不過如果同時起一堆AsyncTask後,其實他一點也不Async,事實上他還挺Sync的勒,每個AsyncTask的doInBackground的執行居然還是一個一個排好隊慢慢來,一個執行完後再換下一個。
原因是…請參考下面連結
ps 下面貼一段API告誡開發者的事項,沒注意的話搞不好會犯錯喔~
Threading rules
There are a few threading rules that must be followed for this class to work properly:
- The task instance must be created on the UI thread.
- execute(Params…) must be invoked on the UI thread.
- Do not call onPreExecute(), onPostExecute(Result), doInBackground(Params…), onProgressUpdate(Progress…) manually.
- The task can be executed only once (an exception will be thrown if a second execution is attempted.)
Android 上面取得IMEI
可以透過Context.getSystemService(Context.TELEPHONY_SERVICE)取得TelephonyManager的實體,然後呼叫getDeviceId()取得字串型態的IMEI值
Activity and Task Design Guidelines
今天 Android Developers Blog介紹了一篇文章Activity and Task Design Guidelines,用非常直覺的方式介紹Activity 跟 Task在平台上的行為,裡頭非常多例子(圖文並茂),結尾還提供了一些設計上原則,整篇文章對於不同AP或是同一個AP中的Activities與Task的關係、Notification還有Back key、Home key都有非常清楚的釐清,值得一看!
Android Service 與 Process 相關釐清
前一篇文章看了Shaka的留言,想想還是不要偷懶,查了一下SDK,發現現在的文件已經比我那個時候看的品質好多了:>,覺得自己已經釐清一些問題,想要回個文,不過想要貼的東西有點漏漏藤,放在回文裡頭會有點亂,所以再弄一篇新的。
在Service - Process Life Cycle 裡頭有這麼一句話
If the service has been started, then its hosting process is considered to be less important than any processes that are currently visible to the user on-screen, but more important than any process not visible. Because only a few processes are generally visible to the user, this means that the service should not be killed except in extreme low memory conditions.
所以我遇到的狀況其實文件已經有提到了,我查了一下關於Service的API,發現他有一個onLowMemory的callback function,也就是我煩惱的問題可以在這邊處理。以下是API的說明
public void onLowMemory ()
This is called when the overall system is running low on memory, and would like actively running process to try to tighten their belt. While the exact point at which this will be called is not defined, generally it will happen around the time all background process have been killed, that is before reaching the point of killing processes hosting service and foreground UI that we would like to avoid killing.
Applications that want to be nice can implement this method to release any caches or other unnecessary resources they may be holding on to. The system will perform a gc for you after returning from this method.
另外在AndroidMenifest.xml裡頭可以另外生一個process用來執行service,不過在命名的時候有點小技巧,請看下面第二段
android:process
The name of the process where the service is to run. Normally, all components of an application run in the default process created for the application. It has the same name as the application package. The <application> element’s process attribute can set a different default for all components. But component can override the default with its own process attribute, allowing you to spread your application across multiple processes.If the name assigned to this attribute begins with a colon (‘:’), a new process, private to the application, is created when it’s needed and the service runs in that process. If the process name begins with a lowercase character, the service will run in a global process of that name, provided that it has permission to do so. This allows components in different applications to share a process, reducing resource usage.
關於Shaka提到的background service 與 foreground service,我之前根本就沒有注意到這是瞎咪碗糕(羞),我也順便查了一下資料。照文件說的,service預設都是屬於background service,系統假設其與UI呈現沒有關係,所以當記憶體需要勒緊褲帶的時候,就會先找background service下手,至於service要如何變成foreground service則需要透過Service.setForeground()這個function來達到。
還有一個問題是剛剛我們提到的都是Service 在記憶體不足的時候的行為,那Process在系統out of memory的時候處理的機制為何呢?文件是這麼說的
Android may decide to shut down a process at some point, when memory is low and required by other processes that are more immediately serving the user. Application components running in the process are consequently destroyed. A process is restarted for those components when there’s again work for them to do.
沒錯,依舊殺很大!
最後,Shaka謝謝你嚕~
PS: 目前我處理的方法依舊是使用蛤蟆功配上使用foreground service,同時在onLowMemory再做處理,其實是不是真的還需要繼續使用蛤蟆功是需要斟酌的(不太確定kill process時候是否會觸發onLowMemory函式),不過我有點懶,不想做實驗了:P
有夠阿莎力!
以下部份內容在技術上可能描述不夠精準(憑印象回憶),僅供參考。
當Android在記憶體不足的時候,常常會很阿莎力的把程式的process給殺掉,因為我的程式有跑背景服務,所以即使沒有畫面打在螢幕上,都還會佔據記憶體,自然程式偶而就會被莫名其妙的殺掉,如果這樣子的機制可以神不知鬼不覺的發生,我當然不在意,可是很不幸的我的背景服務程式是需要去維護ongoing notification畫面上方的小圖示,天啊!程式已經被殺光光了,下載圖示還高高掛在哪,是鬼打牆還怎樣!
我嘗試透過DDMS去複製這個問題,發現在ongoing notification行為與我類似的其他程式(例如 imeem)也會發生令人同樣費解的狀況。目前我透過醜陋的方式解決這個問題,在我主程式的進入點與ongoing notification 的pending intent所指定的類別裡個別去做判斷並處理onging notification(service recovery 或者把ongoing notification給取消掉)。
如果有隱居山林的奇人無意間看到我的文章,且身懷九陽真經可以引領我離開走火入魔之境,請讓小弟知道,因為蛤蟆功實在難登正統中原大雅之堂啊!
Webware 100 Winners!
一定要看看的資訊。
Welcome to the 2009 Webware 100! Below you’ll find 100 Web apps in 10 categories voted to be the best of the best by Webware readers and users of the apps themselves.
Be sure to also see the new 11th category, Editors Choice, for a list of 12 products that we feel merit inclusion in this year’s awards program, even if they weren’t big enough to win the popular vote.
Congratulations to the winners of the Webware 100!
來源:cnet Webware
Houston, We have a problem!
過去我的Android程式很少會出現ANR (Application Not Response)狀況,不過自從把平台升級到1.5之後,ANR出現的次數就明顯增多了,目前透過/data/anr/traces.txt觀察到的結果如下:
—– pid 16896 at 2009-05-05 06:47:57 —–
Cmd line: com.blackdidi.podcast
DALVIK THREADS:
“main” prio=5 tid=3 NATIVE
| group=”main” sCount=1 dsCount=0 s=0 obj=0×40018e70
| sysTid=16896 nice=0 sched=0/0 handle=-1091085172
at com.ibm.icu4jni.util.Resources.getTimeZonesNative(Native Method)
at com.ibm.icu4jni.util.Resources.createTimeZoneNamesFor(Resources.java:223)
at com.ibm.icu4jni.util.Resources.getDisplayTimeZones(Resources.java:273)
at java.text.DateFormatSymbols.internalZoneStrings(DateFormatSymbols.java:111)
at java.text.SimpleDateFormat.appendTimeZone(SimpleDateFormat.java:564)
at java.text.SimpleDateFormat.append(SimpleDateFormat.java:529)
at java.text.SimpleDateFormat.formatImpl(SimpleDateFormat.java:923)
at java.text.SimpleDateFormat.format(SimpleDateFormat.java:774)
at java.text.DateFormat.format(DateFormat.java:459)
at java.util.Date.toString(Date.java:728)
at java.lang.StringBuilder.append(StringBuilder.java:209)
啥鬼!這樣子也會出現ANR的狀況,我的程式剛在Android 1.5平台上的時候就有因為locale的問題出了一次包(因為1.5可以切換locale,導致SimpleDataFormat的文字解析出現問題),不過從來都沒有想到類似的狀況會反應到ANR上@@
根據traces.txt所提供的call stack,目前猜測是IBM icu lib (ResourceInterface.cpp)在搞鬼,先去吃早餐,改天再來瞧瞧問題在哪裡(天啊!我的好奇心真的要讓我去追莫名其妙JNI跟腦中空谷C++嗎?)






