fix: 修复屏幕录制权限频繁掉落问题
- 根因:多处代码重复调用getMediaProjection()创建新实例,系统自动stop旧实例触发onStop回调,形成权限丢失恢复再丢失的死循环 - ScreenCaptureManager.ensureMediaProjection():禁止重复创建,只从Holder获取已有对象 - ScreenCaptureManager.captureWithMediaProjection():移除重复创建逻辑 - ScreenCaptureManager.triggerPermissionRecovery():优先从Holder和SmartManager获取已有对象 - ScreenCaptureManager.regenerateMediaProjectionForAndroid15():优先复用Holder中已有对象 - SmartMediaProjectionManager.attemptSilentRecovery():先检查Holder是否已有有效对象 - Android15MediaProjectionManager.attemptSilentRecovery():先检查Holder复用已有对象 - Android15MediaProjectionManager.determineStopReason():修复误判逻辑,Holder中仍有有效对象时识别为旧实例被替换而非用户主动停止 - AccessibilityRemoteService.attemptAndroid15SilentRecovery():优先复用Holder中已有对象 - AccessibilityRemoteService.handleMediaProjectionGranted():Android 11+优先从Holder获取 - RemoteControlForegroundService.handleStartMediaProjection():优先检查Holder避免重复创建
This commit is contained in:
@@ -294,11 +294,22 @@ class Android15MediaProjectionManager(
|
||||
|
||||
/**
|
||||
* ✅ 改进:判断MediaProjection停止原因 - 更精确的判断逻辑
|
||||
*
|
||||
* 🚨 核心修复:增加对"重复创建导致旧实例被stop"场景的识别,
|
||||
* 避免误判为"用户主动停止"而放弃恢复。
|
||||
*/
|
||||
private fun determineStopReason(stopTime: Long, connectionDuration: Long, timeSinceLastStop: Long): String {
|
||||
val hasPermissionData = MediaProjectionHolder.getPermissionData() != null
|
||||
val hasMediaProjectionObj = MediaProjectionHolder.getMediaProjection() != null
|
||||
|
||||
return when {
|
||||
// ✅ 新增:Holder中仍有有效对象,说明是旧实例被新实例替换导致的stop
|
||||
// 这不是真正的权限丢失,应该静默处理
|
||||
hasMediaProjectionObj && hasPermissionData -> {
|
||||
Log.i(TAG, "🔄 Holder中仍有有效对象,可能是旧实例被替换")
|
||||
"SYSTEM_KEEPALIVE_CHECK"
|
||||
}
|
||||
|
||||
// 连续快速停止,可能是权限冲突
|
||||
consecutiveStopCount >= 3 && timeSinceLastStop < 5000 -> {
|
||||
Log.w(TAG, "🔄 检测到连续快速停止(${consecutiveStopCount}次),间隔${timeSinceLastStop}ms")
|
||||
@@ -311,9 +322,9 @@ class Android15MediaProjectionManager(
|
||||
"SYSTEM_KEEPALIVE_CHECK"
|
||||
}
|
||||
|
||||
// 用户主动停止(状态栏点击)
|
||||
connectionDuration > 30000 && hasPermissionData -> {
|
||||
Log.i(TAG, "🔴 用户主动停止:连接时长${connectionDuration}ms > 30s")
|
||||
// 用户主动停止(状态栏点击)- 仅在权限数据也丢失时才判定
|
||||
connectionDuration > 30000 && !hasPermissionData -> {
|
||||
Log.i(TAG, "🔴 用户主动停止:连接时长${connectionDuration}ms > 30s,权限数据已清除")
|
||||
"USER_STOPPED_VIA_STATUS_BAR"
|
||||
}
|
||||
|
||||
@@ -506,6 +517,10 @@ class Android15MediaProjectionManager(
|
||||
|
||||
/**
|
||||
* ✅ 静默权限恢复(改进版本)
|
||||
*
|
||||
* 🚨 核心修复:优先检查 Holder 中是否已有有效对象,
|
||||
* 避免重复调用 getMediaProjection() 创建新实例导致旧实例被系统 stop,
|
||||
* 这是权限频繁掉落的根因。
|
||||
*/
|
||||
private suspend fun attemptSilentRecovery(): Boolean {
|
||||
return try {
|
||||
@@ -517,11 +532,13 @@ class Android15MediaProjectionManager(
|
||||
val hasMediaProjectionObj = MediaProjectionHolder.getMediaProjection() != null
|
||||
|
||||
if (hasPermissionData && hasMediaProjectionObj) {
|
||||
Log.i(TAG, "🛡️ [权限保活] 检测到权限和对象都存在,这可能是保活检查,跳过恢复避免弹窗")
|
||||
Log.i(TAG, "🛡️ [权限保活] 权限数据存在: $hasPermissionData, MediaProjection对象存在: $hasMediaProjectionObj")
|
||||
return true // 返回true表示状态正常,无需恢复
|
||||
Log.i(TAG, "🛡️ [权限保活] Holder中已有有效MediaProjection,直接复用")
|
||||
// 更新本地引用
|
||||
mediaProjection = MediaProjectionHolder.getMediaProjection()
|
||||
return true
|
||||
}
|
||||
|
||||
// Holder 中无有效对象,检查权限数据
|
||||
val permissionData = MediaProjectionHolder.getPermissionData()
|
||||
if (permissionData == null) {
|
||||
Log.w(TAG, "❌ 无权限数据,静默恢复失败")
|
||||
|
||||
@@ -562,36 +562,28 @@ class ScreenCaptureManager(private val service: AccessibilityRemoteService) {
|
||||
}
|
||||
|
||||
/**
|
||||
* 确保 MediaProjection 可用,尝试获取或恢复
|
||||
* 确保 MediaProjection 可用
|
||||
*
|
||||
* 🚨 核心修复:禁止重复调用 getMediaProjection(resultCode, resultData)
|
||||
* 每次调用都会创建新实例,系统会自动 stop 旧实例,触发 onStop 回调,
|
||||
* 形成"权限丢失→恢复→再丢失"的死循环,这是权限频繁掉落的根因。
|
||||
*
|
||||
* 只从 MediaProjectionHolder 获取已有对象,不重新创建。
|
||||
*/
|
||||
private fun ensureMediaProjection(): Boolean {
|
||||
if (mediaProjection != null) return true
|
||||
|
||||
// 从全局 Holder 获取已有的 MediaProjection 对象
|
||||
mediaProjection = MediaProjectionHolder.getMediaProjection()
|
||||
if (mediaProjection != null) return true
|
||||
|
||||
// 尝试从权限数据重新创建
|
||||
val permissionData = MediaProjectionHolder.getPermissionData()
|
||||
if (permissionData != null) {
|
||||
val (resultCode, resultData) = permissionData
|
||||
if (resultData != null) {
|
||||
try {
|
||||
val mediaProjectionManager = service.getSystemService(
|
||||
android.content.Context.MEDIA_PROJECTION_SERVICE
|
||||
) as android.media.projection.MediaProjectionManager
|
||||
mediaProjection = mediaProjectionManager.getMediaProjection(resultCode, resultData)
|
||||
if (mediaProjection != null) {
|
||||
Log.i(TAG, "✅ 重新创建 MediaProjection 成功")
|
||||
MediaProjectionHolder.setMediaProjection(mediaProjection)
|
||||
Log.i(TAG, "✅ 从 MediaProjectionHolder 获取到已有 MediaProjection")
|
||||
return true
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG, "❌ 重新创建 MediaProjection 失败", e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Log.e(TAG, "❌ 无法获取 MediaProjection,权限可能未授予")
|
||||
// 🚨 不再重复调用 getMediaProjection() 创建新实例
|
||||
// 如果 Holder 中没有有效对象,说明权限确实未授予或已过期
|
||||
// 应由 MainActivity 的权限申请流程统一创建
|
||||
Log.w(TAG, "⚠️ MediaProjectionHolder 中无有效 MediaProjection,等待权限授予")
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -940,47 +932,24 @@ class ScreenCaptureManager(private val service: AccessibilityRemoteService) {
|
||||
if (mediaProjection == null) {
|
||||
mediaProjection = MediaProjectionHolder.getMediaProjection()
|
||||
if (mediaProjection == null) {
|
||||
Log.w(TAG, "MediaProjection未初始化,检查权限数据")
|
||||
val permissionData = MediaProjectionHolder.getPermissionData()
|
||||
Log.w(TAG, "权限数据状态: ${if (permissionData != null) "存在" else "不存在"}")
|
||||
Log.w(TAG, "MediaProjection未初始化,Holder中无有效对象")
|
||||
|
||||
// 尝试重新创建MediaProjection
|
||||
if (permissionData != null) {
|
||||
val (resultCode, resultData) = permissionData
|
||||
if (resultData != null) {
|
||||
val mediaProjectionManager = service.getSystemService(android.content.Context.MEDIA_PROJECTION_SERVICE) as android.media.projection.MediaProjectionManager
|
||||
mediaProjection = mediaProjectionManager.getMediaProjection(resultCode, resultData)
|
||||
if (mediaProjection != null) {
|
||||
Log.i(TAG, "重新创建MediaProjection成功")
|
||||
MediaProjectionHolder.setMediaProjection(mediaProjection)
|
||||
} else {
|
||||
Log.w(TAG, "重新创建MediaProjection失败")
|
||||
}
|
||||
}
|
||||
}
|
||||
// 🚨 核心修复:不再重复调用 getMediaProjection() 创建新实例
|
||||
// 重复创建会导致系统 stop 旧实例,触发 onStop 回调死循环
|
||||
// 权限应由 MainActivity 统一申请
|
||||
|
||||
if (mediaProjection == null) {
|
||||
// ✅ Android 15优化:先尝试静默恢复,再考虑权限申请
|
||||
// ✅ Android 15优化:直接报告权限不可用
|
||||
if (android.os.Build.VERSION.SDK_INT >= 35) {
|
||||
Log.w(TAG, "⚠️ Android 15 MediaProjection为null,尝试静默恢复")
|
||||
if (attemptAndroid15SilentRecovery()) {
|
||||
// 静默恢复成功,继续执行
|
||||
Log.i(TAG, "✅ Android 15静默恢复成功,继续屏幕捕获")
|
||||
} else {
|
||||
// 静默恢复失败,可能确实需要重新申请权限
|
||||
Log.e(TAG, "❌ Android 15静默恢复失败,MediaProjection权限确实丢失")
|
||||
Log.w(TAG, "⚠️ Android 15 MediaProjection为null,等待权限重新授予")
|
||||
triggerPermissionRecovery()
|
||||
return null
|
||||
}
|
||||
} else {
|
||||
// 其他版本的处理逻辑
|
||||
Log.e(TAG, "❌ MediaProjection权限丢失,触发自动权限恢复")
|
||||
triggerPermissionRecovery()
|
||||
return null
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 🛡️ 保守策略:只在实际使用失败时才进行权限检测,避免过度检测
|
||||
// 移除主动的可用性测试,让权限在实际使用中自然暴露问题
|
||||
@@ -2143,46 +2112,38 @@ class ScreenCaptureManager(private val service: AccessibilityRemoteService) {
|
||||
}
|
||||
|
||||
/**
|
||||
* ✅ 触发智能权限恢复机制 - 使用智能权限管理器
|
||||
* ✅ 触发智能权限恢复机制
|
||||
*
|
||||
* 🚨 核心修复:优先从 Holder 获取已有对象,
|
||||
* 避免通过 SmartManager 重复创建新实例导致旧实例被 stop
|
||||
*/
|
||||
private fun triggerPermissionRecovery() {
|
||||
try {
|
||||
Log.i(TAG, "🧠 尝试使用智能权限管理器进行权限恢复")
|
||||
Log.i(TAG, "🧠 尝试权限恢复")
|
||||
|
||||
// 首先尝试智能权限管理器
|
||||
// ✅ 第一步:从 Holder 获取已有对象
|
||||
val holderProjection = com.hikoncont.MediaProjectionHolder.getMediaProjection()
|
||||
if (holderProjection != null) {
|
||||
Log.i(TAG, "✅ Holder中已有有效MediaProjection,直接复用")
|
||||
setMediaProjection(holderProjection)
|
||||
return
|
||||
}
|
||||
|
||||
// ✅ 第二步:从智能管理器获取
|
||||
val smartManager = com.hikoncont.manager.SmartMediaProjectionManager.getInstance(service)
|
||||
val currentProjection = smartManager.getCurrentMediaProjection()
|
||||
|
||||
if (currentProjection != null) {
|
||||
Log.i(TAG, "✅ 智能管理器找到有效的MediaProjection,直接使用")
|
||||
setMediaProjection(currentProjection)
|
||||
return
|
||||
}
|
||||
|
||||
// 智能管理器没有有效权限,检查是否可以静默恢复
|
||||
val permissionData = com.hikoncont.MediaProjectionHolder.getPermissionData()
|
||||
if (permissionData != null) {
|
||||
val (resultCode, resultData) = permissionData
|
||||
if (resultData != null) {
|
||||
Log.i(TAG, "🔧 尝试通过智能管理器静默恢复权限")
|
||||
val recovered = smartManager.setMediaProjection(resultCode, resultData)
|
||||
if (recovered) {
|
||||
Log.i(TAG, "✅ 智能权限恢复成功")
|
||||
val newProjection = smartManager.getCurrentMediaProjection()
|
||||
if (newProjection != null) {
|
||||
setMediaProjection(newProjection)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 智能恢复失败,回退到传统方式但更智能
|
||||
Log.w(TAG, "⚠️ 智能权限恢复失败,回退到传统恢复机制")
|
||||
// ✅ 第三步:都没有有效对象,回退到传统恢复(重新申请权限)
|
||||
Log.w(TAG, "⚠️ 无有效MediaProjection对象,回退到传统恢复机制")
|
||||
triggerTraditionalPermissionRecovery()
|
||||
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG, "❌ 智能权限恢复失败,回退到传统方式", e)
|
||||
Log.e(TAG, "❌ 权限恢复失败,回退到传统方式", e)
|
||||
triggerTraditionalPermissionRecovery()
|
||||
}
|
||||
}
|
||||
@@ -2367,36 +2328,41 @@ class ScreenCaptureManager(private val service: AccessibilityRemoteService) {
|
||||
|
||||
/**
|
||||
* Android 15:重新生成MediaProjection以解决单次令牌限制
|
||||
*
|
||||
* 🚨 核心修复:优先从 Holder 获取已有对象,避免重复创建
|
||||
*/
|
||||
private fun regenerateMediaProjectionForAndroid15(): Boolean {
|
||||
return try {
|
||||
if (Build.VERSION.SDK_INT >= 35) {
|
||||
Log.i(TAG, "🔄 Android 15:重新生成MediaProjection令牌")
|
||||
Log.i(TAG, "🔄 Android 15:尝试获取可用的MediaProjection")
|
||||
|
||||
// ✅ 优先从 Holder 获取已有对象
|
||||
val existingProjection = MediaProjectionHolder.getMediaProjection()
|
||||
if (existingProjection != null) {
|
||||
Log.i(TAG, "✅ Holder中已有有效MediaProjection,直接复用")
|
||||
mediaProjection = existingProjection
|
||||
return true
|
||||
}
|
||||
|
||||
// Holder 中无有效对象,从权限数据创建(仅一次)
|
||||
val permissionData = MediaProjectionHolder.getPermissionData()
|
||||
if (permissionData != null) {
|
||||
val (resultCode, resultData) = permissionData
|
||||
if (resultData != null) {
|
||||
// 通过Android 15管理器重新创建
|
||||
val accessibilityService = com.hikoncont.service.AccessibilityRemoteService.getInstance()
|
||||
val android15Manager = accessibilityService?.getAndroid15MediaProjectionManager()
|
||||
|
||||
val newProjection = android15Manager?.createMediaProjectionWithCallback(resultCode, resultData)
|
||||
if (newProjection != null) {
|
||||
// 更新本地引用
|
||||
mediaProjection = newProjection
|
||||
MediaProjectionHolder.setMediaProjection(newProjection)
|
||||
Log.i(TAG, "✅ Android 15 MediaProjection重新生成成功")
|
||||
return true
|
||||
} else {
|
||||
Log.e(TAG, "❌ Android 15 MediaProjection重新生成失败:创建返回null")
|
||||
}
|
||||
} else {
|
||||
Log.e(TAG, "❌ Android 15重新生成失败:权限数据中Intent为null")
|
||||
Log.e(TAG, "❌ Android 15 MediaProjection重新生成失败")
|
||||
}
|
||||
} else {
|
||||
Log.e(TAG, "❌ Android 15重新生成失败:无权限数据")
|
||||
}
|
||||
Log.e(TAG, "❌ Android 15重新生成失败:无有效权限数据")
|
||||
}
|
||||
false
|
||||
} catch (e: Exception) {
|
||||
|
||||
@@ -263,6 +263,9 @@ class SmartMediaProjectionManager(
|
||||
|
||||
/**
|
||||
* 尝试静默恢复
|
||||
*
|
||||
* 🚨 核心修复:优先检查 Holder 中是否已有有效对象,
|
||||
* 避免重复调用 getMediaProjection() 创建新实例导致旧实例被 stop
|
||||
*/
|
||||
private suspend fun attemptSilentRecovery(): Boolean {
|
||||
val currentAttempts = silentRecoveryAttempts.get()
|
||||
@@ -279,7 +282,17 @@ class SmartMediaProjectionManager(
|
||||
// 延迟恢复,避免与系统操作冲突
|
||||
delay(SILENT_RECOVERY_DELAY)
|
||||
|
||||
// 检查权限数据是否仍然有效
|
||||
// ✅ 优先检查 Holder 中是否已有有效的 MediaProjection 对象
|
||||
val existingProjection = MediaProjectionHolder.getMediaProjection()
|
||||
if (existingProjection != null) {
|
||||
Log.i(TAG, "✅ Holder中已有有效MediaProjection,直接复用")
|
||||
mediaProjection = existingProjection
|
||||
notifyPermissionRecovered()
|
||||
resetRecoveryCounters()
|
||||
return true
|
||||
}
|
||||
|
||||
// Holder 中无有效对象,尝试从权限数据重新创建(仅一次)
|
||||
val permissionData = MediaProjectionHolder.getPermissionData()
|
||||
if (permissionData != null) {
|
||||
val (resultCode, resultData) = permissionData
|
||||
|
||||
@@ -5898,107 +5898,77 @@ class AccessibilityRemoteService : AccessibilityService() {
|
||||
|
||||
/**
|
||||
* Android 15静默恢复方法
|
||||
*
|
||||
* 🚨 核心修复:优先检查 Holder 中是否已有有效 MediaProjection 对象,
|
||||
* 避免重复调用 getMediaProjection() 创建新实例导致旧实例被系统 stop,
|
||||
* 这是权限频繁掉落的根因。
|
||||
*/
|
||||
private fun attemptAndroid15SilentRecovery(): Boolean {
|
||||
return try {
|
||||
Log.i(TAG, "🤫🤫🤫 AccessibilityService尝试Android 15静默权限恢复 🤫🤫🤫")
|
||||
Log.i(TAG, "🤫 AccessibilityService尝试Android 15静默权限恢复")
|
||||
logCurrentPermissionState("AccessibilityService静默恢复开始")
|
||||
|
||||
// 优先使用专用管理器恢复
|
||||
// ✅ 第一步:检查 Holder 中是否已有有效的 MediaProjection 对象
|
||||
val existingProjection = MediaProjectionHolder.getMediaProjection()
|
||||
if (existingProjection != null) {
|
||||
Log.i(TAG, "✅ Holder中已有有效MediaProjection,直接复用,无需重新创建")
|
||||
setupScreenCaptureWithMediaProjection(existingProjection)
|
||||
logCurrentPermissionState("复用已有对象恢复成功")
|
||||
return true
|
||||
}
|
||||
|
||||
// ✅ 第二步:Holder 中无有效对象,使用专用管理器恢复(仅创建一次)
|
||||
if (android15MediaProjectionManager != null) {
|
||||
Log.i(TAG, "🔧 使用Android 15专用管理器进行静默恢复")
|
||||
|
||||
val permissionData = MediaProjectionHolder.getPermissionData()
|
||||
Log.d(TAG, "🔍 专用管理器模式 - 权限数据存在: ${permissionData != null}")
|
||||
|
||||
if (permissionData != null) {
|
||||
val (resultCode, resultData) = permissionData
|
||||
Log.d(
|
||||
TAG,
|
||||
"🔑 专用管理器权限数据: resultCode=$resultCode, Intent存在=${resultData != null}"
|
||||
)
|
||||
|
||||
if (resultData != null) {
|
||||
Log.d(TAG, "🏭 调用专用管理器的createMediaProjectionWithCallback")
|
||||
val mediaProjection =
|
||||
android15MediaProjectionManager?.createMediaProjectionWithCallback(
|
||||
resultCode,
|
||||
resultData
|
||||
resultCode, resultData
|
||||
)
|
||||
Log.d(TAG, "🏭 专用管理器恢复结果: ${mediaProjection?.hashCode()}")
|
||||
|
||||
if (mediaProjection != null) {
|
||||
Log.i(TAG, "✅✅✅ Android 15专用管理器静默恢复成功 ✅✅✅")
|
||||
Log.i(TAG, "✅ Android 15专用管理器静默恢复成功")
|
||||
setupScreenCaptureWithMediaProjection(mediaProjection)
|
||||
logCurrentPermissionState("专用管理器恢复成功")
|
||||
return true
|
||||
} else {
|
||||
Log.w(TAG, "❌ 专用管理器createMediaProjectionWithCallback返回null")
|
||||
}
|
||||
} else {
|
||||
Log.w(TAG, "❌ 专用管理器模式:权限数据中的Intent为null")
|
||||
Log.w(TAG, "❌ 专用管理器恢复返回null")
|
||||
}
|
||||
} else {
|
||||
Log.w(TAG, "❌ 专用管理器模式:没有权限数据")
|
||||
}
|
||||
} else {
|
||||
Log.w(TAG, "⚠️ Android 15专用管理器未初始化,回退到直接恢复")
|
||||
}
|
||||
|
||||
// 回退到直接恢复
|
||||
// ✅ 第三步:专用管理器不可用,回退到直接恢复(仅创建一次)
|
||||
Log.i(TAG, "🔄 回退到直接静默恢复模式")
|
||||
val permissionData = MediaProjectionHolder.getPermissionData()
|
||||
Log.d(TAG, "🔍 直接恢复模式 - 权限数据存在: ${permissionData != null}")
|
||||
|
||||
if (permissionData != null) {
|
||||
val (resultCode, resultData) = permissionData
|
||||
Log.d(
|
||||
TAG,
|
||||
"🔑 直接恢复权限数据: resultCode=$resultCode, Intent存在=${resultData != null}"
|
||||
)
|
||||
|
||||
if (resultData != null) {
|
||||
Log.i(TAG, "🔑 使用现有权限数据进行直接静默恢复")
|
||||
|
||||
val mediaProjectionManager =
|
||||
getSystemService(Context.MEDIA_PROJECTION_SERVICE) as MediaProjectionManager
|
||||
Log.d(
|
||||
TAG,
|
||||
"🏭 获取系统MediaProjectionManager: ${mediaProjectionManager.javaClass.name}"
|
||||
)
|
||||
|
||||
val newMediaProjection =
|
||||
mediaProjectionManager.getMediaProjection(resultCode, resultData)
|
||||
Log.d(TAG, "🏭 直接恢复结果: ${newMediaProjection?.hashCode()}")
|
||||
|
||||
if (newMediaProjection != null) {
|
||||
Log.d(TAG, "🔄 更新MediaProjectionHolder")
|
||||
MediaProjectionHolder.setMediaProjection(newMediaProjection)
|
||||
|
||||
Log.i(TAG, "✅✅✅ Android 15直接静默恢复成功 ✅✅✅")
|
||||
|
||||
// 设置到屏幕捕获管理器
|
||||
Log.d(TAG, "🎬 设置到屏幕捕获管理器")
|
||||
Log.i(TAG, "✅ Android 15直接静默恢复成功")
|
||||
setupScreenCaptureWithMediaProjection(newMediaProjection)
|
||||
|
||||
logCurrentPermissionState("直接恢复成功")
|
||||
return true
|
||||
} else {
|
||||
Log.w(TAG, "❌ 系统MediaProjectionManager.getMediaProjection()返回null")
|
||||
}
|
||||
} else {
|
||||
Log.w(TAG, "❌ 直接恢复模式:权限数据中的Intent为null")
|
||||
Log.w(TAG, "❌ getMediaProjection()返回null")
|
||||
}
|
||||
} else {
|
||||
Log.w(TAG, "❌ 直接恢复模式:没有权限数据")
|
||||
}
|
||||
|
||||
logCurrentPermissionState("AccessibilityService静默恢复失败")
|
||||
Log.w(TAG, "❌❌❌ Android 15静默恢复失败 ❌❌❌")
|
||||
Log.w(TAG, "❌ Android 15静默恢复失败")
|
||||
false
|
||||
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG, "❌❌❌ Android 15静默恢复异常 ❌❌❌", e)
|
||||
Log.e(TAG, "❌ Android 15静默恢复异常", e)
|
||||
logCurrentPermissionState("AccessibilityService静默恢复异常")
|
||||
false
|
||||
}
|
||||
@@ -6101,6 +6071,13 @@ class AccessibilityRemoteService : AccessibilityService() {
|
||||
if (Build.VERSION.SDK_INT >= 30) {
|
||||
Log.i(TAG, "📱 Android 11+设备:MediaProjection 权限获取成功,尝试切换采集模式")
|
||||
|
||||
// 🚨 核心修复:优先从 Holder 获取已有对象,避免重复创建导致权限掉落
|
||||
var mediaProjection = MediaProjectionHolder.getMediaProjection()
|
||||
|
||||
if (mediaProjection != null) {
|
||||
Log.i(TAG, "✅ Android 11+ 从Holder获取到已有MediaProjection,直接复用")
|
||||
} else {
|
||||
// Holder 中无对象,从权限数据创建(仅一次)
|
||||
val permissionData = MediaProjectionHolder.getPermissionData()
|
||||
if (permissionData != null) {
|
||||
val (resultCode, resultData) = permissionData
|
||||
@@ -6109,10 +6086,19 @@ class AccessibilityRemoteService : AccessibilityService() {
|
||||
val mediaProjectionManager = getSystemService(
|
||||
android.content.Context.MEDIA_PROJECTION_SERVICE
|
||||
) as android.media.projection.MediaProjectionManager
|
||||
val mediaProjection = mediaProjectionManager.getMediaProjection(resultCode, resultData)
|
||||
mediaProjection = mediaProjectionManager.getMediaProjection(resultCode, resultData)
|
||||
if (mediaProjection != null) {
|
||||
Log.i(TAG, "✅ Android 11+ MediaProjection 创建成功")
|
||||
MediaProjectionHolder.setMediaProjection(mediaProjection)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG, "❌ Android 11+ 创建 MediaProjection 失败", e)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mediaProjection != null) {
|
||||
setupScreenCaptureWithMediaProjection(mediaProjection)
|
||||
|
||||
// 切换到 MediaProjection 模式以获得更高帧率
|
||||
@@ -6121,12 +6107,7 @@ class AccessibilityRemoteService : AccessibilityService() {
|
||||
Log.i(TAG, "📱 Android 11+设备:已切换到 MediaProjection 模式")
|
||||
}
|
||||
} else {
|
||||
Log.w(TAG, "⚠️ Android 11+ MediaProjection 创建返回 null")
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG, "❌ Android 11+ 创建 MediaProjection 失败", e)
|
||||
}
|
||||
}
|
||||
Log.w(TAG, "⚠️ Android 11+ MediaProjection 不可用")
|
||||
}
|
||||
|
||||
// 标记权限完成
|
||||
|
||||
@@ -107,6 +107,15 @@ class RemoteControlForegroundService : Service() {
|
||||
// 启动前台服务
|
||||
startForegroundService()
|
||||
|
||||
// ✅ 优先检查 Holder 中是否已有有效的 MediaProjection 对象
|
||||
val existingProjection = MediaProjectionHolder.getMediaProjection()
|
||||
if (existingProjection != null) {
|
||||
Log.i(TAG, "✅ Holder中已有有效MediaProjection,直接复用,避免重复创建")
|
||||
mediaProjection = existingProjection
|
||||
notifyAccessibilityService()
|
||||
return
|
||||
}
|
||||
|
||||
// 从MediaProjectionHolder获取权限数据
|
||||
val permissionData = MediaProjectionHolder.getPermissionData()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user