排查前台服务问题

本页讨论了前台服务可能会失败的一些常见原因,并帮助您确定导致问题的原因。

本文档讨论了以下问题:

排查问题之前的准备工作

检查前台服务近期是否发生了变更

如果前台服务使用不当,可能会对设备性能和电池续航时间产生负面影响。因此,Android 平台版本通常会对前台服务行为进行更改,以限制这些不良影响。

如果您在使用前台服务时遇到问题,应查看前台服务变更文档,看看是否有任何最近的变更可以解释您的问题。在以下情况下,请务必检查是否有更改:

  • 之前可正常运行的前台服务代码现在无法运行
  • 您刚刚开始在新平台版本上进行测试,或者您更改了应用的目标 API 级别

此外,如果您在平台开发者预览版上测试设备,请务必查看最新的开发者预览版文档

应用无响应 (ANR) 错误

在某些情况下,应用应关闭其前台服务。如果应用未停止该服务,系统会停止该服务并触发应用无响应 (ANR) 错误。

短期服务运行时间过长,导致 ANR

使用 shortService 类型的前台服务必须在短时间内(大约三分钟内)完成。当时间耗尽时,系统会调用服务的 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

修复方法

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