You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 13:06:23