03-前台服务与后台限制
前台服务与后台限制
1. 为什么不能再简单说 Service 可以后台无限运行
早期 Android 资料常说:
Service 可以在后台长期运行。
这个说法在现代 Android 中必须加限制条件。Android 8.0 开始,后台 Service 受到系统限制;Android 12 开始,从后台启动前台服务也受到限制;Android 14 开始,前台服务类型和权限要求更严格;Android 15 以后,部分前台服务类型从 BOOT_COMPLETED 启动也受到限制。
更准确的说法是:
Service 可以承载后台或前台任务,但后台执行能力受到系统版本、应用前后台状态、前台服务类型、权限和电量策略限制。
2. Background Service
后台服务是用户不直接感知的 Service。
例如:
- 清理缓存。
- 定时同步。
- 后台上传日志。
Android 8.0 以后,如果应用进入后台一段时间,系统会限制后台服务继续运行,并可能像调用了 stopSelf() 一样停止它。
所以对于不需要立即执行、需要可靠调度的任务,更推荐:
WorkManager / JobScheduler
3. Foreground Service
前台服务用于用户能明显感知、需要立即持续执行的任务。它必须显示通知,让用户知道应用正在执行任务。
适合场景:
| 场景 | 是否适合前台服务 |
|---|---|
| 音乐播放 | 是 |
| 导航定位 | 是 |
| 运动记录 | 是 |
| 录音/通话 | 是,但要满足权限和类型要求 |
| 静默上传日志 | 通常不适合,优先 WorkManager |
| 定时清理缓存 | 不适合,优先 WorkManager |
4. 启动前台服务
Activity 可见时启动:
val intent = Intent(this, MusicService::class.java)
ContextCompat.startForegroundService(this, intent)
Service 中尽快提升为前台服务:
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
val notification = createNotification()
ServiceCompat.startForeground(
this,
NOTIFICATION_ID,
notification,
ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK
)
return START_STICKY
}
注意:启动前台服务后,必须在规定时间内调用 startForeground() 显示通知,否则会被系统停止并可能触发异常或 ANR。
5. Android 8.0 后台服务限制
Android 8.0 以后:
- 应用在前台时,可以正常创建和运行前台/后台服务。
- 应用进入后台后,只有短暂窗口期可以继续使用后台服务。
- 超过窗口期后,系统会停止后台服务。
- 如果需要后台启动前台服务,应使用
startForegroundService(),并尽快调用startForeground()。
6. Android 12 前台服务后台启动限制
Android 12 以后,应用在后台时通常不能直接启动前台服务,除非满足少数例外情况,例如:
- 用户刚刚触发了和应用相关的可见操作。
- 高优先级 FCM 消息。
- 某些系统角色或特殊权限。
- 从通知、Widget、气泡等用户可见入口触发。
否则可能抛出:
ForegroundServiceStartNotAllowedException
7. Android 14 前台服务类型要求
如果应用 target Android 14 或更高,前台服务必须声明合适的类型,例如:
<service
android:name=".LocationService"
android:exported="false"
android:foregroundServiceType="location" />
还需要声明对应权限:
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_LOCATION" />
并且运行时还要满足该类型需要的权限,例如定位前台服务需要定位权限。
常见类型:
| 类型 | 场景 |
|---|---|
mediaPlayback |
音视频播放 |
location |
导航、位置共享 |
camera |
后台视频通话等 |
microphone |
录音、语音通话 |
dataSync |
用户可感知的数据同步 |
connectedDevice |
蓝牙、USB、NFC 等设备连接 |
shortService |
很短的关键任务 |
8. Android 15 相关注意
Android 15 对部分前台服务类型增加了限制,例如 target Android 15 或更高的应用,某些类型不能从 BOOT_COMPLETED 广播接收器中启动。
因此启动前台服务时要同时考虑:
应用是否在前台
targetSdkVersion
服务类型
运行时权限
启动来源
是否有系统例外条件
9. WorkManager 什么时候更合适
以下任务通常不应该用 Service 硬扛:
| 任务 | 推荐方案 |
|---|---|
| 定时同步 | WorkManager PeriodicWorkRequest |
| 网络可用时上传 | WorkManager + NetworkType.CONNECTED |
| 设备充电时清理 | WorkManager + Charging constraint |
| App 重启后仍要继续的任务 | WorkManager |
| 立即但可在几分钟内完成的后台任务 | WorkManager expedited work |
| 用户明确可感知的持续任务 | Foreground Service |
10. 面试回答模板
问题:Service 能一直在后台运行吗?
可以这样回答:
不能简单这么说。Service 默认运行在主线程,而且从 Android 8.0 开始后台服务受到限制,应用进入后台一段时间后后台 Service 可能被系统停止。用户可感知的持续任务应该使用前台服务并显示通知;不需要立即执行但要求可靠的任务应该使用 WorkManager。Android 12 以后后台启动前台服务也有限制,Android 14 以后还需要声明前台服务类型和对应权限。