从后台启动前台服务的限制

目标 API 级别为 Android 12 (API 级别 31) 或更高版本的应用在应用后台运行时无法启动前台服务,但少数特殊情况除外。如果应用在后台运行时尝试启动前台服务,并且该前台服务不满足特殊情况之一,系统将抛出 ForegroundServiceStartNotAllowedException

此外,如果应用想要启动需要*使用中*权限(例如,身体传感器、相机、麦克风或位置权限)的前台服务,则即使应用属于后台启动限制的豁免情况之一,它也不能在应用在后台时*创建*该服务。原因在需要使用中权限的前台服务启动限制部分进行了解释。

后台启动限制的豁免情况

在以下情况下,即使您的应用在后台运行,也可以启动前台服务

对启动需要使用中权限的前台服务的限制

在 Android 14 (API 级别 34) 或更高版本上,如果您正在启动需要使用中权限的前台服务,则需要注意一些特殊情况。

如果您的应用目标 API 级别为 Android 14 或更高版本,操作系统会在您创建前台服务时检查以确保您的应用拥有该服务类型的所有相应权限。例如,当您创建 麦克风类型的前台服务时,操作系统会验证您的应用当前是否具有 RECORD_AUDIO 权限。如果您没有该权限,系统会抛出 SecurityException

对于使用中权限,这可能会导致一个问题。如果您的应用拥有使用中权限,则它仅在*在前台运行时*才拥有该权限。这意味着如果您的应用在后台,并且它尝试创建相机、位置或麦克风类型的前台服务,系统会发现您的应用*当前*没有所需的权限,并会抛出 SecurityException

同样,如果您的应用在后台,并且它创建了一个需要 BODY_SENSORS 权限的健康服务,则应用当前没有该权限,系统会抛出异常。(如果它是需要不同权限的健康服务,例如 ACTIVITY_RECOGNITION,则不适用此情况。)调用 PermissionChecker.checkSelfPermission() 不会阻止此问题。如果您的应用拥有使用中权限,并且它调用 checkSelfPermission() 来检查是否拥有该权限,即使应用在后台,该方法也会返回 PERMISSION_GRANTED。当该方法返回 PERMISSION_GRANTED 时,它表示“您的应用在*使用时*拥有此权限”。

因此,如果您的前台服务需要使用中权限,您必须在应用具有可见 Activity 时调用 Context.startForegroundService()Context.bindService(),除非该服务属于定义的豁免情况之一。

使用中权限限制的豁免情况

在某些情况下,即使前台服务是在应用后台运行时启动的,它仍然可以在应用在前台(“使用中”)运行时访问位置、相机和麦克风信息。

在这些相同的情况下,如果服务声明了 location 类型的前台服务,并且由具有 ACCESS_BACKGROUND_LOCATION 权限的应用启动,则此服务可以始终访问位置信息,即使应用在后台运行。

以下列表包含这些情况

  • 系统组件启动服务。
  • 服务通过与应用小部件交互启动。
  • 服务通过与通知交互启动。
  • 服务作为从不同可见应用发送的 PendingIntent 启动。
  • 服务由在设备所有者模式下运行的设备策略控制器应用启动。
  • 服务由提供 VoiceInteractionService 的应用启动。
  • 服务由具有 START_ACTIVITIES_FROM_BACKGROUND 特权权限的应用启动。

确定您的应用中受影响的服务

测试应用时,启动其前台服务。如果启动的服务对位置、麦克风和相机有受限访问,则 Logcat 中会显示以下消息

Foreground service started from background can not have \
location/camera/microphone access: service SERVICE_NAME