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

2013年5月14日 星期二

[Android] onSaveInstanceState/onRestoreInstanceState

  • 在離開畫面時 onSaveInstanceState() 會被呼叫並保存下當時畫面狀態於 bundle 中,以預防此畫面被不預期關閉; 這樣要重新開啟時,onRestoreInstanceState() 能藉由保存下來的資料來回到關閉前的狀態。
  • 預設會保留住 setContentView 狀態 (ex: 輸入值)。
  • onSaveInstanceState 一定會發生在 onStop 前 但不一定是在 onPause 前或後。
  • 從 Honeycomb 開始 在收到 onStop 回傳前 都不是 kiiable status 這時 onSaveInstanceState 可能會在 onPause 後才被呼叫。

Activity a to Activity b running orders:
  • Open b in a
    • a: onSaveInstanceState -> onPause -> onStop
  • Change orientation:
    • a: onSaveInstanceState -> onPause -> onStop -> onDestroy -> onCreate -> onStart -> onRestoreInstanceState -> onResume
  • Open b with dialog theme in a:
    • a: onSaveInstanceState -> onPause (因為還能看到 a 所以不會呼叫 onStop()!)


以下狀態下不會呼叫 onRestoreInstanceState
  • 從程式集開啟 app 時。
    • onCreate -> onStart -> onResume
  • 從 Activity b 返回 Activity a。
    • onRestart -> onStart -> onResume


* Reference
- onSaveInstanceState
- onRestoreInstanceState

2013年1月26日 星期六

[Android] get system values when reboot

Error Message

若是 livewallpaper app

重開機時 取到的 system values 會是 0 (ex: imei, iccid...)



Solution

若已設定 livewallpaper 然後重開機

在開機中 system 便會呼叫 livewallpaper

此時所取到的 system values 便會是 0

可等接收到 BOOT_COMPLETED action 後 再去取 便能取到正確值

或是判定為 SIM_STATE_READY 才將取到的值視為有效值


飛安模式 -> SIM_STATE_UNKNOWN -> 取不到

關閉網路 -> SIM_STATE_READY -> OK


測試中(HTC One V) 轉換飛安模式和一般模式的行為 會使得物件等被清除

仍不確定是否依手機而異 與影響範圍

2012年6月15日 星期五

[Android] Context

public abstract class Context
  • 管理 global application 資訊的 interface,是由 Android System 實作。
    • Interface to global information about an application environment. This is an abstract class whose implementation is provided by the Android system.
  • 可由此取得 application-specific 的 resources and classes。
    • It allows access to application-specific resources and classes, as well as up-calls for application-level operations such as launching activities, broadcasting and receiving intents, etc.

getApplicationContext()
  • 在啟動 app 時,預設會啟動 Application,也就是 AndroidManifest.xml 中的 <application>,因此也能自己實作指定在此 tag 中,替代此預設。
  • 回傳所在 process 中的 global application context。
    • Return the context of the single, global Application object of the current process.
  • 應被使用在當 lifecycle 不和當前 component 綁在一起時。
    • This generally should only be used if you need a Context whose lifecycle is separate from the current context, that is tied to the lifetime of the process rather than the current component.
ex: 
  • registerReceiver(BroadcastReceiver, IntentFilter)
    • 如果使用的是 Activity context,這個 receiver 就是被註冊在此 Activity,所以你必須在此 Activity destroy 前 unregister 此 receiver,若沒有這樣做則會發生 exception。
      • If you use the Activity context to register a receiver that is static (global to the process, not associated with an Activity instance) then that registration will be removed on you at whatever point the activity you used is destroyed.
    • 如果是使用 Application context,這個 receiver 是和 application 相關連,因此不會被 unregistered,但有可能會造成 leak。
      • However using the ApplicationContext elsewhere can easily lead to serious leaks if you forget to unregister, unbind, etc.
  • 使用在 DB 操作時。


* Reference
- 求getApplicationContext用法-Android 问题&解答-eoeAndroid开发者社区 - Powered by Discuz!
谈谈Android里的Context的使用!!! - Android_Tutor的专栏 - 博客频道 - CSDN.NET

2012年5月20日 星期日

[AndroidDev] Managing the Activity Lifecycle

  • 如果 AndroidManifest.xml 中沒有任何 activity 有宣告 MAIN action 與 LAUNCHER category,此 app 的 launch icon 則不會出現在 app list 中。
  • onPause <-> onResume
  • onStop -> onRestart -> onStart -> onResume

onCreate()
  • 適合處理在整個 activity life 中只應處理一次的邏輯,ex: 初始化 class-scope variables。

onRestart()
  • 當 activity 是從 onStop() 被啟動時,系統才會呼叫此 method。所以若是有在 onStop() 中釋放資源,記得在此初始或設定。

onStart()
  • activity 已為可見狀態,但會很快的便進入 onResume()。

onResume()
  • 會停留到 resume 完 activity 到暫停前的狀態。

onPause()
  • activity 仍為半可視狀態,ex: 被 dialog 覆蓋。
  • 可表示 user 離開此 activity 而進入 onStop(),所以可執行:
    • Stop animations or other ongoing actions that could consume CPU.
    • Commit unsaved changes, but only if users expect such changes to be permanently saved when they leave (such as a draft email).
    • Release system resources.
      • broadcast receivers, handles to sensors (like GPS).
      • Any resources that may affect battery life while your activity is paused and the user does not need them.
  • 不需要在此儲存 user 所輸入的資料,因為其實此 Activity instance 還是被儲存在 memory 中的,所以當在 onResume(),元件的狀態會再被重新載入,除非這是項明確功能:
    • ex: email 會自動儲存為草槁。
  • 不適合在此中處理會耗費 CPU 的工作,ex: 寫入 DB,因為會拖慢顯現下一個 activity 的速度,所以這類型的工作更適合在 onStop() 中處理。
    • 要到 activity B 前,activity A 需先進入 onPause()。

onStop()
  • 保證 UI 不是可視的,user 已在使用另一個 activity 或 app。
  • 適合做耗費 CPU 的工作:
    • ex: 寫入 DB。
  • 不需要在此儲存 user 所輸入的資料,因為其實此 Activity instance 還是被儲存在 memory 中的,所以當 onResume(),元件的狀態會再被重新載入。
    • ex: If the user entered text into an EditText widget, that content is retained so you don't need to save and restore it.
    • 即使 activity 被 destroy,其中的 View objects 仍會被儲存在 Bundle 中,並且在 user 回到此 activity(the same instance of the activity) 時被重新載入。
  • 以下情況使得 activity A 會被 stopped 與 restarted:
    • user 由 Recent Apps window 開啟另一個 app,activity A 會進入 onStop(),若 user 再由 Home launcher icon or Recent Apps window 開啟你的 app,那麼 activity A 會進入 onRestart()。
    • 在你的 app 中進入下一個 activity,activity A 會進入 onStop(),若 user 按下 Back 鍵,activity A 會進入 onRestart()。
    • user 在使用 app 時有來電。

onDestroy()
  • The system calls onDestroy() after it has already called onPause() and onStop() in all situations except one:
    • when you call finish() from within the onCreate() method.
    • onCreate() 會直接進入 onDestroy()。

以下情況可能會使得你的 activity 被 destroyed:
  • The user presses the Back button.
  • Calling finish().
  • Activity is in onStop() 且已長時間沒有被使用而被系統回收。
  • Foreground activity 需要更多資源,因此關閉 background processes to recover memory。

若 activity 是被系統回收,那麼系統會記下它的狀態(is called the "instance state", stored in a Bundle object.),以在 user 想開啟此 activity 時能 restore 該狀態。

onSaveInstanceState()
  • 當系統要 destroy this activity,會呼叫此 method,並且傳入 Bundle object 來儲存 activity 資訊,所以你若有需要保存的資訊也可儲存在此 Bundle 中。
  • 然後此 activity 會被系統 recreate 並且傳入與 destroy 時相同的 Bundle object,因此可以在 onCreate() 中從 Bundle 中取出之前所儲存的資訊。
    • 但因為 activity 可以是完全新建立或是重新被建立的,也就是說傳入的 Bundle 不一定都是有值的,若是要使用,務必判斷是不是 null。
    • 或者與其在 onCreate() 中 restore 資訊,也可以選擇在 onRestoreInstanceState() 做。
      • 此 method 會在 onStart() 後被呼叫。
      • 只有在 Bundle != null 時會被呼叫。
  • The default implementation of this method saves information about the state of the activity's view hierarchy:
    • ex: he text in an EditTextwidget or the scroll position of a ListView. 
    • 所以在此 method 和 onRestoreInstanceState() 中記得呼叫 super.xxxx; 以儲存與重載 the state of the view hierarchy。


* Reference
- Starting an Activity | Android Developers
- Pausing and Resuming an Activity | Android Developers
- Stopping and Restarting an Activity | Android Developers
- Recreating an Activity | Android Developers

2012年3月25日 星期日

[Android] System installer, Unmounted SD Card


如果安裝好 app 則立即點開啟 -> Home -> 點擊 app icon 開啟
  • 會在同個 task create another app (onCreate)。

如果 SD Card 發生不預期時移除
  • 系統則會殺掉正在使用 SD Card 的 process,再重啟(但不一定會重啟成功)。

2011年11月1日 星期二

[Android] Start Activity in Service or Content Provider

* 可以在 Service 或 Content Provider 中開啟 Activity,但 Intent 中必須加入 Intent.FLAG_ACTIVITY_NEW_TASK Flag 才行,否則會出現以下錯誤。


* In Service
   ......
java.lang.RuntimeException: Unable to start service com.yellow.android.service.EmptyService@444bde30 with Intent { cmp=TestService}: android.util.AndroidRuntimeException: Calling startActivity() from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want?
   ......
Caused by: android.util.AndroidRuntimeException: Calling startActivity() from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want?
at android.app.ApplicationContext.startActivity(ApplicationContext.java:560)
   ......


* In Content Provider
   ......
android.util.AndroidRuntimeException: Calling startActivity() from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want?
at android.app.ApplicationContext.startActivity(ApplicationContext.java:560)
   ......


* Pending Issues
  • Why must sartActivity with new task?
  • Different tasks in an application will have any effects?


Related

2011年10月30日 星期日

[Android] CalledFromWrongThreadException

Error Message
at android.os.AsyncTask$3.done(AsyncTask.java:200)
at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:273)
at java.util.concurrent.FutureTask.setException(FutureTask.java:124)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:307)
at java.util.concurrent.FutureTask.run(FutureTask.java:137)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1068)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:561)
at java.lang.Thread.run(Thread.java:1102)
Caused by: android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
at android.view.ViewRoot.checkThread(ViewRoot.java:2705)
at android.view.ViewRoot.invalidateChild(ViewRoot.java:574)
at android.view.ViewRoot.invalidateChildInParent(ViewRoot.java:600)
at android.view.ViewGroup.invalidateChild(ViewGroup.java:2450)
at android.view.View.invalidate(View.java:4945)
at android.widget.TextView.checkForRelayout(TextView.java:5442)
at android.widget.TextView.setText(TextView.java:2693)
at android.widget.TextView.setText(TextView.java:2561)
at android.widget.TextView.setText(TextView.java:2536)
at com.yellow.android.TextActivity$1.onProgressUpdate(TextActivity.java:40)
at com.yellow.android.TextActivity$1.doInBackground(TextActivity.java:32)
at com.yellow.android.TextActivity$1.doInBackground(TextActivity.java:1)
at android.os.AsyncTask$2.call(AsyncTask.java:185)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
 ... 4 more



Solution

Caused by: android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.

一般是因為沒有在 UI thread 執行關於 UI 上的操作 所以會利用 AsyncTask

原以為是因為在 AsyncTask 中使用 Thread.sleep() 而發生的 exception

但重寫後並不是

所以目前不確定發生的情況與真正原因


2011年9月17日 星期六

[AndroidDev] Process and Thread

[Process]
* 如果 application 在沒有任何 component 被執行中的情況下開啟,則會開啟新的 process 執行單一執行緒;若是已有被執行中的 component,則會在相同的 process and thread 執行你所要執行的功能。
  • When an application component starts and the application does not have any other components running, the Android system starts a new Linux process for the application with a single thread of execution.
  • By default, all components of the same application run in the same process and thread (called the "main" thread).
  • If an application component starts and there already exists a process for that application (because another component from the application exists), then the component is started within that process and uses the same thread of execution.
* However, you can arrange for different components in your application to run in separate processes, and you can create additional threads for any process.
  • <activity>, <service>, <receiver>, and 中可利用 android:process 屬性來指定其 component 要跑在那個 process 上。
  • <application> 也能利用 android:process 去設定所有 components 的預設值。
  • By default, all components of the same application run in the same process and most applications should not change this.
* Process Types
To determine which processes to keep and which to kill, the system places each process into an "importance hierarchy" based on the components running in the process and the state of those components.
  1. Foreground process: user 正在執行中的 process。ex:
    • User 正在使用的 activity (activity is onResume())。
    • User 正在使用的 activity 所使用的 service
    • The Service has called startForeground().
    • A Service that's executing one of its lifecycle callbacks (onCreate(), onStart(), or onDestroy()).
    • A BroadcastReceiver that's executing its onReceive() method.
  2. Visible process: A process that doesn't have any foreground components, but still can affect what the user sees on screen. ex:
    • An Activity that is not in the foreground, but is still visible to the user (its onPause() method has been called). This might occur, for example, if the foreground activity started a dialog, which allows the previous activity to be seen behind it.
    • A Service that's bound to a visible (or foreground) activity.
  3. Service process: A process that is running a service that has been started with the startService() method and does not fall into either of the two higher categories.
  4. Background process: A process holding an activity that's not currently visible to the user (the activity's onStop() method has been called). These processes have no direct impact on the user experience.
    • Usually there are many background processes running, so they are kept in an LRU (least recently used) list to ensure that the process with the activity that was most recently seen by the user is the last to be killed. 
    • If an activity implements its lifecycle methods correctly, and saves its current state, killing its process will not have a visible effect on the user experience, because when the user navigates back to the activity, the activity restores all of its visible state.
  5. Empty process: A process that doesn't hold any active application components. The only reason to keep this kind of process alive is for caching purposes, to improve startup time the next time a component needs to run in it.
    • A process running a service is ranked higher than a process with background activities.


[Thread]


* Main/UI Thread
  • When an application is launched, the system creates a thread of execution for the application, called "main."
  • It is in charge of dispatching events to the appropriate user interface widgets, including drawing events.
  • The thread in which your application interacts with components from the Android UI toolkit (components from the android.widget and android.view packages).
  • By default, the system does not create a separate thread for each instance of a component. All components that run in the same process are instantiated in the UI thread, and system calls to each component are dispatched from that thread.
  • If the UI thread is blocked for more than a few seconds (about 5 seconds currently) the user is presented with the infamous "application not responding" (ANR) dialog.
  • Is not thread-safe.


* Worker/Background Thread
  • If you have operations to perform that are not instantaneous, you should make sure to do them in separate threads ("background" or "worker" threads).
  • Do not access the Android UI toolkit from outside the UI thread.
  • Android offers several ways to access the UI thread from other threads. ex:
// about Thread
new Thread(new Runnable() {
    Activity.runOnUiThread(Runnable)
}
View.post(Runnable)
View.postDelayed(Runnable, long)

// http://developer.android.com/reference/android/os/AsyncTask.html
public abstract class AsyncTask

// http://developer.android.com/reference/android/os/Handler.html
public class Handler

Using example:
new Thread(new Runnable() {
        public void run() {
            final Bitmap bitmap = loadImageFromNetwork("http://example.com/image.png");
            mImageView.post(new Runnable() {
                public void run() {
                    mImageView.setImageBitmap(bitmap);
                }
            });
        }
    }).start();


* AsyncTask
You can then run the task by calling execute() from the UI thread.
public void onClick(View v) {
    new DownloadImageTask().execute("http://example.com/image.png");
}

private class DownloadImageTask extends AsyncTask<String, Void, Bitmap> {
    /** The system calls this to perform work in a worker thread and
      * delivers it the parameters given to AsyncTask.execute() */
    protected Bitmap doInBackground(String... urls) {
        return loadImageFromNetwork(urls[0]);
    }
    
    /** The system calls this to perform work in the UI thread and delivers
      * the result from doInBackground() */
    protected void onPostExecute(Bitmap result) {
        mImageView.setImageBitmap(result);
    }
}


  • The method doInBackground() executes automatically on a worker thread.
  • onPreExecute(), onPostExecute(), and onProgressUpdate() are all invoked on the UI thread
  • You can call publishProgress() at anytime in doInBackground() to execute onProgressUpdate() on the UI thread.


* Another problem you might encounter when using a worker thread is unexpected restarts in your activity due to a runtime configuration change (such as when the user changes the screen orientation), which may destroy your worker thread.


[Thread-safe methods]

* Service
  • When a call on a method implemented in an IBinder originates in the same process in which the IBinder is running, the method is executed in the caller's thread.
  • Because a service can have more than one client, more than one pool thread can engage the same IBinder method at the same time. IBinder methods must, therefore, be implemented to be thread-safe.


* Content Provider
  • A content provider can receive data requests that originate in other processes.
  • Although the ContentResolver and ContentProvider classes hide the details of how the interprocess communication is managed, ContentProvider methods that respond to those requests—the methods query(), insert(), delete(), update(), and getType()—are called from a pool of threads in the content provider's process, not the UI thread for the process. Because these methods might be called from any number of threads at the same time, they too must be implemented to be thread-safe.

* These are the another issue need be explored.


* Reference
- Processes and Threads | Android Developers

2011年9月5日 星期一

[Lifecycle] Activity Lifecycle


應用程式中所使用的 activity 會被堆疊在 stack 中 (task?)。

畫面上的呈現與 activity 狀態對應如下:
  • running <-> visible and get focus
    • 正在運行的 activity 便是 stack 最上面的那個 activity,會顯示在畫面上的。
  • onPause <-> visible but lost focus
    • 在畫面上仍是可見的,但已失去焦點。
    • ex: 最上的 activity 畫面獲得焦點且是可看見背景的,那麼原本的 activity ,即使是 onPause 也仍存活著,保持自己的狀態與訊息,仍然與 window manager 保持連接,但有可能會被系統殺掉。
  • onStop <-> non-visible and lost focus
    • 在畫面上已被其他 activity 完全擋住兒而不可見的,仍保有自己的狀態與資訊,但 window manager 已不再管理其訊息,系統資源不夠時會被殺掉。


當 activity is onPause or onStop,系統則可以清楚它,可能提示 user 是否結束或只是殺掉其 process。




* 當Progress Dialog啟動時Activity模糊化(blur)進入OnPause()狀態, 並以執行緒(Thread)模擬事件進度.



* Reference
- Android activity 堆栈(1) - 嘴嘴的小的日志 - 网易博客
- tsots的Android範例Source: ProgressDialog~ProgressBar~搭配Handler顯示執行進度