排解前景服務問題

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

本文將探討下列問題:

疑難排解前的準備

查看前景服務近期異動

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

如果前景服務發生問題,請參閱前景服務異動說明文件,看看最近是否有任何異動可能導致問題。在下列情況下,請務必檢查是否有變更:

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

此外,如果您是在平台的開發人員預覽版上測試裝置,請務必查看最新版本的開發人員預覽版說明文件。

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

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

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

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

診斷:

如果 ANR 是因前景服務無法自行停止而造成,系統會擲回內部例外狀況。您可以查看 ANR 報告,確認這是否為問題所在。如果問題確實如此,報表會顯示下列訊息:

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()。如果服務未自行停止,系統會產生內部 RemoteServiceException,導致應用程式停止運作。

診斷:

您可以查看堆疊追蹤,瞭解例外狀況為何,並查看 Logcat,取得更詳細的錯誤資訊。在這種情況下,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(),將自身升級為前景服務。如果服務未執行這項操作,則會擲回內部 ForegroundServiceDidNotStartInTimeException。

診斷:

您可以查看堆疊追蹤,瞭解例外狀況為何,並查看 Logcat,取得更詳細的錯誤資訊。在這種情況下,Logcat 會顯示下列錯誤訊息:

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

修正方法:

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

WorkManager:

如果 WorkManager worker 執行前景服務 (呼叫 setForegound 或 setForegroundAsync),您也可能會看到這個例外狀況。當兩個前景 worker 的生命週期重疊,其中一個 worker 嘗試啟動前景服務,而先前執行的前景服務嘗試關閉時,這個當機問題會伴隨下列記錄:

Re-initializing SystemForegroundService after a request to shut-down

WorkManager 2.10.5 版已修正這個當機問題。

如果應用程式遇到這個例外狀況,請更新至最新版本的 WorkManager,並將任何持續發生的問題回報至 WorkManager Issue Tracker。

ForegroundServiceStartNotAllowedException

錯誤:

系統擲回 ForegroundServiceStartNotAllowedException。

原因:

這通常是因為應用程式在沒有有效豁免權的情況下,從背景啟動前景服務。

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

舉例來說,應用程式可能會有一個按鈕,使用者點選後,應用程式會執行一些處理作業,然後啟動前景服務。在這種情況下,使用者可能會點選按鈕,然後立即將應用程式放在背景中。接著,應用程式會嘗試從背景啟動服務。如果應用程式不符合任何指定的豁免條件,系統會擲回 ForegroundServiceStartNotAllowedException。

此外,部分豁免條件有短暫的時間限制。舉例來說,如果應用程式啟動前景服務,以回應高優先順序的 FCM 訊息,則可獲得短暫豁免。如果未及時啟動服務,就會發生 ForegroundServiceStartNotAllowedException。

隨著 Android 新版本推出,特定豁免條件有時會變得更嚴格。如果您變更了應用程式指定的 Android 版本,請參閱前景服務異動說明文件,確認應用程式仍符合其中一項豁免條件。

修正方法:

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

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

SecurityException

錯誤:

系統會擲回 SecurityException。

原因:

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

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

修正方法:

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