低概率MediaProjection相关SecurityException崩溃问题排查求助
问题详情
程序有0.001%的极低概率触发如下崩溃,而且崩溃一旦出现,不重启设备就会一直发生:
java.lang.SecurityException: Media projections require a foreground service of type ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PROJECTION
该问题只在Android 10、11、12版本出现,Android 13及以上暂未发现。
已确认的正确配置
- Manifest里已经加了
android.permission.FOREGROUND_SERVICE和android.permission.FOREGROUND_SERVICE_MEDIA_PROJECTION权限 - 目标服务已经声明
android:foregroundServiceType="mediaProjection"属性 - 通知渠道、通知都已创建,服务启动时
startForeground()调用成功(日志可证) - 试过
adb shell dumpsys activity命令,没法导出服务的前台服务类型信息
排查建议
1. 盯紧服务启动和MediaProjection获取的时序
Android 10+对前台服务的绑定时机卡得严,必须先完成startForeground(),再去请求MediaProjection权限、创建MediaProjection实例。极低概率出现的问题,大概率是极端场景下(比如系统资源紧张,服务启动慢),MediaProjection的请求跑在了startForeground()前面。
- 加日志打点,记录
startForeground()完成的时间点,还有MediaProjection实例创建的时间点,对比两者的先后顺序 - 在MediaProjection的
onActivityResult回调里,先确认服务已经进入前台状态,再初始化投影逻辑
2. 排查系统层面的前台服务状态异常
有些Android 10-12的定制ROM,可能存在前台服务状态同步延迟或者异常,导致系统没正确识别服务的mediaProjection类型:
- 崩溃发生后,马上调用
Context.getSystemService(ActivityManager.class).getRunningServices(),遍历找到目标服务的RunningServiceInfo,检查foregroundServiceType字段有没有包含ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PROJECTION - 如果代码拿不到,试试
adb shell dumpsys activity services <你的完整包名>,精准定位目标服务的状态
3. 处理服务被系统强制降级的情况
Android 10+在某些场景下(比如应用被后台杀死后重启),可能会强制取消前台服务的类型声明,导致后面启动的服务没法正确关联mediaProjection类型:
- 在服务的
onCreate()或者onStartCommand()里,额外检查当前服务的前台类型对不对,要是不匹配,就重新调用startForeground()(注意要用同一个通知ID) - 监听
ACTION_PACKAGE_RESTARTED这类系统广播,应用重启后重新初始化前台服务状态
4. 验证MediaProjection权限令牌的有效性
MediaProjection的权限令牌(MediaProjectionManager.getMediaProjection()返回的实例)在设备重启前是有效的,但如果服务被销毁后重建,可能出现令牌和新服务不绑定的情况:
- 保存好通过
createScreenCaptureIntent()拿到的权限令牌,服务重建时重新获取令牌并绑定到新的服务实例 - 别在多个服务实例之间共享同一个MediaProjection令牌
5. 针对定制ROM做特殊适配
部分国产定制ROM(比如小米、华为、vivo等)在Android 10-12版本对前台服务有额外限制,可能存在系统层面的拦截:
- 在崩溃设备上检查应用的「后台弹出界面」「显示悬浮窗」这类权限有没有被禁用
- 试试把通知优先级设成最高(
Notification.PRIORITY_MAX),避免被系统强制回收
内容的提问来源于stack exchange,提问作者progquester

