目标 API 级别为 Android 12 (API 级别 31) 或更高版本的应用在应用后台运行时无法启动前台服务,但少数特殊情况除外。如果应用在后台运行时尝试启动前台服务,并且该前台服务不满足特殊情况之一,系统将抛出 ForegroundServiceStartNotAllowedException
。
此外,如果应用想要启动需要*使用中*权限(例如,身体传感器、相机、麦克风或位置权限)的前台服务,则即使应用属于后台启动限制的豁免情况之一,它也不能在应用在后台时*创建*该服务。原因在需要使用中权限的前台服务启动限制部分进行了解释。
后台启动限制的豁免情况
在以下情况下,即使您的应用在后台运行,也可以启动前台服务
- 您的应用从用户可见状态转换而来,例如Activity。
- 您的应用可以从后台启动 Activity,但应用程序在现有任务的返回堆栈中存在 Activity 的情况除外。
您的应用使用 Firebase Cloud Messaging 收到高优先级消息。
您的应用调用精确闹钟以完成用户请求的操作。
您的应用是设备的当前输入法。
设备重启后,并在广播接收器中收到
ACTION_BOOT_COMPLETED
、ACTION_LOCKED_BOOT_COMPLETED
或ACTION_MY_PACKAGE_REPLACED
意图操作。您的应用在广播接收器中收到
ACTION_TIMEZONE_CHANGED
、ACTION_TIME_CHANGED
或ACTION_LOCALE_CHANGED
意图操作。您的应用收到来自
NfcService
的ACTION_TRANSACTION_DETECTED
事件。您的应用使用 Companion Device Manager 并声明
REQUEST_COMPANION_START_FOREGROUND_SERVICES_FROM_BACKGROUND
权限或REQUEST_COMPANION_RUN_IN_BACKGROUND
权限。尽可能使用REQUEST_COMPANION_START_FOREGROUND_SERVICES_FROM_BACKGROUND
。用户为您的应用关闭了电池优化。
您的应用持有
SYSTEM_ALERT_WINDOW
权限。注意:如果您的应用目标 API 级别为 Android 15 或更高版本,则它必须拥有SYSTEM_ALERT_WINDOW
权限*并且*应用当前必须具有可见的叠加窗口。
对启动需要使用中权限的前台服务的限制
在 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