前台服务问题排查

本页面讨论了前台服务可能失败的一些常见原因,并帮助您识别问题根源。

本文档讨论以下问题:

问题排查前

检查前台服务的近期变更

如果前台服务使用不当,可能会对设备性能和电池续航产生负面影响。因此,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

修复:

在启动前台服务之前,请求所有适当的前台服务权限,并确认您已满足所有其他运行时先决条件。