ArturoYi
安卓代码加固

安卓代码加固(9):防录屏

来电页、落地页、全屏广告使用 FLAG_SECURE。截屏与录屏得到黑屏,无需额外权限。

代码放入加密 dex 之后,屏幕上的来电页、落地页和全屏广告仍能被截屏或录屏。工程用系统窗口标志 FLAG_SECURE 处理这一层:截屏失败或得到黑图,录屏画面为全黑,多任务缩略图也会被抹掉。

这不是 DEX 加固,是窗口级隐私保护。不需要 Manifest 权限,也不影响点击。

通过 SDK 指令调用

接入文档约定 invoke(13, activity)。实现位于加密 dex 的 applyScreenProtection:

hidden-landing-page/src/main/java/com/example/minidex/hidden/HiddenLandingPageController.kt
fun applyScreenProtection(activity: Activity, enable: Boolean) {
    if (enable) {
        activity.window.addFlags(WindowManager.LayoutParams.FLAG_SECURE)
    } else {
        activity.window.clearFlags(WindowManager.LayoutParams.FLAG_SECURE)
    }
}

关键点是:未 init 也会加标志。HiddenSdk.fallback 在 native 尚未 ready 时会自行操作 window,避免密钥错误后来电页反而能被截屏。

hidden-sdk/src/main/java/com/example/minidex/sdk/HiddenSdk.kt
13 -> {
    val activity = a as? Activity
    if (activity != null) {
        val enable = when (b) {
            is Boolean -> b
            else -> true
        }
        if (enable) {
            activity.window.addFlags(WindowManager.LayoutParams.FLAG_SECURE)
        } else {
            activity.window.clearFlags(WindowManager.LayoutParams.FLAG_SECURE)
        }
    }
    null
}

Demo 宿主在来电路由页和落地页的 onCreate 里调用 HiddenSdk.invoke(13, this)(或 HostBridge.protect)。

保护全屏广告

:ads 不走 HiddenSdk,自己按 Activity 类名判断:

ads/src/main/java/com/example/minidex/ads/internal/AdScreenProtection.kt
fun isAdRelatedActivity(className: String): Boolean {
    return className.contains("com.google.android.gms.ads") ||
        className.contains("AdActivity") ||
        className.contains("AdLandingActivity") ||
        className.contains("com.google.android.libraries.ads")
}

fun applyScreenProtection(activity: Activity, enable: Boolean = true) {
    if (enable) {
        activity.window.addFlags(WindowManager.LayoutParams.FLAG_SECURE)
    } else {
        activity.window.clearFlags(WindowManager.LayoutParams.FLAG_SECURE)
    }
}

init(application) 注册生命周期回调,在 created、started、resumed 时重复施加。AdMob 全屏页由 SDK 自行启动,宿主清单里没有类名,只能按包名匹配。

可用 AdConfig.enableScreenProtection 关掉。落地页 AdLandingActivity 也会再调用一次 AdSdk.applyScreenProtection(this)。

FLAG_SECURE 阻止的是系统截屏、录屏和 Recents 缩略图。它不能阻止 HDMI、定制 ROM 或已 root 设备上的帧缓冲抓取。

对照两套入口

场景入口未初始化
来电 / 落地页HiddenSdk.invoke(13, activity)fallback 仍加标志
全屏广告AdScreenProtection 生命周期与 HiddenSdk 无关

两套实现都是同一条系统 API,故意不抽成公共模块,避免广告模块 compile 依赖 hidden-sdk。

下一步

Copyright © 2026