排解前景服務問題

本頁將說明前景服務失敗的常見原因,並協助您找出問題原因。

本文將討論以下問題:

疑難排解前的準備

查看前景服務的近期異動

如果前景服務使用方式不當,可能會對裝置效能和電池續航力造成負面影響。因此,Android 平台版本經常會變更前景服務行為,以限制這些負面影響。

如果您在使用前景服務時遇到問題,請查看前景服務異動說明文件,看看是否有任何近期異動可解釋您的問題。在下列情況下,請務必檢查是否有變更:

  • 先前可正常運作的前景服務程式碼現在無法運作
  • 您剛開始在新的平台版本上進行測試,或是已變更應用程式指定的 API 級別

此外,如果您要使用平台的開發人員預覽版測試裝置,請務必查看最新版開發人員預覽版說明文件

應用程式無回應 (ANR) 錯誤

在某些情況下,應用程式應會關閉前景服務。如果應用程式未停止服務,系統會停止服務並觸發「應用程式無回應」(ANR) 錯誤。

短程服務執行時間過長,導致 ANR

使用短服務類型的前景服務必須在約三分鐘內完成。時間到期後,系統會呼叫服務的 Service.onTimeout(int,int) 方法。服務有幾秒的時間可以呼叫 stopSelf()。如果服務未自行停止,系統會觸發「應用程式無回應」錯誤。

診斷

如果 ANR 是因為前景服務無法自行停止而發生,系統會擲回內部例外狀況。您可以查看 Logcat 確認是否為此問題。在這種情況下,記錄會包含以下訊息:

Fatal Exception: android.app.RemoteServiceException: "A foreground service of
type FOREGROUND_SERVICE_TYPE_SHORT_SERVICE did not stop within its timeout:
[component name]"

修正方法

請確認所有限時前景服務都能在系統時間限制內完成工作並呼叫 stopForeground(int)

讓前景服務實作 Service.onTimeout(int,int)。請確認您對該方法的實作會立即呼叫 stopSelf()

前景服務例外狀況

本節將說明幾個可能導致系統擲回例外狀況的前景服務問題。如果應用程式未擷取例外狀況,使用者會看到對話方塊,說明應用程式已停止運作。

在某些情況下,系統會擲回內部例外狀況。您無法擷取這些例外狀況,但可以查看 Logcat,瞭解系統擲回了哪些例外狀況。

內部例外狀況:逾時

系統會限制資料同步和媒體處理前景服務在應用程式處於背景執行時的執行時間。如果服務超過該限制,系統會呼叫服務的 Service.onTimeout(int,int) 方法。服務有幾秒的時間可以呼叫 stopSelf()。如果服務未自行停止,系統會產生內部例外狀況,導致應用程式當機。

診斷

如果超時是原因,Logcat 會包含以下訊息:

Fatal Exception: android.app.RemoteServiceException: "A foreground service of
type [service type] did not stop within its timeout: [component name]"

修正方法

請確認所有限時前景服務都能在系統時間限制內完成工作並呼叫 stopForeground(int)

讓前景服務實作 Service.onTimeout(int,int)。請務必立即呼叫該方法的實作 stopSelf()

內部例外狀況:ForegroundServiceDidNotStartInTimeException

當您透過呼叫 context.startForegroundService() 啟動服務時,該服務會在幾秒內呼叫 ServiceCompat.startForeground(),將自己提升為前景服務。如果服務未執行這項操作,系統會觸發 ANR 錯誤。

診斷

如果前景服務未及時啟動,應用程式就會當機,導致使用者看到「App has stopped」對話方塊。在這種情況下,您可以在 Logcat 中找到以下訊息:

android.app.RemoteServiceException$ForegroundServiceDidNotStartInTimeException:
Context.startForegroundService() did not then call Service.startForeground()

修正方法

請確認所有新建立的前景服務都能在幾秒內呼叫 ServiceCompat.startForeground()

ForegroundServiceStartNotAllowedException

錯誤

系統會擲回 ForegroundServiceStartNotAllowedException

原因

這通常是因為應用程式在沒有有效的例外狀況時,從背景啟動前景服務所造成。

自 Android 12 (API 級別 31) 起,應用程式在背景執行時不得啟動前景服務,但有少數例外情況。如果您嘗試從背景啟動前景服務,但不符合其中一個豁免條件的規定,系統會擲回 ForegroundServiceStartNotAllowedException。如果您不符合豁免條件,系統也會採取這項行動。

舉例來說,應用程式可能會提供使用者可點選的按鈕,導致應用程式執行一些處理作業,然後啟動前景服務。在這種情況下,使用者可能會按下按鈕,然後立即將應用程式置於背景,這會造成危險。在這種情況下,應用程式會嘗試從背景啟動服務。如果應用程式不符合其中一個指定的豁免條件,系統會擲回 ForegroundServiceStartNotAllowedException

此外,部分豁免條款的有效期限很短。舉例來說,如果應用程式為了回應高優先順序的 FCM 訊息而啟動前景服務,就會暫時豁免。如果您未以足夠的速度啟動服務,就會發生 ForegroundServiceStartNotAllowedException

特定豁免條款有時會隨著新版 Android 版本變得更加嚴格。如果您變更了應用程式指定的 Android 版本,請查看前景服務變更說明文件,並確認您的應用程式仍符合其中一個允許的豁免條件。

修正方法

變更應用程式的工作流程,讓應用程式在背景執行時不必啟動前景服務,或是確認應用程式符合其中一個豁免條件。

您可以使用 LiveData 等生命週期元件來管理應用程式的生命週期,避免不小心從背景啟動前景服務。

SecurityException

錯誤

系統會擲回 SecurityException

原因

您的應用程式嘗試啟動前景服務,但未取得必要的權限。

  • 如果應用程式指定 Android 9 (API 級別 28) 以上版本,則必須具備 FOREGROUND_SERVICE 權限才能啟動前景服務。
  • 如果應用程式指定 Android 14 (API 級別 34) 以上版本,則必須符合前景服務類型的所有先決條件。如需這些先決條件的詳細說明,請參閱前景服務類型說明文件。請特別留意下列規定:
    • 部分前景服務類型需要特定的執行階段權限。舉例來說,遠端訊息前景服務必須具備 FOREGROUND_SERVICE_REMOTE_MESSAGING 權限。
  • 在某些情況下,部分前景服務類型需要的權限,會受到額外的使用中限制。這些權限只會在應用程式處於前景時授予應用程式 (但有幾個例外情況)。也就是說,即使應用程式已要求並獲得其中一個權限,如果應用程式在背景執行時嘗試啟動前景服務,即使應用程式有從背景啟動前景服務的豁免權,系統仍會擲回 SecurityException。詳情請參閱「啟動需要使用中權限的前景服務的限制」。
    • 如果您要求必要權限,但在確認已授予必要權限前啟動前景服務,可能會收到 SecurityException

修正方法

啟動前景服務前,請要求所有適當的前景服務權限,並確認您已符合所有其他的執行階段先決條件。