package com.xw.common import android.view.Window import android.view.WindowManager import java.lang.ref.WeakReference /** * 统一管理 APP 防截屏(FLAG_SECURE)开关。 * * 默认行为:非 DEBUG 包禁止截屏,DEBUG 包允许截屏,保持与历史逻辑一致。 * * 内部用弱引用集合保存所有受管理的 [Window](避免持有 Activity/Dialog 导致内存泄漏)。 * 当 [allowScreenShot] 在 true/false 之间发生变化时,会自动刷新所有存活 window 的 * FLAG_SECURE 标记,从而实时启用 / 禁用截屏。 */ object SecureScreenShot { /** 受管理的 window 弱引用集合 */ private val windowRefs = mutableListOf>() /** * 运行时是否允许截屏。默认 false(即开启防截屏)。 * 赋值发生变化时,会自动刷新所有已登记 window 的截屏标记。 */ @Volatile var allowScreenShot: Boolean = false set(value) { if (field == value) return field = value refreshAll() } /** * 登记并立即为指定 [window] 应用当前的截屏配置。 * 同一个 window 不会重复登记,失效的弱引用会被顺带清理。 */ @Synchronized fun apply(window: Window?) { window ?: return var exists = false val iterator = windowRefs.iterator() while (iterator.hasNext()) { val w = iterator.next().get() if (w == null) { iterator.remove() } else if (w === window) { exists = true } } if (!exists) { windowRefs.add(WeakReference(window)) } applyFlag(window) } /** * 刷新所有存活 window 的截屏标记,并清理已失效的弱引用。 */ @Synchronized private fun refreshAll() { val iterator = windowRefs.iterator() while (iterator.hasNext()) { val w = iterator.next().get() if (w == null) { iterator.remove() } else { applyFlag(w) } } } /** * 根据当前配置为指定 [window] 应用或清除防截屏标记。 * * - DEBUG 包或 [allowScreenShot] 为 true 时:清除 FLAG_SECURE,允许截屏 * - 否则:添加 FLAG_SECURE,禁止截屏 */ private fun applyFlag(window: Window) { if (BuildConfig.DEBUG || allowScreenShot) { window.clearFlags(WindowManager.LayoutParams.FLAG_SECURE) } else { window.addFlags(WindowManager.LayoutParams.FLAG_SECURE)//禁止截屏 } } }