Flutter三方库适配OpenHarmony【secure_application】— setWindowPrivacyMode 隐私模式实现

前言

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net

上一篇我们拿到了 Window 对象,这一篇讲怎么用它。setWindowPrivacyMode 是 OpenHarmony 提供的系统级隐私保护 API,开启后截屏、录屏都会变成黑屏,应用切换器中也看不到内容。这和 Android 的 FLAG_SECURE 效果一样,但 API 设计完全不同。

一、setWindowPrivacyMode API 详解

1.1 方法签名

typescript 复制代码
setWindowPrivacyMode(isPrivacy: boolean): Promise<void>
参数 类型 说明
isPrivacy boolean true=开启隐私模式,false=关闭
返回值 Promise 异步操作,成功时 resolve,失败时 reject

1.2 调用示例

typescript 复制代码
// 开启隐私模式
await this.mainWindow.setWindowPrivacyMode(true);

// 关闭隐私模式
await this.mainWindow.setWindowPrivacyMode(false);

1.3 系统行为

开启隐私模式后,系统会做以下处理:

行为 隐私模式关闭 隐私模式开启
用户截屏 正常截取内容 截取到黑屏
系统录屏 正常录制内容 录制到黑屏
应用切换器 显示App缩略图 显示黑屏/空白
投屏 正常投屏 投屏黑屏
辅助功能 可读取 部分受限

📌 这是系统级保护,不是应用层面的模拟。即使用 root 权限的工具也无法绕过。

二、applyPrivacyMode 实现

2.1 完整代码

typescript 复制代码
private applyPrivacyMode(win: window.Window, isPrivacy: boolean): void {
  try {
    win.setWindowPrivacyMode(isPrivacy).then(() => {
      Log.i(TAG, "Window privacy mode set to: " + isPrivacy);
    }).catch((err: BusinessError) => {
      Log.e(TAG, "Failed to set window privacy mode: " + JSON.stringify(err));
    });
  } catch (err) {
    Log.e(TAG, "Exception applying privacy mode: " + JSON.stringify(err));
  }
}

2.2 错误处理层次

复制代码
applyPrivacyMode(win, true)
    │
    ├── try-catch 外层
    │   └── 捕获同步异常(如 win 对象无效)
    │
    └── Promise.then/catch 内层
        ├── then → 成功日志
        └── catch → 异步错误日志

2.3 常见错误码

错误码 含义 处理方式
1300002 窗口状态异常 重新获取窗口
1300003 系统服务异常 延迟重试
1300004 权限不足 检查 PRIVACY_WINDOW 权限

三、setPrivacyMode 的完整调用链

3.1 从 Dart 到原生

复制代码
Dart: controller.secure()
    │
    ▼
Dart: SecureApplicationNative.secure()
    │
    ▼
Dart: _channel.invokeMethod('secure')
    │
    ▼ MethodChannel
    │
Native: onMethodCall(call, result)
    │ case "secure"
    ▼
Native: this.secured = true
Native: this.setPrivacyMode(true)
    │
    ▼
Native: this.applyPrivacyMode(win, true)
    │
    ▼
Native: win.setWindowPrivacyMode(true)
    │
    ▼
系统:开启窗口隐私保护

3.2 setPrivacyMode 方法

typescript 复制代码
private setPrivacyMode(isPrivacy: boolean): void {
  if (this.mainWindow == null) {
    // 窗口还没获取到,尝试重新获取
    if (this.context != null) {
      try {
        window.getLastWindow(this.context).then((win: window.Window) => {
          this.mainWindow = win;
          this.applyPrivacyMode(win, isPrivacy);
        }).catch((err: BusinessError) => {
          Log.e(TAG, "Failed to get window for privacy mode: " + JSON.stringify(err));
        });
      } catch (err) {
        Log.e(TAG, "Exception setting privacy mode: " + JSON.stringify(err));
      }
    }
    return;
  }
  this.applyPrivacyMode(this.mainWindow, isPrivacy);
}

3.3 两条执行路径

路径 条件 行为
快速路径 mainWindow != null 直接调用 applyPrivacyMode
慢速路径 mainWindow == null 先获取窗口,再调用 applyPrivacyMode

四、ohos.permission.PRIVACY_WINDOW 权限

4.1 权限说明

属性
权限名 ohos.permission.PRIVACY_WINDOW
类型 system_basic
是否必须 API 20 中可选
授权方式 静态声明

4.2 声明方式

在宿主应用的 module.json5 中声明:

json5 复制代码
{
  "module": {
    "requestPermissions": [
      {
        "name": "ohos.permission.PRIVACY_WINDOW"
      }
    ]
  }
}

4.3 插件 vs 宿主应用的权限声明

位置 文件 是否生效
插件的 module.json5 ohos/src/main/module.json5 ⚠️ HAR 模块的权限声明可能不生效
宿主应用的 module.json5 entry/src/main/module.json5 ✅ 生效

💡 重要 :权限应该在宿主应用中声明,而不是在插件中。插件的 README 应该告知开发者需要声明哪些权限。

4.4 不声明权限会怎样

在 API 20 的实际测试中,不声明 PRIVACY_WINDOW 权限也能正常调用 setWindowPrivacyMode。但这可能在未来的 API 版本中改变,所以建议还是声明。

五、隐私模式与 Android FLAG_SECURE 的对比

5.1 功能对比

功能 Android FLAG_SECURE OHOS setWindowPrivacyMode
截屏防护
录屏防护
应用切换器 ✅ 自动 ✅ 自动
API 类型 同步 异步
粒度 窗口级 窗口级
权限要求 可选

5.2 API 设计对比

kotlin 复制代码
// Android:同步,标志位操作
activity.window.addFlags(LayoutParams.FLAG_SECURE)    // 开启
activity.window.clearFlags(LayoutParams.FLAG_SECURE)  // 关闭
typescript 复制代码
// OpenHarmony:异步,布尔值操作
await win.setWindowPrivacyMode(true)   // 开启
await win.setWindowPrivacyMode(false)  // 关闭

5.3 哪个设计更好

维度 Android OpenHarmony
易用性 ✅ 更简单 需要处理异步
错误处理 ❌ 无法知道是否成功 ✅ Promise 可以捕获错误
灵活性 标志位可以组合 单一布尔值
语义清晰度 FLAG_SECURE 含义模糊 ✅ PrivacyMode 含义明确

📌 OpenHarmony 的 API 设计更现代------异步操作、明确的错误处理、语义化的方法名。虽然用起来复杂一点,但更健壮。

六、隐私模式的开关时机

6.1 开启时机

typescript 复制代码
case "secure":
  this.secured = true;
  this.setPrivacyMode(true);  // Dart 层调用 secure() 时开启
  result.success(true);
  break;

6.2 关闭时机

typescript 复制代码
case "open":
  this.secured = false;
  this.setPrivacyMode(false);  // Dart 层调用 open() 时关闭
  result.success(true);
  break;

6.3 状态同步

复制代码
Dart 层状态          原生层状态           系统状态
secured=true    →   this.secured=true  →  PrivacyMode=true
secured=false   →   this.secured=false →  PrivacyMode=false

三层状态必须保持同步。如果出现不同步(比如原生端 setPrivacyMode 失败),用户可能以为保护已开启但实际上没有。

6.4 状态不同步的处理

typescript 复制代码
// 理想方案:根据 setWindowPrivacyMode 的结果更新状态
win.setWindowPrivacyMode(isPrivacy).then(() => {
  // 成功,状态已同步
  Log.i(TAG, "Privacy mode synced: " + isPrivacy);
}).catch((err) => {
  // 失败,通知 Dart 层
  Log.e(TAG, "Privacy mode failed, notifying Dart");
  // 可以通过 channel 通知 Dart 层保护未生效
});

当前实现选择了静默失败,但如果安全要求很高,可以在失败时通知 Dart 层。

七、实际测试验证

7.1 测试步骤

  1. 运行示例应用到 OpenHarmony 设备
  2. 点击 "secure" 按钮开启保护
  3. 尝试截屏 → 应该得到黑屏
  4. 按 Home 键查看应用切换器 → 应该看不到内容
  5. 点击 "open" 按钮关闭保护
  6. 再次截屏 → 应该正常截取

7.2 验证命令

bash 复制代码
# 查看日志确认隐私模式状态
hdc hilog | grep "Window privacy mode"

# 预期输出
# SecureApplicationPlugin: Window privacy mode set to: true
# SecureApplicationPlugin: Window privacy mode set to: false

7.3 常见测试问题

问题 原因 解决
截屏仍然正常 setWindowPrivacyMode 调用失败 检查日志中的错误信息
应用切换器仍显示内容 隐私模式未生效 确认窗口获取成功
调用报错 API 版本不支持 确认 SDK 版本 >= API 20

总结

本文详细讲解了 setWindowPrivacyMode 的实现:

  1. API 特性:异步调用,布尔值控制,系统级保护
  2. 错误处理:双重 try-catch + Promise.catch
  3. 权限要求:PRIVACY_WINDOW 在 API 20 中可选,建议在宿主应用声明
  4. 与 FLAG_SECURE 对比:功能等价,API 设计更现代
  5. 状态同步:Dart 层、原生层、系统层三层状态保持一致

下一篇我们讲窗口事件监听------如何检测用户切换到其他应用。

如果这篇文章对你有帮助,欢迎点赞👍、收藏⭐、关注🔔,你的支持是我持续创作的动力!


相关资源:

相关推荐
tIjJrDKv2 小时前
自动驾驶汽车轨迹规划:人工势场法与MPC联合仿真探索
harmonyos
哈__2 小时前
基础入门 Flutter for OpenHarmony:image_cropper 图片裁剪详解
flutter
哈__2 小时前
基础入门 Flutter for OpenHarmony:flutter_contacts 通讯录管理详解
flutter
星空22232 小时前
【HarmonyOS】day29:React Native开发实践:实现Popover组件内容自适应
react native·华为·harmonyos
_waylau2 小时前
跟老卫学仓颉编程语言开发:浮点类型
人工智能·华为·harmonyos·鸿蒙·鸿蒙系统·仓颉
星空22233 小时前
【HarmonyOS】React Native of HarmonyOS实战:手势冲突解决方案
react native·华为·harmonyos
键盘鼓手苏苏3 小时前
Flutter for OpenHarmony:cider 自动化版本管理与变更日志生成器(发布流程标准化的瑞士军刀) 深度解析与鸿蒙适配指南
运维·开发语言·flutter·华为·rust·自动化·harmonyos
无巧不成书02183 小时前
【RN鸿蒙教学|第11课时】应用打包与部署实战:完成从开发到落地的全闭环
react native·华为·开源·交互·harmonyos
前端不太难3 小时前
鸿蒙如何重新定义“超级 App”
华为·状态模式·harmonyos