Flutter跨平台应用macOS端禁用截图实现方案咨询
macOS 端禁用截图/录屏的实现方案(适配Flutter跨平台应用)
核心思路
macOS 无法完全禁止系统级的截图/录屏操作,但可以通过应用层配置限制窗口内容被捕获,同时配合监听系统录屏状态,在检测到录屏时动态添加内容遮挡,实现内容保护。核心是利用系统窗口属性和状态通知来实现防护。
实现方式(Swift/C++ 两种可选)
1. Swift 原生实现(适配Flutter插件开发)
在Flutter的macOS原生插件代码中,通过MethodChannel与Flutter侧交互,控制窗口属性并监听录屏状态:
import Cocoa import FlutterMacOS class ScreenProtectorPlugin: NSObject, FlutterPlugin { static func register(with registrar: FlutterPluginRegistrar) { let channel = FlutterMethodChannel(name: "screen_protector", binaryMessenger: registrar.messenger) let instance = ScreenProtectorPlugin() registrar.addMethodCallDelegate(instance, channel: channel) } func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) { switch call.method { case "enableProtection": enableScreenProtection() result(true) case "disableProtection": disableScreenProtection() result(true) default: result(FlutterMethodNotImplemented) } } private func enableScreenProtection() { guard let window = NSApplication.shared.windows.first else { return } // 设置窗口禁止被共享捕获 window.sharingType = .none // 监听系统录屏状态变化 NotificationCenter.default.addObserver( self, selector: #selector(onScreenRecordingStateChange), name: NSApplication.screenRecordingStateDidChangeNotification, object: nil ) } private func disableScreenProtection() { guard let window = NSApplication.shared.windows.first else { return } window.sharingType = .default NotificationCenter.default.removeObserver( self, name: NSApplication.screenRecordingStateDidChangeNotification, object: nil ) // 清除所有遮挡层 window.contentView?.subviews.forEach { if $0 is NSVisualEffectView { $0.removeFromSuperview() } } } @objc private func onScreenRecordingStateChange(_ notification: Notification) { guard let window = NSApplication.shared.windows.first else { return } let isRecording = NSApplication.shared.isScreenRecordingActive if isRecording { // 添加模糊遮罩层覆盖窗口内容 let blurView = NSVisualEffectView(frame: window.contentView!.bounds) blurView.blendingMode = .behindWindow blurView.material = .dark blurView.state = .active window.contentView?.addSubview(blurView) } else { // 移除遮罩层 window.contentView?.subviews.forEach { if $0 is NSVisualEffectView { $0.removeFromSuperview() } } } } }
2. C++ 实现(通过Objective-C++桥接)
如果需要用C/C实现,可通过Objective-C桥接调用macOS原生API,将代码保存为.mm文件后在工程中编译:
#include <Cocoa/Cocoa.h> extern "C" void enableScreenProtection() { NSWindow *window = [NSApplication sharedApplication].windows.firstObject; if (!window) return; window.sharingType = NSWindowSharingNone; // 监听录屏状态通知 [[NSNotificationCenter defaultCenter] addObserverForName:NSApplicationScreenRecordingStateDidChangeNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) { BOOL isRecording = [NSApplication sharedApplication].isScreenRecordingActive; NSView *contentView = window.contentView; if (isRecording) { NSVisualEffectView *blurView = [[NSVisualEffectView alloc] initWithFrame:contentView.bounds]; blurView.blendingMode = NSVisualEffectBlendingModeBehindWindow; blurView.material = NSVisualEffectMaterialDark; blurView.state = NSVisualEffectStateActive; [contentView addSubview:blurView]; } else { for (NSView *subview in contentView.subviews) { if ([subview isKindOfClass:[NSVisualEffectView class]]) { [subview removeFromSuperview]; } } } }]; } extern "C" void disableScreenProtection() { NSWindow *window = [NSApplication sharedApplication].windows.firstObject; if (!window) return; window.sharingType = NSWindowSharingDefault; [[NSNotificationCenter defaultCenter] removeObserver:nil name:NSApplicationScreenRecordingStateDidChangeNotification object:nil]; // 清除遮罩层 for (NSView *subview in window.contentView.subviews) { if ([subview isKindOfClass:[NSVisualEffectView class]]) { [subview removeFromSuperview]; } } }
关键注意事项
NSWindowSharingNone属性会让窗口内容无法被系统自带的截图/录屏工具捕获,但无法完全阻止第三方恶意捕获工具。- 监听录屏状态通知可以在系统开始录屏时动态添加遮挡,进一步提升内容安全性。
- Flutter侧可通过已有的MethodChannel逻辑,直接调用上述原生方法,保持和Android/iOS端
screen_protector插件的调用一致性。
内容的提问来源于stack exchange,提问作者jameel spario
相关产品推荐
相关产品推荐

