每當應用程式在背景執行時,都會耗用裝置的部分有限資源,例如 RAM。這可能會導致使用者體驗不佳,尤其在使用者使用的應用程式會耗用大量資源時 (例如玩遊戲或觀看影片)。為了改善使用者體驗,Android 8.0 (API 級別 26) 針對應用程式在背景執行時可執行的作業設下限制。本文件將說明作業系統的相關變更,以及如何更新應用程式,以便在新的限制下順利運作。
總覽
許多 Android 應用程式和服務可以同時執行。舉例來說,使用者可能會在另一個視窗中瀏覽網頁時,在某個視窗中玩遊戲,以及使用第三方應用程式播放音樂。同時執行的應用程式越多,系統上的負載就越多。如果其他應用程式或服務在背景執行,系統就會增加額外的負載,進而對使用者體驗造成負面影響,例如音樂應用程式可能會突然關閉。
為了降低這些問題發生的機率,Android 8.0 針對應用程式可在使用者未直接與應用程式互動時可執行的操作設下限制。應用程式受到以下兩種限制:
背景服務限制:當應用程式處於閒置狀態時,背景服務對其使用設有限制。這不適用於前景服務,因為這類服務對使用者而言更明顯。
廣播限制:在少數例外狀況下,應用程式無法使用其資訊清單註冊隱式廣播。他們仍然可以在執行階段註冊這些廣播訊息,並且可以使用資訊清單註冊為應用程式專屬的明確廣播和廣播訊息。
在大多數情況下,應用程式可以使用 JobScheduler
工作解決這些限制。這個方法可讓應用程式排列在應用程式未主動執行時執行工作,但仍可讓系統能以不影響使用者體驗的方式安排這些工作。Android 8.0 針對 JobScheduler
提供了多項改善,方便您以排程工作取代服務和廣播接收器。詳情請參閱 JobScheduler 改善項目。
背景服務限制
在背景執行的服務可能會耗用裝置資源,進而對使用者體驗造成負面影響。為緩解這個問題,系統會對服務套用幾項限制。
系統會區分「前景」和「背景」應用程式。(就服務限制用途的定義與記憶體管理的定義不同;應用程式可能因為記憶體管理而在背景執行,但是在前景運作而取決於其啟動服務能力。)如果應用程式符合下列任一條件,即視為在前景執行:
- 無論活動已開始或暫停,都有可見的活動。
- 具有前景服務。
- 另一個前景應用程式透過繫結至其中一項服務,或使用其中一個內容供應器,與該應用程式連結。舉例來說,如果另一個應用程式繫結至前景,應用程式就會在前景運作:
- 輸入法編輯器
- 桌布服務
- 通知接聽器
- 語音或簡訊服務
如果這些條件都不存在,系統會將應用程式視為在背景執行。
應用程式在前景運作時,可以自由建立及執行前景和背景服務。應用程式進入背景時,具有數分鐘的視窗仍允許建立及使用服務。視窗結束時,應用程式即視為「閒置」。此時,系統會停止應用程式的背景服務,就像應用程式曾呼叫服務的 Service.stopSelf()
方法一樣。
在某些情況下,背景應用程式會列入臨時許可清單中數分鐘。應用程式列入許可清單時,可以不受限制地啟動服務,而且其背景服務可以執行。如果應用程式會處理向使用者顯示的工作,例如:
- 處理高優先順序的 Firebase 雲端通訊 (FCM) 訊息。
- 接收廣播,例如簡訊/多媒體訊息。
- 從通知執行
PendingIntent
。 - 在 VPN 應用程式升級至前景之前啟動
VpnService
。
在許多情況下,應用程式可以將背景服務替換為 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()
(而非在資訊清單中宣告接收器) 的方式,在執行階段建立接收器。 - 請使用已排定的工作來檢查會觸發隱式廣播的條件。