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 OH3.41.10-ohos-1.0.1
Dart3.11.5
DevEco Studio26.0.0 Release
HarmonyOS SDKAPI 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.lockurlresolved-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);
    }
  }
}

插件没有需要调用方释放的订阅,但窗口状态必须由业务恢复。不要只在无法 awaitdispose() 里调用 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

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐