| New file |
| | |
| | | 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<WeakReference<Window>>() |
| | | |
| | | /** |
| | | * 运行时是否允许截屏。默认 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)//禁止截屏 |
| | | } |
| | | } |
| | | } |