簡體   English   中英

在 Android 12 (SDK 31) 中獲取 android.app.ForegroundServiceStartNotAllowedException

[英]Getting android.app.ForegroundServiceStartNotAllowedException in Android 12 (SDK 31)

我將我的應用程序targetSdkVersioncompileSdkVersion升級到 SDK 31,並開始在后台更新小部件的服務中收到以下應用程序崩潰。

java.lang.RuntimeException: 
  at android.app.ActivityThread.handleReceiver (ActivityThread.java:4321)
  at android.app.ActivityThread.access$1600 (ActivityThread.java:247)
  at android.app.ActivityThread$H.handleMessage (ActivityThread.java:2068)
  at android.os.Handler.dispatchMessage (Handler.java:106)
  at android.os.Looper.loopOnce (Looper.java:201)
  at android.os.Looper.loop (Looper.java:288)
  at android.app.ActivityThread.main (ActivityThread.java:7842)
  at java.lang.reflect.Method.invoke (Native Method)
  at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:548)
  at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:1003)
Caused by: android.app.ForegroundServiceStartNotAllowedException: 
  at android.app.ForegroundServiceStartNotAllowedException$1.createFromParcel (ForegroundServiceStartNotAllowedException.java:54)
  at android.app.ForegroundServiceStartNotAllowedException$1.createFromParcel (ForegroundServiceStartNotAllowedException.java:50)
  at android.os.Parcel.readParcelable (Parcel.java:3333)
  at android.os.Parcel.createExceptionOrNull (Parcel.java:2420)
  at android.os.Parcel.createException (Parcel.java:2409)
  at android.os.Parcel.readException (Parcel.java:2392)
  at android.os.Parcel.readException (Parcel.java:2334)
  at android.app.IActivityManager$Stub$Proxy.startService (IActivityManager.java:5971)
  at android.app.ContextImpl.startServiceCommon (ContextImpl.java:1847)
  at android.app.ContextImpl.startForegroundService (ContextImpl.java:1823)
  at android.content.ContextWrapper.startForegroundService (ContextWrapper.java:779)
  at android.content.ContextWrapper.startForegroundService (ContextWrapper.java:779)
  at com.mypackage.appname.ui.widget.widget_package.WidgetClassName.onUpdate (WidgetClassName.java:48)
  at android.appwidget.AppWidgetProvider.onReceive (AppWidgetProvider.java:66)
  at com.mypackage.appname.ui.widget.widget_package.WidgetClassName.onReceive (WidgetClassName.java)
  at android.app.ActivityThread.handleReceiver (ActivityThread.java:4312)
  at android.app.ActivityThread.access$1600 (ActivityThread.java:247)
  at android.app.ActivityThread$H.handleMessage (ActivityThread.java:2068)
  at android.os.Handler.dispatchMessage (Handler.java:106)
  at android.os.Looper.loopOnce (Looper.java:201)
  at android.os.Looper.loop (Looper.java:288)
  at android.app.ActivityThread.main (ActivityThread.java:7842)
  at java.lang.reflect.Method.invoke (Native Method)
  at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:548)
  at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:1003)
Caused by: android.os.RemoteException: 
  at com.android.server.am.ActiveServices.startServiceLocked (ActiveServices.java:691)
  at com.android.server.am.ActiveServices.startServiceLocked (ActiveServices.java:616)
  at com.android.server.am.ActivityManagerService.startService (ActivityManagerService.java:11839)
  at android.app.IActivityManager$Stub.onTransact (IActivityManager.java:2519)
  at com.android.server.am.ActivityManagerService.onTransact (ActivityManagerService.java:2498)

此外,如果您使用的是 Firebase Crashlytics,您的堆棧跟蹤必須是這樣的 ->

Caused by android.app.ForegroundServiceStartNotAllowedException: startForegroundService() not allowed due to mAllowStartForeground false: service com.mypackage.appname/.ui.widget.widget_package.MyForegroundServiceName
       at android.app.ForegroundServiceStartNotAllowedException$1.createFromParcel(ForegroundServiceStartNotAllowedException.java:54)
       at android.app.ForegroundServiceStartNotAllowedException$1.createFromParcel(ForegroundServiceStartNotAllowedException.java:50)
       at android.os.Parcel.readParcelable(Parcel.java:3333)
       at android.os.Parcel.createExceptionOrNull(Parcel.java:2420)
       at android.os.Parcel.createException(Parcel.java:2409)
       at android.os.Parcel.readException(Parcel.java:2392)
       at android.os.Parcel.readException(Parcel.java:2334)
       at android.app.IActivityManager$Stub$Proxy.startService(IActivityManager.java:5971)
       at android.app.ContextImpl.startServiceCommon(ContextImpl.java:1847)
       at android.app.ContextImpl.startForegroundService(ContextImpl.java:1823)
       at android.content.ContextWrapper.startForegroundService(ContextWrapper.java:779)
       at android.content.ContextWrapper.startForegroundService(ContextWrapper.java:779)
       at com.mypackage.appname.ui.widget.widget_package.WidgetClassName.onUpdate(WidgetClassName.java:48)
       at android.appwidget.AppWidgetProvider.onReceive(AppWidgetProvider.java:66)
       at com.mypackage.appname.ui.widget.widget_package.WidgetClassName.onReceive(WidgetClassName.java)
       at android.app.ActivityThread.handleReceiver(ActivityThread.java:4312)
       at android.app.ActivityThread.access$1600(ActivityThread.java:247)
       at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2068)
       at android.os.Handler.dispatchMessage(Handler.java:106)
       at android.os.Looper.loopOnce(Looper.java:201)
       at android.os.Looper.loop(Looper.java:288)
       at android.app.ActivityThread.main(ActivityThread.java:7842)
       at java.lang.reflect.Method.invoke(Method.java)
       at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003)

我正在添加重現此問題的方法,並修復此問題,因為當我搜索它時,我沒有在 StackOverflow 上找到任何關於此的文檔。

如何重現崩潰

步驟 1. 將您的targetSdkVersioncompileSdkVersion更新為 SDK 31。

第 2 步。嘗試在您的應用程序處於后台時運行任何前台服務。 在我的例子中,它是在updatePeriodMillis時間之后updatePeriodMillis小部件的onUpdate方法,它將啟動一個前台服務,該服務通過從互聯網獲取適當的信息來更新數據。

請記住:Android 8.0 中添加的后台執行限制與此問題無關。 此限制/例外是在 Android 12/SDK 31 - Source 中添加的


這是什么異常,為什么要添加它?

除少數特殊情況外,面向 Android 12(API 級別 31)或更高版本的應用無法在后台運行時啟動前台服務。 如果應用程序在后台運行時嘗試啟動前台服務,並且前台服務不滿足其中一種異常情況,則系統會拋出ForegroundServiceStartNotAllowedException

這些特殊情況是:

  • 您的應用程序從用戶可見的狀態(例如活動)轉換。

  • 您的應用程序可以從后台啟動 Activity,除非應用程序在現有任務的后台堆棧中有一個 Activity。

  • 您的應用使用 Firebase 雲消息傳遞接收高優先級消息。

  • 用戶對與您的應用相關的 UI 元素執行操作。 例如,他們可能會與氣泡、通知、小部件或活動進行交互。

  • 您的應用會調用准確的警報來完成用戶請求的操作。

  • 您的應用是設備當前的輸入法。

  • 您的應用收到與地理圍欄或活動識別轉換相關的事件。

  • 在設備重新啟動並在廣播接收器中接收 ACTION_BOOT_COMPLETED、ACTION_LOCKED_BOOT_COMPLETED 或 ACTION_MY_PACKAGE_REPLACED 意圖操作后。

  • 您的應用在廣播接收器中接收 ACTION_TIMEZONE_CHANGED、ACTION_TIME_CHANGED 或 ACTION_LOCALE_CHANGED 意圖操作。

  • 您的應用收到需要 BLUETOOTH_CONNECT 或 BLUETOOTH_SCAN 權限的藍牙廣播。

  • 具有特定系統角色或權限的應用程序,例如設備所有者和配置文件所有者。

  • 您的應用使用配套設備管理器並聲明 REQUEST_COMPANION_START_FOREGROUND_SERVICES_FROM_BACKGROUND 權限或 REQUEST_COMPANION_RUN_IN_BACKGROUND 權限。 盡可能使用 REQUEST_COMPANION_START_FOREGROUND_SERVICES_FROM_BACKGROUND。

  • 用戶為您的應用關閉電池優化。 您可以通過將用戶發送到系統設置中應用的應用信息頁面來幫助用戶找到此選項。 為此,請調用包含 ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS 意圖操作的意圖。


可能的解決方案

解決方案1

這將在 Play 商店中工作一段時間,直到 Google 強制升級到 API 級別 31。

目前,從 2021 年 11 月開始,所有應用程序都必須面向 API 級別 30 及更高級別。 因此,如果您的應用程序使用 API 級別 31,將compileSdkVersiontargetSdkVersion降級到 API 級別 30 應該可以解決問題(至少targetSdkVersion )。

解決方案2

對於時間敏感的工作

如果您使用 Foreground 服務執行時間敏感的工作,請在准確的警報內啟動 Foreground 服務。 從此處的文檔中查看有關此內容的更多信息 -> 設置精確警報

對於時間不敏感/加急的工作

這是我最終用於我的應用程序的解決方案。 使用WorkManager調度和啟動后台工作。 從此處的文檔中查看有關此內容的更多信息 -> 安排加急工作

您可以在此處了解有關 WorkManager 的更多信息 -> WorkManager

適用於 WorkManager 示例的 Github Repo -> WorkManager 示例

我特別添加了這個答案,因為搜索此異常不會提供任何資源來了解為什么該服務在 Android 12 上的行為不同。所有這些都存在於 Google 的文檔中,並且始終記得檢查文檔中的行為更改。

與此更改相關的所有內容都可以在此處找到 -> Android 12 行為更改,特別是在前台服務啟動限制內

如果您的 App 是 MediaPlayer(即使用MediaBrowseService )並且您遇到ForegroundServiceStartNotAllowedException崩潰,那么您可能需要:

  1. 使用android:foregroundServiceType="mediaPlayback"Service聲明中更新您的清單以指定您的服務用於媒體播放

  2. 在調用Serivce.startForeground方法時包含ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK參數

在創建通知時使用.setForegroundServiceBehavior(NotificationCompat.FOREGROUND_SERVICE_IMMEDIATE)以及NotificationManager.IMPORTANCE_MAX

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM