Flutter三方库适配OpenHarmony【secure_application】— iOS 端原生模糊遮罩实现分析
欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.netiOS 没有 Android 那样的 FLAG_SECURE 机制,无法从系统层面阻止截屏。所以 iOS 端走了一条完全不同的路——在应用即将进入后台时,用原生 UIVisualEffectView 创建一个模糊视图覆盖在整个 App 上方,让应用切换器中看到的是模糊画面。这种方案和 Op
前言
欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net
iOS 没有 Android 那样的 FLAG_SECURE 机制,无法从系统层面阻止截屏。所以 iOS 端走了一条完全不同的路——在应用即将进入后台时,用原生 UIVisualEffectView 创建一个模糊视图覆盖在整个 App 上方,让应用切换器中看到的是模糊画面。
这种方案和 OpenHarmony 的 setWindowPrivacyMode 有本质区别,但理解它有助于我们全面认识各平台的隐私保护策略。
一、iOS 的隐私保护机制
1.1 iOS 应用切换器的行为
iOS 在用户按 Home 键或上滑时,会对当前 App 做一次快照(snapshot),这个快照会显示在应用切换器中。
用户按 Home 键
│
├── iOS 系统对当前界面截图
├── 截图保存为应用切换器缩略图
└── App 进入后台
1.2 为什么 iOS 不能用 FLAG_SECURE
| 特性 | Android | iOS |
|---|---|---|
| 系统级截屏防护 | ✅ FLAG_SECURE | ❌ 不支持 |
| 应用切换器快照控制 | 自动(FLAG_SECURE) | 需要手动遮挡 |
| 第三方截屏工具防护 | ✅ | ❌ |
| 录屏防护 | ✅ | ❌ |
iOS 的设计哲学是用户拥有设备的完全控制权,不允许 App 阻止用户截屏。所以只能用"遮挡"的方式来保护内容。
1.3 iOS 端的保护策略
App 即将进入非活跃状态 (applicationWillResignActive)
│
└── 添加 UIVisualEffectView(模糊视图)到 Window 上方
│
App 回到活跃状态 (applicationDidBecomeActive)
│
└── 延迟 500ms 后移除 UIVisualEffectView
二、UIVisualEffectView 模糊视图
2.1 创建模糊视图
let blurEffect = UIBlurEffect(style: .light)
let blurView = UIVisualEffectView(effect: blurEffect)
blurView.frame = UIScreen.main.bounds
blurView.tag = 12345 // 用于后续查找和移除
2.2 模糊样式选择
| 样式 | 效果 | 适用场景 |
|---|---|---|
.light |
浅色模糊 | 浅色主题 App |
.dark |
深色模糊 | 深色主题 App |
.extraLight |
更浅的模糊 | 需要更亮的遮罩 |
.regular |
标准模糊 | 通用场景 |
.prominent |
突出模糊 | 需要更强遮挡 |
secure_application 使用的是 .light 样式,在大多数场景下效果不错。
2.3 添加到 Window
// 获取当前 Window
if let window = UIApplication.shared.windows.first {
window.addSubview(blurView)
}
添加到 Window 的最顶层,确保覆盖所有内容,包括 Flutter 的渲染视图。
2.4 移除模糊视图
if let window = UIApplication.shared.windows.first {
window.viewWithTag(12345)?.removeFromSuperview()
}
通过 tag 找到之前添加的模糊视图并移除。
三、应用生命周期处理
3.1 Swift 端的生命周期监听
class SecureApplicationPlugin: NSObject, FlutterPlugin {
var secured = false
var channel: FlutterMethodChannel?
public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
switch call.method {
case "secure":
secured = true
result(true)
case "open":
secured = false
removeBlurView()
result(true)
case "lock":
if secured { addBlurView() }
result(true)
case "unlock":
removeBlurView()
result(true)
case "opacity":
// 处理透明度参数
result(true)
default:
result(FlutterMethodNotImplemented)
}
}
}
3.2 NotificationCenter 事件注册
NotificationCenter.default.addObserver(
self,
selector: #selector(applicationWillResignActive),
name: UIApplication.willResignActiveNotification,
object: nil
)
NotificationCenter.default.addObserver(
self,
selector: #selector(applicationDidBecomeActive),
name: UIApplication.didBecomeActiveNotification,
object: nil
)
3.3 事件处理
@objc func applicationWillResignActive() {
if secured {
addBlurView()
channel?.invokeMethod("lock", arguments: nil)
}
}
@objc func applicationDidBecomeActive() {
// 延迟移除,等待 Flutter 渲染完成
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
self.removeBlurView()
}
}
3.4 延迟移除的必要性
用户切回 App
│
├── t=0ms: iOS 调用 applicationDidBecomeActive
├── t=0ms: Flutter 开始渲染(SecureGate 模糊遮罩还没显示)
├── t=100ms: Flutter 渲染完成,SecureGate 遮罩已显示
├── t=500ms: iOS 移除原生模糊视图
└── 用户看到的始终是模糊画面 ✅
如果不延迟移除:
用户切回 App
│
├── t=0ms: iOS 立即移除原生模糊视图
├── t=0ms: Flutter 还没渲染完成
├── t=0-100ms: 用户短暂看到未保护的内容 ❌
└── t=100ms: Flutter SecureGate 遮罩才显示
📌 这就是 nativeRemoveDelay 参数的由来。Dart 层默认设置为 1000ms,iOS 原生端默认 500ms,取较大值来确保安全。
四、iOS 与 Android 的对比
4.1 保护机制对比
| 维度 | Android | iOS |
|---|---|---|
| 截屏防护 | ✅ 系统级(FLAG_SECURE) | ❌ 无法阻止 |
| 录屏防护 | ✅ 系统级 | ❌ 无法阻止 |
| 应用切换器 | 自动隐藏 | 手动添加模糊视图 |
| 实现复杂度 | 低(一行代码) | 中(需要管理视图生命周期) |
| 延迟问题 | 无 | 需要延迟移除原生遮罩 |
| 用户体验 | 切换器显示空白 | 切换器显示模糊画面 |
4.2 代码量对比
| 平台 | 核心代码行数 | 主要工作 |
|---|---|---|
| Android | ~40行 | FLAG_SECURE 开关 |
| iOS | ~100行 | 模糊视图创建/移除 + 生命周期管理 |
| OpenHarmony | ~234行 | 隐私模式 + 窗口事件 + 生命周期 |
4.3 OpenHarmony 的定位
OpenHarmony 的 setWindowPrivacyMode 在能力上更接近 Android 的 FLAG_SECURE:
| 能力 | Android | iOS | OpenHarmony |
|---|---|---|---|
| 系统级截屏防护 | ✅ | ❌ | ✅ |
| 系统级录屏防护 | ✅ | ❌ | ✅ |
| 应用切换器保护 | 自动 | 手动 | 自动 |
| 需要原生遮罩视图 | ❌ | ✅ | ❌ |
| 需要延迟移除 | ❌ | ✅ | ❌ |
💡 好消息:OpenHarmony 不需要像 iOS 那样创建原生模糊视图,也不需要处理延迟移除的问题。这简化了实现。
五、iOS 端的 opacity 处理
5.1 原生端的 opacity 应用
case "opacity":
if let args = call.arguments as? [String: Any],
let opacity = args["opacity"] as? Double {
self.opacity = CGFloat(opacity)
updateBlurViewOpacity()
}
result(true)
5.2 动态更新模糊视图透明度
func updateBlurViewOpacity() {
if let window = UIApplication.shared.windows.first,
let blurView = window.viewWithTag(12345) {
blurView.alpha = CGFloat(opacity)
}
}
iOS 端的 opacity 直接控制原生模糊视图的 alpha 值。而在 OpenHarmony 端,opacity 参数主要由 Flutter 层的 SecureGate 处理,原生端不需要做特殊处理。
六、从 iOS 实现中学到的经验
6.1 对 OpenHarmony 适配的启示
| iOS 的做法 | OpenHarmony 是否需要 | 原因 |
|---|---|---|
| 创建原生模糊视图 | ❌ | setWindowPrivacyMode 自动处理 |
| 延迟移除原生遮罩 | ❌ | 没有原生遮罩需要移除 |
| NotificationCenter 监听 | ✅(用不同方式) | 需要监听前后台切换 |
| 通知 Dart 层 lock | ✅ | 窗口失焦时通知锁定 |
6.2 需要注意的点
- 不要照搬 iOS 的模糊视图方案:OpenHarmony 有系统级保护,不需要
- 生命周期监听仍然需要:虽然方式不同,但目的相同
- nativeRemoveDelay 在 OpenHarmony 上可以更短:因为没有原生遮罩需要移除
6.3 三平台方案总结
Android: FLAG_SECURE ──────────────────► 系统自动处理一切
iOS: UIVisualEffectView ──────────► 手动遮挡 + 延迟移除
OHOS: setWindowPrivacyMode ────────► 系统自动处理 + 事件监听
七、Web 和 Windows 端简述
7.1 Web 端
// secure_application_web.dart
class SecureApplicationWeb {
// 监听 visibilitychange 事件
// 页面不可见时通知 Dart 层锁定
// 无法阻止截屏
}
Web 端能力最弱,只能检测页面可见性变化,无法阻止截屏或录屏。
7.2 Windows 端
// SecureApplicationPlugin.cpp
// 监听窗口最小化和锁屏事件
// 无法阻止截屏
Windows 端可以检测窗口最小化和系统锁屏,但同样无法阻止截屏。
7.3 五平台能力矩阵
| 能力 | Android | iOS | OHOS | Web | Windows |
|---|---|---|---|---|---|
| 截屏防护 | ✅ | ❌ | ✅ | ❌ | ❌ |
| 录屏防护 | ✅ | ❌ | ✅ | ❌ | ❌ |
| 切换器保护 | ✅ | ✅ | ✅ | N/A | N/A |
| 模糊遮罩 | ✅ | ✅ | ✅ | ✅ | ✅ |
| 认证解锁 | ✅ | ✅ | ✅ | ✅ | ✅ |
总结
本文分析了 secure_application 的 iOS 端实现:
- UIVisualEffectView:原生模糊视图遮挡应用内容
- 生命周期监听:willResignActive 添加遮罩,didBecomeActive 延迟移除
- 延迟移除:500ms 延迟确保 Flutter 渲染完成后再移除原生遮罩
- 能力限制:iOS 无法阻止截屏/录屏,只能遮挡
- 与 OpenHarmony 的差异:OHOS 有系统级保护,不需要原生遮罩
下一篇我们正式进入 OpenHarmony 适配——搭建 ohos 插件工程。
如果这篇文章对你有帮助,欢迎点赞👍、收藏⭐、关注🔔,你的支持是我持续创作的动力!
相关资源:
- iOS UIVisualEffectView 文档
- iOS App 生命周期
- UIBlurEffect 样式
- secure_application iOS 源码
- Flutter iOS Plugin 开发
- NotificationCenter 文档
- Swift 语言指南
- 开源鸿蒙跨平台社区

iOS 端应用切换器中的模糊遮罩效果
更多推荐


所有评论(0)