背景執行限制

每當應用程式在背景執行時,都會耗用裝置的部分有限資源,例如 RAM。這可能會導致使用者體驗不佳,特別是在使用者使用會耗用大量資源的應用程式時,例如玩遊戲或觀看影片。為改善使用者體驗,Android 8.0 (API 級別 26) 對應用程式在背景執行時可執行的操作設下限制。本文件說明作業系統的變更,以及如何更新應用程式,以便在新限制下順利運作。

總覽

許多 Android 應用程式和服務可以同時執行。舉例來說,使用者可能會在一個視窗中玩遊戲,同時在另一個視窗瀏覽網路,以及使用第三個應用程式播放音樂。同時執行的應用程式越多,系統的負載就越重。如果其他應用程式或服務在背景執行,這會在系統中增加額外載入作業,這可能導致使用者體驗不佳,例如音樂應用程式可能會突然關閉。

為了降低這類問題發生的機率,Android 8.0 會對應用程式在使用者未直接與應用程式互動時可執行的作業設下限制。應用程式有以下兩種限制:

  • 背景服務限制:應用程式處於閒置狀態時,使用背景服務會受到相關限制。這不適用於使用者更容易注意到的前景服務。

  • 廣播限制:在少數例外狀況下,應用程式無法使用其資訊清單註冊隱式廣播。他們仍可在執行階段註冊這些廣播訊息,並且利用資訊清單註冊為應用程式專屬的明確廣播和廣播訊息。

在大多數情況下,應用程式可以使用 JobScheduler 工作來避免這些限制。這個方法可讓應用程式安排在應用程式未主動執行時執行工作,同時讓系統能繼續以不影響使用者體驗的方式排定工作時程。Android 8.0 針對 JobScheduler 提供了多項改善功能,方便您使用已排定的工作取代服務和廣播接收器。詳情請參閱 JobScheduler 改善項目

背景服務限制

在背景中執行的服務可能會耗用裝置資源,可能導致使用者體驗不佳。為減緩此問題,系統會對服務套用一些限制。

系統會區分「前景」和「背景」應用程式。(用於服務限制的背景定義與記憶體管理使用的定義不同:應用程式可能在背景執行與記憶體管理相關,但取決於其啟動服務的能力)。如果應用程式符合下列任一條件,即視為位於前景:

  • 無論該活動已開始或暫停,都有可見活動。
  • 該應用程式提供前景服務。
  • 另一個前景應用程式會透過繫結至其中一項服務,或使用其其中一個內容供應器,連結至應用程式。舉例來說,如果另一個應用程式繫結至前景,則應用程式位於前景:

如果這些條件都不成立,應用程式會視為位於背景。

當應用程式在前景運作時,即可自由建立並執行前景和背景服務。當應用程式進入背景時,會有幾分鐘的時間允許建立及使用服務。該視窗結束時,系統會將應用程式視為「閒置」。此時,系統會比照應用程式呼叫 Service.stopSelf() 方法一樣,停止應用程式的背景服務。

在某些情況下,背景應用程式會暫時列入暫時許可清單,應用程式在許可清單中時,可以不受限制地啟動服務,並允許執行背景服務。應用程式處理使用者可見的工作時,就會加入許可清單:

在許多情況下,應用程式可將背景服務替換為 JobScheduler 工作。舉例來說,CoolPhotoApp 必須檢查使用者是否已收到來自好友的共享相片,即使應用程式並未在前景執行也一樣。先前,應用程式使用的背景服務會檢查應用程式的雲端儲存空間。遷移至 Android 8.0 (API 級別 26) 時,開發人員會將背景服務替換成排程工作 (定期啟動),查詢伺服器,然後退出。

在 Android 8.0 之前,建立前景服務的常見做法是建立背景服務,然後在前景執行該服務。在 Android 8.0 中,有一個小工具;系統不允許背景應用程式建立背景服務。因此,Android 8.0 推出了新方法 startForegroundService(),以便在前景啟動新服務。系統建立服務後,應用程式有五秒可以呼叫服務的 [startForeground()](/reference/android/app/Service#startForeground(int, android.app.Notification) 方法,以便顯示新服務的使用者可見通知。如果應用程式「未」在時限內呼叫 startForeground(),系統就會停止服務,並宣告應用程式為 ANR

廣播限制

如果應用程式藉由註冊接收廣播,應用程式的接收器會在每次傳送廣播時耗用資源。如果註冊的應用程式過多,要接收基於系統事件的廣播訊息,則這可能會造成問題;觸發廣播的系統事件可能會導致所有應用程式快速連續消耗資源,進而影響使用者體驗。為減少這個問題,Android 7.0 (API 級別 24) 對廣播功能設有限制,如「背景最佳化」一節所述。Android 8.0 (API 級別 26) 則讓這些限制更加嚴格。

  • 指定 Android 8.0 以上版本的應用程式無法再為資訊清單中的隱式廣播註冊接收器,除非廣播訊息限定為應用程式。隱式廣播是指未指定應用程式中特定元件的廣播。舉例來說,系統會將 ACTION_PACKAGE_REPLACED 傳送給所有應用程式中所有已註冊的事件監聽器,讓他們知道裝置上的部分套件已取代。由於廣播是隱含的,因此不會在指定 Android 8.0 以上版本的應用程式中,將廣播訊息傳送給已註冊資訊清單的接收器。ACTION_MY_PACKAGE_REPLACED 也是隱含廣播,但由於應用程式只會傳送至已取代套件的應用程式套件,因此會傳送給已註冊資訊清單的接收器。
  • 應用程式可在資訊清單中繼續註冊明確廣播。
  • 應用程式可在執行階段使用 Context.registerReceiver(),為任何廣播訊息註冊接收器,包括隱含或明確的廣播。
  • 需要簽章權限的廣播則不受此限制,因為這類廣播訊息只會傳送至以相同憑證簽署的應用程式,而不是傳送給裝置上的所有應用程式。

在許多情況下,先前註冊隱式廣播的應用程式可以使用 JobScheduler 工作取得類似的功能。舉例來說,社交相片應用程式可能需要不時對其資料執行清理作業,且偏好在裝置連接充電器時執行此操作。先前,應用程式會在資訊清單中為 ACTION_POWER_CONNECTED 註冊接收器;當應用程式收到該廣播訊息時,就會檢查是否需要清理。如要遷移至 Android 8.0 以上版本,應用程式會從資訊清單移除該接收器。應用程式會改為排定在裝置閒置及充電時執行的清理工作。

遷移指南

根據預設,這些變更只會影響指定 Android 8.0 (API 級別 26) 以上版本的應用程式。不過,即使應用程式指定的 API 級別低於 26,使用者仍可從「設定」畫面為任何應用程式啟用這些限制。您可能需要更新應用程式,以符合新限制。

查看應用程式的服務使用情形。如果應用程式依賴的服務在應用程式處於閒置狀態時在背景執行,您將需要更換服務。可能的解決方案包括:

  • 如果應用程式在背景執行時需要建立前景服務,請使用 startForegroundService() 方法,而非 startService()
  • 如果使用者可注意到服務,請將其設為前景服務。舉例來說,播放音訊的服務應一律是前景服務。使用 startForegroundService() 方法 (而非 startService()) 建立服務。
  • 設法藉由已排定的工作來複製服務功能。如果服務沒有立即對使用者察覺的情況,您通常應能改用排定的工作。
  • 使用 FCM 選擇性地在發生網路事件時喚醒應用程式,而不是在背景輪詢。
  • 應用程式將延遲運作,直到應用程式在前景運作為止。

檢查應用程式資訊清單中定義的廣播接收器。如果資訊清單為受影響的隱式廣播宣告接收器,您必須替換該接收器。可能的解決方案包括:

  • 在執行階段呼叫 Context.registerReceiver() 來建立接收器,而不是在資訊清單中宣告接收器。
  • 使用已排定的工作,檢查會觸發隱式廣播的條件。