排解前景服務問題

本頁面會說明前台服務可能失敗的常見原因,並協助您找出問題所在。

本文將探討下列問題:

疑難排解前的準備

檢查前景服務的近期變更

如果使用方式不當,前景服務可能會對裝置效能和電池續航力造成負面影響。因此,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()

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

修正方法

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