前言

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

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

一、setWindowPrivacyMode API 详解

1.1 方法签名

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

1.2 调用示例

// 开启隐私模式
await this.mainWindow.setWindowPrivacyMode(true);

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

1.3 系统行为

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

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

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

二、applyPrivacyMode 实现

2.1 完整代码

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 方法

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 中声明:

{
  "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 设计对比

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

5.3 哪个设计更好

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

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

六、隐私模式的开关时机

6.1 开启时机

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

6.2 关闭时机

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 状态不同步的处理

// 理想方案:根据 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 验证命令

# 查看日志确认隐私模式状态
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 层、原生层、系统层三层状态保持一致

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

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


相关资源:

请添加图片描述

Logo

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

更多推荐