Flutter 鸿蒙 screen_security 1.1.2 使用实战:为敏感页面开启防截图
Flutter 鸿蒙 screen_security 1.1.2 使用实战:为敏感页面开启防截图
本文用 screen_security 1.1.2 完成一个敏感信息页:进入页面后可开启窗口隐私模式,系统截图中的应用区域会被遮黑;关闭后恢复正常。依赖、权限、调用时机和异常处理均以 HarmonyOS 真机结果为准。
三方库仓库: https://atomgit.com/oh-flutter/screen_security
OHOS 适配分支:
ohos-adaptation本文锁定版本:
477879990d220cb517986f85a0f8e9e7fd985399完整 Demo: screen_security/example(受测提交)
一、最终真机效果

图 1:华为畅享 90 Pro Max / HarmonyOS 7.0.0.105 上,隐私模式关闭时系统能正常抓取 Flutter 页面。

图 2:调用 enable() 后,系统抓图中的应用窗口被遮黑,状态栏仍属于系统窗口。

图 3:同一窗口的 isPrivacyMode 完成 false -> true -> false 回环,证明不是只修改了按钮文字。
| 验证点 | 实测结果 |
|---|---|
| 依赖与 HAP | 固定受测 SHA,构建、签名、安装和启动通过 |
| 开启防护 | 页面抓图变黑,窗口属性变为 true |
| 关闭防护 | 窗口属性恢复 false,页面可再次抓取 |
| 自动化 | flutter analyze 无问题,26 项 Dart 测试通过 |
| 边界 | 本次没有单独保存录屏文件,不把录屏列为真机实测通过 |
二、什么时候应该用它
我把它用于证件、支付确认、恢复码和一次性口令这类“短时间展示敏感信息”的页面。应用进入敏感流程时开启,离开流程前关闭。它修改的是当前应用窗口的系统隐私属性,不是给页面叠一层黑色 Widget,因此能影响系统屏幕捕获结果。
它也不是完整的数据防泄漏方案。拍照、另一台设备录像、无障碍读取、日志泄漏和业务接口越权都不在这个插件的能力范围内。页面还应继续做数据最小化、超时隐藏和后端权限控制。

图 4:页面调用 ScreenSecurity,经 MethodChannel 到 OHOS 当前窗口隐私模式。
三、环境与依赖
| 组件 | 实测版本 |
|---|---|
| Flutter OH | 3.41.10-ohos-1.0.1 |
| Dart | 3.11.5 |
| DevEco Studio | 26.0.0 Release |
| HarmonyOS SDK | API 26 |
| 真机 | CHZ-AL00 / HarmonyOS 7.0.0.105 |
版本号最大的 3.44.9+ohos-0.0.1-canary1 是预览版,本文使用完成回归的最新正式稳定标签。当前库没有 OHOS 稳定 TAG,所以依赖必须固定 commit:
dependencies:
screen_security:
git:
url: https://atomgit.com/oh-flutter/screen_security.git
ref: 477879990d220cb517986f85a0f8e9e7fd985399
flutter pub get
检查 pubspec.lock 的 url 与 resolved-ref,不要只看 pub get 成功。历史适配分支名就是 ohos-adaptation,不是统一规范实施后的 feat/ohos_...。
四、鸿蒙宿主权限
插件 HAR 声明了窗口隐私权限,最终 HAP 中必须合并出:
"requestPermissions": [
{
"name": "ohos.permission.PRIVACY_WINDOW"
}
]

图 5:从最终 HAP 检查到 PRIVACY_WINDOW,比只看源码声明更可靠。
不需要截图、相册或存储权限。若业务宿主重写了模块配置或打包流程,发布前仍应检查最终 HAP,而不是假定 HAR 权限一定合并成功。
五、核心 API 与页面状态
公共 API 只有开启和关闭:
import 'package:screen_security/screen_security.dart';
final ScreenSecurity screenSecurity = ScreenSecurity();
Future<void> protect() => screenSecurity.enable();
Future<void> unprotect() => screenSecurity.disable();
实际页面应防止重复点击,并只在原生调用成功后更新 UI:
class SensitivePageState extends State<SensitivePage> {
final ScreenSecurity _security = ScreenSecurity();
bool _enabled = false;
bool _busy = false;
String? _error;
Future<void> _setProtected(bool value) async {
if (_busy) return;
setState(() {
_busy = true;
_error = null;
});
try {
if (value) {
await _security.enable();
} else {
await _security.disable();
}
if (mounted) setState(() => _enabled = value);
} catch (error) {
if (mounted) setState(() => _error = error.toString());
} finally {
if (mounted) setState(() => _busy = false);
}
}
}
插件没有需要调用方释放的订阅,但窗口状态必须由业务恢复。不要只在无法 await 的 dispose() 里调用 disable();更稳妥的做法是在关闭按钮、路由返回或敏感流程完成时,先等待 disable() 成功,再离开页面。应用异常退出时系统会销毁窗口,但正常导航仍应明确收尾。

图 6:插件取得当前主窗口并调用 setWindowPrivacyMode(enabled),使用方无需复制 ArkTS 实现。
六、验证步骤
flutter analyze
flutter test
flutter build hap --debug --no-codesign

图 7:静态检查和 26 项 Dart 测试通过。

图 8:OHOS 示例成功产出无签名 HAP。
真机验收不能只看页面显示“ON”。我先在关闭状态截图并查询窗口属性,再调用 enable() 重复两项操作,最后调用 disable() 回读。只有抓图内容和系统属性都改变,才能确认插件真正生效。
七、常见问题
Q1:按钮显示开启,截图仍能看到内容
- 现象: Flutter 状态已更新,但系统截图未遮黑。
- 原因: 页面在原生 Future 完成前就更新,或最终 HAP 没有合并权限。
- 解决方法:
await enable()后再更新状态,并检查 HAP 内PRIVACY_WINDOW。 - 验证结果: 真机系统属性和抓图同步变化。
Q2:离开敏感页后整个应用仍无法截图
- 现象: 普通页面也被遮黑。
- 原因: 隐私模式是窗口状态,路由离开前没有调用
disable()。 - 解决方法: 将恢复动作放在可等待的退出流程,并处理失败后再决定是否跳转。
- 验证结果: 本次回环最终
isPrivacyMode=false。
Q3:为什么状态栏没有变黑
- 现象: 应用内容被遮黑,状态栏仍可见。
- 原因: 插件控制当前应用窗口,状态栏是系统窗口。
- 解决方法: 按应用内容是否隐藏判断,不把系统 UI 纳入插件效果。
- 验证结果: 图 2 与系统窗口属性一致。
八、适用边界与总结
screen_security 适合在前台敏感页面临时限制常规系统截图。接入关键是固定受测 SHA、确认最终 HAP 权限、等待异步开关完成,并在离开流程前恢复窗口。本文已验证截图遮黑和状态回环,未单独验证录屏,也不把它描述成完整防泄漏方案。
九、参考链接
欢迎加入CPF-Flutter 鸿蒙社区:https://atomgit.com/CPF-Flutter
更多推荐



所有评论(0)