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)//禁止截屏
|
}
|
}
|
}
|