天天看點

關于在 Service 或 BroadcastReceiver 中 startActivity 的問題

1. 不從背景啟動 Activity 準則:

在谷歌的 Android API Guides 中,特意提醒開發者不要在背景啟動 activity,包括在 Service 和 BroadcastReceiver 中,這樣的設計是為了避免在使用者毫不知情的情況下突然中斷使用者正在進行的工作,在   http://developer.android.com/guide/practices/seamlessness.html#interrupt  中有如下解釋:

That is, don't call startActivity() from BroadcastReceivers or Services running in the background. Doing so will interrupt whatever application is currently running, and result in an annoyed user. Perhaps even worse, your Activity may become a "keystroke bandit" and receive some of the input the user was in the middle of providing to the previous Activity. Depending on what your application does, this could be bad news.

2. 需要違反“不從背景啟動 Activity”準則的特例:

特例:即便如此,手機廠商的開發者們在開發基于系統級的應用的時候,可能仍然需要有從 Service 或 BroadcastReceiver 中 startActivity 的需求,往往這樣的前提是連這樣的 Service 或 BroadcastReceiver 也是由使用者的某些操作而觸發的,Service 或 BroadcastReceiver 隻是充當了即将啟動 activity 之前的一些代理參數檢查工作以便決定是否需要 start 該 activity。

除非是上述筆者所述的特殊情況,應用開發者都應該遵循 “ 不要從背景啟動 Activity”準則。

一個需要特别注意的問題是,特例中所述的情況還會遇到一個問題,就是當通過 home 鍵将目前 activity 置于背景時,任何在背景startActivity 的操作都将會延遲 5 秒,除非該應用擷取了 "android.permission.STOP_APP_SWITCHES" 權限。

關于延遲 5 秒的操作在 com.android.server.am.ActivityManagerService 中的 stopAppSwitches() 方法中,系統級的應用當擷取了 "android.permission.STOP_APP_SWITCHES" 後将不會調用到這個方法來延遲通過背景啟動 activity 的操作,事實上 android 原生的 Phone 應用就是這樣的情況,它是一個擷取了"android.permission.STOP_APP_SWITCHES" 權限的系統級應用,當有來電時,一個從背景啟動的 activity 将突然出現在使用者的面前,警醒使用者有新的來電,這樣的設計是合理的。 

是以,當你需要開發類似 Phone 這樣的應用時,需要做如下工作:

  1. root 你的手機;
  2. 在 AndroidManifest.xml 中添加 "android.permission.STOP_APP_SWITCHES"  使用者權限;
  3. 将你開發的應用程式 push 到手機的 /system/app 目錄中。

3.參考資料:

  1. 無縫的設計之——不要中斷你的使用者: http://developer.android.com/guide/practices/seamlessness.html#interrupt
  2. stackoverflow 中關于背景 startActivity 被延遲 5 秒的探讨: http://stackoverflow.com/questions/5600084/starting-an-activity-from-a-service-after-home-button-pressed-without-the-5-seco