排查前台服务问题

本页介绍了前台服务可能失败的一些常见原因,并可帮助您找出导致问题的原因。

本文档讨论了以下问题:

排查问题之前的准备工作

检查前台服务的近期变更

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

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

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

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

应用无响应 (ANR) 错误

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

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

使用短时服务类型的前台服务必须在约三分钟内快速完成。时间耗尽后,系统会调用服务的 Service.onTimeout(int,int) 方法。服务有几秒钟的时间来调用 stopSelf()。如果服务未自行停止,系统会触发“应用无响应”错误。

诊断

如果 ANR 是由前台服务未能自行停止而导致的,系统会抛出内部异常。您可以通过检查 Logcat 来验证是否存在此问题。在本例中,日志包含以下消息:

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()。如果服务未自行停止,系统会生成内部异常,导致应用崩溃。

诊断

如果超时是原因,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() 将自身提升为前台服务。如果服务未执行此操作,系统会触发 ANR 错误。

诊断

如果前台服务未及时启动,应用将崩溃,导致用户看到应用已停止对话框。在这种情况下,您可以在 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 版本,请参阅前台服务变更文档,并确认您的应用仍符合允许的豁免条件之一。

修复方法

更改应用的工作流程,使其在后台运行时无需启动前台服务,或者确认您的应用符合某项豁免条件。

您可以使用 LiveData 等生命周期组件来管理应用的生命周期,以免无意中尝试从后台启动前台服务。

SecurityException

错误

系统抛出 SecurityException

原因

您的应用在未获得必要权限的情况下尝试启动前台服务。

  • 如果应用以 Android 9(API 级别 28)或更高版本为目标平台,则必须具有 FOREGROUND_SERVICE 权限才能启动前台服务。
  • 如果应用以 Android 14(API 级别 34)或更高版本为目标平台,则必须满足其前台服务类型的所有前提条件。前台服务类型文档详细介绍了这些前提条件。请特别注意以下要求:
    • 某些前台服务类型需要特定的运行时权限。例如,远程消息传递前台服务必须具有 FOREGROUND_SERVICE_REMOTE_MESSAGING 权限。
  • 在某些情况下,某些前台服务类型需要的权限在使用期间还会受到额外的限制。只有在应用处于前台时,系统才会向应用授予这些权限(少数特定情况除外)。这意味着,即使您的应用已请求并获得其中一种权限,如果应用在后台运行时尝试启动前台服务,即使应用有从后台启动前台服务的豁免,系统也会抛出 SecurityException。如需了解详情,请参阅与启动需要使用时权限的前台服务相关的限制
    • 如果您请求了必要的权限,但在确认已授予所需权限之前启动了前台服务,则可能会收到 SecurityException

修复方法

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