更新记录

0.2.0(2026-09-06)

  • 新增录屏/投屏自动遮挡,可与后台遮罩独立配置;Android 15+ 与 iOS 捕获状态变化时自动覆盖敏感内容。
  • 新增前台动态水印,支持文本、颜色、透明度、字号、旋转角度和横纵间距配置。
  • 新增多监听器 API,监听器使用独立 ID 注册和移除;保留 startPrivacyEventMonitor() / stopPrivacyEventMonitor() 兼容旧项目。
  • 新增运行诊断 API,返回系统版本、前后台状态、监听器数量、遮罩与水印可见状态、原生回调注册状态和最近错误。
  • Android 补充 DETECT_SCREEN_RECORDING 普通权限,完善多 Activity 生命周期、回调切换和 Android 10 兼容处理。
  • iOS 17+ 改用 Scene 捕获状态 Trait,低版本继续使用系统捕获状态通知;完善多 Scene/多窗口恢复逻辑。
  • 示例页新增主动保护和运行诊断区域,继续采用白色系界面,并同步完善 API、FAQ、隐私说明和测试清单。
  • Android、iOS UTS 插件模块编译通过;完整真机保护效果仍需按测试清单验证。

0.1.0(2026-08-21)

  • 修复 Android 10 上 ActivityLifecycleCallbacks$-CC 缺失导致的启动崩溃,并在 SEUIC CRUISE Ge2 真机验证前后台切换不再报错。
  • 完成 Android 后台遮罩、FLAG_SECURE 截屏保护、Android 14 截图事件和 Android 15 录屏状态检测。
  • 完成 iOS 后台遮罩、截图完成事件及录屏/投屏状态监听。
  • 新增平台能力状态 API、交互式示例页、API 文档和发布前测试清单。
  • 通过 Android、iOS UTS 插件模块与双端整项目编译,并在 iOS 模拟器完成首屏运行检查。

平台兼容性

uni-app x(4.0)

Chrome Safari Android Android插件版本 iOS iOS插件版本 鸿蒙 微信小程序
× × 5.0 0.2.0 12 0.2.0 × ×

其他

多语言 暗黑模式 宽屏模式 蒸汽模式
× × × √

APP 隐私屏幕保护

xs-privacy-screen 是面向 uni-app x App 的本地隐私屏幕保护 UTS 插件。它用一套接口封装 Android、iOS 后台任务快照遮罩、录屏自动遮挡、前台动态水印、Android FLAG_SECURE 截屏保护,以及系统支持范围内的截图、录屏/投屏和前后台事件。

当前版本:0.2.0

0.2.0 已通过 Android、iOS UTS 插件模块与整项目编译,并在 iOS 26.3 模拟器完成示例页启动、状态/诊断读取和白色系首屏检查。Android 10 真机兼容记录来自 0.1.0;新增保护效果和多窗口逻辑仍应按测试清单完成真机验收。本文不会用编译结果代替真机保护结论。

核心特性

能力 说明
双端统一接口 Android 5.0 及以上、iOS 12.0 及以上使用相同的 UTS 配置、状态和事件类型
后台隐私遮罩 App 离开前台时用原生视图覆盖任务界面快照,可配置颜色、图片和文案
Android 截屏保护 使用系统 FLAG_SECURE 保护当前及后续 Activity 的常规截图和非安全显示输出
截图事件 Android 14+ 监听系统支持的截图动作;iOS 12+ 在截图完成后收到通知
录屏状态 Android 15+ 检测本 App 是否对录屏可见;iOS 12+ 检测录屏、镜像或 AirPlay 克隆
录屏自动遮挡 可独立配置捕获遮罩;检测到录屏/投屏时覆盖前台,捕获结束后恢复
前台动态水印 原生重复绘制文字水印,可配置颜色、透明度、字号、角度和间距
能力矩阵 运行时返回真实系统能力,避免业务层根据平台名称猜测
多监听器与诊断 支持按 ID 管理多个订阅者,并查询回调、遮罩、水印与最近错误
独立控制 后台遮罩、捕获遮罩、水印、截屏保护和事件监听可分别启停
本地与离线 不读取截图内容或屏幕像素,不联网、不存储、不上传数据

适用场景

  • 金融、医疗、政务、企业内部等敏感信息页面的后台任务快照遮挡。
  • Android 登录页、身份信息页、密钥页等页面的系统截图保护。
  • 在系统允许范围内提示用户当前页面正在被录屏或投屏。
  • 记录截图、录屏状态和前后台变化,用于页面提示或业务风控联动。

插件提供的是系统公开能力的统一封装,不是 DRM 或防泄密终局方案。Root、越狱、外部相机、定制系统、调试器和其他进程内采集不在保护承诺内。

平台支持

开发环境

项目 要求
开发框架 uni-app x App
HBuilderX 5.0 及以上
uni-app x 4.0 及以上
Android Android 5.0 / API 21 及以上
iOS iOS 12.0 及以上

能力差异

能力 Android 5.0~13 Android 14 Android 15+ iOS 12+
后台任务快照遮罩 支持 支持 支持 支持
阻止常规系统截屏 FLAG_SECURE FLAG_SECURE FLAG_SECURE 不支持
截图事件 不支持 支持 支持 支持,截图完成后通知
录屏/投屏状态 不支持 不支持 支持 支持
录屏自动遮挡 不支持 不支持 支持 支持
前台动态水印 支持 支持 支持 支持
前后台事件 Activity 级 Activity 级 Activity 级 应用级
用户运行时授权 无 无 无 无

Web、小程序和 HarmonyOS 暂不支持。

安装与运行

将插件目录放入业务项目的 uni_modules/xs-privacy-screen,统一从插件根目录导入公开接口:

import {
  configureCaptureShield,
  configurePrivacyScreen,
  configurePrivacyWatermark,
  setScreenshotBlocked,
  isScreenCaptured,
  getPrivacyScreenDiagnostics,
  getPrivacyScreenStatus,
  addPrivacyEventListener,
  removePrivacyEventListener,
  startPrivacyEventMonitor,
  stopPrivacyEventMonitor
} from '@/uni_modules/xs-privacy-screen'

不要从 utssdk、平台子目录或原生类名导入内部实现,否则后续升级可能失去兼容性。

原生配置

平台 插件内配置 用途
Android android.permission.DETECT_SCREEN_CAPTURE Android 14+ 标准截图检测;普通安装时权限,不弹运行时授权框
Android android.permission.DETECT_SCREEN_RECORDING Android 15+ 录屏可见状态检测;普通安装时权限,不弹运行时授权框
Android minSdkVersion = 21 声明最低系统版本为 Android 5.0
iOS deploymentTarget = 12.0 声明最低系统版本为 iOS 12.0

iOS 不需要用户授权权限。插件也不申请存储、相机、麦克风或网络权限。

标准基座不包含当前插件的完整原生实现和 Android 权限。真机调试前应制作包含本插件的自定义基座,并在最终打包后核对配置合并结果。

快速开始

下面示例在页面进入时配置保护、启动事件监听,在页面销毁时释放当前页面持有的监听。业务项目如果需要全局监听,应把监听所有权放到应用级模块,不要让普通页面卸载时误停止全局监听。

import {
  addPrivacyEventListener,
  configureCaptureShield,
  configurePrivacyScreen,
  configurePrivacyWatermark,
  getPrivacyScreenDiagnostics,
  getPrivacyScreenStatus,
  removePrivacyEventListener,
  setScreenshotBlocked,
  CaptureShieldOptions,
  PrivacyScreenEvent,
  PrivacyScreenOptions,
  PrivacyWatermarkOptions
} from '@/uni_modules/xs-privacy-screen'

let privacyListenerId = ''

function enablePrivacyProtection() {
  configurePrivacyScreen({
    enabled: true,
    backgroundColor: '#101820',
    imagePath: null,
    message: '敏感内容已隐藏'
  } as PrivacyScreenOptions)

  configureCaptureShield({
    enabled: true,
    backgroundColor: '#183126',
    imagePath: null,
    message: '录屏期间内容已隐藏'
  } as CaptureShieldOptions)

  configurePrivacyWatermark({
    enabled: true,
    text: 'CONFIDENTIAL',
    color: '#315D48',
    opacity: 0.12,
    fontSize: 13,
    rotation: -24,
    horizontalGap: 150,
    verticalGap: 100
  } as PrivacyWatermarkOptions)

  const blockSupported = setScreenshotBlocked(true)
  if (!blockSupported) {
    console.log('当前平台不能阻止系统截图,继续使用遮罩和事件提示')
  }

  privacyListenerId = addPrivacyEventListener((event : PrivacyScreenEvent) => {
    if (event.type == 'screenshot') {
      console.log('系统截图事件', event.timestamp)
    } else if (event.type == 'recording-start') {
      console.log('检测到录屏或投屏开始')
    } else if (event.type == 'recording-stop') {
      console.log('录屏或投屏结束')
    }
  })

  const status = getPrivacyScreenStatus()
  console.log('截图保护能力', status.screenshotBlockingSupported)
  console.log('截图事件能力', status.screenshotDetectionSupported)
  console.log('录屏检测能力', status.recordingDetectionSupported)
  console.log('运行诊断', getPrivacyScreenDiagnostics())
}

function releasePageMonitor() {
  if (privacyListenerId.length > 0) {
    removePrivacyEventListener(privacyListenerId)
    privacyListenerId = ''
  }
}

关闭保护时需要分别关闭三个独立部分:

configurePrivacyScreen({
  enabled: false,
  backgroundColor: '#101820',
  imagePath: null,
  message: null
} as PrivacyScreenOptions)

setScreenshotBlocked(false)
configureCaptureShield({
  enabled: false,
  backgroundColor: '#183126',
  imagePath: null,
  message: null
} as CaptureShieldOptions)
configurePrivacyWatermark({
  enabled: false,
  text: 'CONFIDENTIAL',
  color: '#315D48',
  opacity: 0.12,
  fontSize: 13,
  rotation: -24,
  horizontalGap: 150,
  verticalGap: 100
} as PrivacyWatermarkOptions)
releasePageMonitor()

推荐接入顺序

  1. 页面或应用初始化时调用 getPrivacyScreenStatus(),按真实能力决定按钮和提示。
  2. 尽早调用 configurePrivacyScreen(),避免第一次进入后台前尚未注册生命周期。
  3. 需要录屏自动隐藏时配置 configureCaptureShield();需要水印时配置 configurePrivacyWatermark()。
  4. 仅在 Android 且业务确实需要时启用 setScreenshotBlocked(true)。
  5. 新项目用 addPrivacyEventListener() 获取监听 ID,页面销毁时只移除自己持有的监听。
  6. 退出敏感业务或账号登出时,按业务要求分别关闭各项保护。

接口总览

接口 返回值 说明
configurePrivacyScreen(options) void 配置后台遮罩、颜色、图片和文案
configureCaptureShield(options) void 配置录屏/投屏期间自动显示的前台遮罩
configurePrivacyWatermark(options) void 配置前台重复文字水印
setScreenshotBlocked(blocked) boolean Android 设置安全窗口;iOS 返回 false
isScreenCaptured() boolean 同步读取当前录屏、投屏或屏幕镜像状态
getPrivacyScreenStatus() PrivacyScreenStatus 同步读取当前配置和设备能力矩阵
getPrivacyScreenDiagnostics() PrivacyScreenDiagnostics 读取监听、原生回调、遮罩、水印和最近错误
addPrivacyEventListener(callback) string 新增独立监听并返回监听 ID
removePrivacyEventListener(id) boolean 只移除指定监听器
startPrivacyEventMonitor(callback) void 兼容 0.1.0 的单监听槽位
stopPrivacyEventMonitor() void 只停止兼容单监听槽位

后台遮罩

configurePrivacyScreen(options)

configurePrivacyScreen({
  enabled: true,
  backgroundColor: '#101820',
  imagePath: null,
  message: '内容已保护'
})
字段 类型 必填 说明
enabled boolean 是 是否在 App/Activity 进入后台时显示原生遮罩
backgroundColor string 是 推荐 #RRGGBB 或 #AARRGGBB;空值或非法颜色回退到 #101820
imagePath string \| null 是 可选本地图片;空值或解析失败时显示内置 PRIVATE 标识
message string \| null 是 遮罩主文案;空值或空白字符串显示“内容已保护”

图片路径规则:

写法 Android iOS
绝对路径 /... 本地文件 本地文件
file://... 本地文件 URI 本地文件 URL
content://... 支持;调用方需确保读取权限仍有效 不支持
相对路径或名称 Android assets 相对路径 App Bundle 图片名

插件只做本地解码,不下载网络图片。建议使用体积受控的静态图片,避免把超大原图作为遮罩素材;图片解析失败不会阻止遮罩显示。

Android 在 Activity onPause 时添加遮罩,在 onResume 时移除;iOS 在应用进入后台时为当前可见窗口添加遮罩,应用重新激活时移除。复杂导航、多 Activity、多 Scene、分屏和多窗口场景需要在目标项目中单独验证。

录屏自动遮挡

configureCaptureShield(options)

options 的字段结构与后台遮罩一致,但作用时机不同:后台遮罩保护任务快照,捕获遮罩在应用仍处于前台且系统报告录屏/投屏时覆盖内容。

configureCaptureShield({
  enabled: true,
  backgroundColor: '#183126',
  imagePath: null,
  message: '录屏期间内容已隐藏'
} as CaptureShieldOptions)

Android 需要 API 35+ 和插件自动合并的 DETECT_SCREEN_RECORDING 普通权限;iOS 17+ 使用 Scene 捕获状态 Trait,iOS 12~16 使用系统屏幕捕获状态通知。系统不支持检测时配置仍可安全保存,但不会出现自动遮挡,业务应结合 recordingDetectionSupported 提示用户。

前台动态水印

configurePrivacyWatermark(options)

字段 类型 约束与说明
enabled boolean 是否在应用窗口上方绘制水印
text string 空白时回退为 CONFIDENTIAL
color string 推荐 #RRGGBB 或 #AARRGGBB
opacity number 自动限制到 0~1
fontSize number 自动限制到 10~48
rotation number 自动限制到 -60~60 度
horizontalGap number 自动限制到 80~360
verticalGap number 自动限制到 60~300

水印为不拦截触摸的本地原生视图,不读取底层页面、截图或屏幕像素。它只能增加外传识别成本,不等于数字取证、不可移除水印或内容溯源。

Android 截屏保护

setScreenshotBlocked(blocked)

const supported = setScreenshotBlocked(true)
平台 返回值 行为
Android true 对当前及后续 Activity 设置或清除 WindowManager.LayoutParams.FLAG_SECURE
iOS false 不修改系统截图行为

返回值表示平台是否接受这项配置,不表示用户已经截图,也不证明所有外部采集方式都被阻止。

开启 FLAG_SECURE 后,常规系统截图通常会被阻止或显示空白,因此验证 Android 截图事件时应先关闭截屏保护,避免“截图本身未发生”被误判为监听失效。

捕获状态

isScreenCaptured()

const captured = isScreenCaptured()
平台 行为
Android 15+ 返回本 App 当前是否对系统录屏可见
Android 14 及以下 系统没有当前实现使用的等价公开能力,返回 false
iOS 12+ 返回主屏幕是否处于录屏、屏幕镜像或 AirPlay 克隆状态

false 可能表示“当前没有捕获”,也可能表示“当前系统版本不支持检测”。业务判断必须同时查看 recordingDetectionSupported。

状态查询

getPrivacyScreenStatus()

同步返回当前配置与运行设备能力,不申请权限,也不启动监听。

字段 类型 说明
platform string android 或 ios
privacyScreenEnabled boolean 当前后台遮罩配置是否开启
screenshotBlocked boolean 当前是否已请求 Android 截屏保护;iOS 固定为 false
screenshotBlockingSupported boolean 是否支持系统级截屏保护
screenshotDetectionSupported boolean 当前系统版本是否支持截图事件
recordingDetectionSupported boolean 当前系统版本是否支持录屏/投屏状态检测
screenCaptured boolean 当前是否检测到录屏、投屏或屏幕镜像

能力字段表示源码在当前系统版本上存在对应路径,不等同于该设备已经完成真机验收。

getPrivacyScreenDiagnostics()

诊断接口用于接入排错,不启动监听,也不读取屏幕内容。它返回平台与系统版本、应用前后台状态、监听器数量、两类遮罩与水印的配置/可见状态、截图/录屏原生回调是否已注册,以及最近一次原生注册错误。lastError 为 null 表示当前没有已知错误,不代表设备行为已经通过真机验收。

事件监听

startPrivacyEventMonitor(callback)

这是为 0.1.0 保留的兼容 API。重复调用只替换 legacy-listener 兼容槽位,不会移除通过新 API 注册的其他监听器。

startPrivacyEventMonitor((event : PrivacyScreenEvent) => {
  console.log(event.type, event.timestamp)
})
事件 Android iOS 说明
screenshot Android 14+ iOS 12+ Android 为系统支持的截图动作;iOS 为截图完成通知
recording-start Android 15+ iOS 12+ App 内容开始被系统录屏、投屏或镜像捕获
recording-stop Android 15+ iOS 12+ 捕获状态结束
background Android 5.0+ iOS 12+ Android Activity 暂停;iOS 应用进入后台
foreground Android 5.0+ iOS 12+ Android Activity 恢复;iOS 应用重新激活

事件结构:

字段 类型 说明
type PrivacyEventType 五种事件之一
timestamp number 事件产生时的 Unix 毫秒时间戳

Android 14 标准截图检测主要覆盖系统支持的截图入口,不承诺 ADB、测试框架或定制厂商路径。启用标准截图检测后,系统可能向用户显示隐私提示,业务页面应提前说明用途。

iOS 在开始监听时,如果屏幕已经处于被捕获状态,当前实现会立即发送一次 recording-start,用于同步初始状态。

addPrivacyEventListener(callback) / removePrivacyEventListener(id)

新项目推荐使用多监听器 API:每次添加返回一个不透明字符串 ID,移除时只影响对应订阅者。

const listenerId = addPrivacyEventListener((event : PrivacyScreenEvent) => {
  console.log(event.type, event.timestamp)
})

const removed = removePrivacyEventListener(listenerId)

多个监听器共享底层系统回调。Android 在最后一个事件监听器移除后注销截图回调;若录屏自动遮挡仍开启,录屏回调会继续保留,这是保护功能的正常行为。

stopPrivacyEventMonitor()

只停止 startPrivacyEventMonitor() 创建的兼容监听槽位,不影响 addPrivacyEventListener() 创建的订阅。没有其他监听器且录屏自动遮挡关闭时,Android 会释放对应平台捕获回调;iOS 系统通知观察者保留供后续复用,但不会继续向已移除的业务回调发送事件。

该调用不会:

  • 关闭后台隐私遮罩。
  • 清除 Android FLAG_SECURE。
  • 修改之前调用 configurePrivacyScreen() 保存的配置。
  • 关闭录屏自动遮挡或动态水印。

典型调用流程

仅保护后台任务快照

页面初始化 -> configurePrivacyScreen(enabled = true)
离开前台 -> 原生遮罩覆盖窗口 -> 系统生成任务快照
返回前台 -> 原生遮罩移除

Android 截屏保护

进入敏感业务 -> setScreenshotBlocked(true)
离开敏感业务 -> setScreenshotBlocked(false)

事件驱动提示

读取能力 -> 支持时启动监听 -> 收到事件 -> 更新页面提示
                                  |
页面/业务结束 --------------------> 停止监听

页面与生命周期建议

  • 尽早配置后台遮罩,不要等到 App 已进入后台才首次调用。
  • 页面级监听应在页面卸载时停止;全局监听应由唯一的应用级模块持有。
  • Android 会聚合已启动 Activity 后再发出应用级 background/foreground;多窗口和厂商系统仍需真机验证。
  • 事件回调中只更新轻量状态;需要网络上报时由业务层做节流、隐私告知和失败重试。
  • screenCaptured 为 true 时可隐藏敏感区域、暂停展示或提醒用户;开启捕获遮罩后插件会自动覆盖整个应用窗口。
  • 账号退出、敏感流程结束或插件不再使用时,显式恢复业务期望的遮罩和安全窗口状态。

常见问题

为什么 iOS 开启阻止截屏后返回 false?

iOS 没有面向第三方 App 的公开系统截图禁用 API。插件不会通过私有 API 或伪造成功结果,iOS 可用的是后台遮罩、截图完成通知和录屏/镜像状态检测。

为什么 Android 设备没有截图事件?

先查看 screenshotDetectionSupported。该事件要求 Android 14 / API 34 及以上;Android 13 及以下返回不支持。测试时还应先关闭 FLAG_SECURE,并使用设备的标准系统截图入口。

为什么 isScreenCaptured() 一直返回 false?

Android 只有 15 / API 35 及以上支持当前实现使用的录屏可见状态 API。较低版本的 false 表示无法检测,不应解释为安全证明;同时检查 recordingDetectionSupported。

为什么停止监听后后台遮罩仍然存在?

五组能力相互独立。停止监听只释放对应事件回调;后台遮罩、捕获遮罩和水印需分别重新配置为 enabled: false,关闭 Android 截屏保护要调用 setScreenshotBlocked(false)。

插件能拿到用户的截图或录屏文件吗?

不能。事件只包含类型和时间戳,插件不读取截图、录屏、屏幕像素或业务内容。

当前限制

  • 只面向 uni-app x App-Android、App-iOS。
  • iOS 不支持系统截图阻止,截图事件发生在截图完成后。
  • Android 14 以下没有截图事件,Android 15 以下没有录屏状态检测。
  • Android 前后台事件会聚合已启动 Activity;复杂导航、多窗口和厂商行为仍需真机验证。
  • 动态水印是视觉提示层,不提供不可删除、身份绑定或服务端溯源保证。
  • 不提供事件持久化、网络上报、截图内容、录屏文件或审计后台。
  • 不承诺防 Root、越狱、外部相机、定制 ROM 或其他非标准采集方式。
  • 最低版本、多厂商、多窗口和完整系统事件仍需在业务目标设备上验证。

验证建议

正式使用前至少完成:

  1. Android API 21、34、35 与 iOS 12、当前 iOS 的版本边界验证。
  2. 开启和关闭后台遮罩后检查系统任务界面快照。
  3. Android 开启、关闭 FLAG_SECURE 后分别测试截图与投屏。
  4. Android 14 关闭 FLAG_SECURE 后测试标准系统截图事件。
  5. Android 15、iOS 真机测试录屏开始/结束和投屏、镜像状态。
  6. 连续前后台切换、连续启停监听、页面跳转和多窗口稳定性。
  7. 自定义图片、非法路径、透明颜色和长文案的显示边界。

隐私与合规

插件本身不联网只代表插件实现不发送数据,不代表集成它的业务应用不会记录或上传事件。业务方如需把截图或录屏事件用于风控、审计或账号处置,应在隐私政策和产品界面中说明用途、保存期限、访问范围与申诉机制,并遵守适用法律和平台规则。

更多文档

  • docs/API.md:完整类型、接口、平台差异、事件顺序和生命周期说明。
  • docs/PLATFORM_AND_PRIVACY.md:保护模型、权限、数据流、产品提示和发布检查清单。
  • docs/FAQ.md:接入、测试和常见故障排查。
  • docs/TESTING.md:双端真机测试矩阵和设备记录模板。
  • docs/VERIFICATION.md:当前已经完成与尚未完成的验证证据。

官方参考

隐私、权限声明

1. 本插件需要申请的系统权限列表:

Android 自动合并 android.permission.DETECT_SCREEN_CAPTURE 与 android.permission.DETECT_SCREEN_RECORDING(普通安装时权限,分别用于 Android 14+ 截图事件与 Android 15+ 录屏检测);iOS 无需申请用户授权权限

2. 本插件采集的数据、发送的服务器地址、以及数据用途说明:

仅在设备本地读取截屏、录屏和应用前后台状态,不采集截图内容,不存储、不上传任何数据

3. 本插件是否包含广告,如包含需详细说明广告表达方式、展示频率:

无

暂无用户评论。