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

Flutter实现禁止录屏但允许截图的解决方案咨询

实现Flutter应用禁止录屏但允许截图的可行方案

针对你的需求,需要分Android和iOS平台分别处理,下面是具体的实现思路和代码示例:

Android 平台实现

Android系统的FLAG_SECURE会同时禁止录屏和系统截图,但我们可以通过临时移除该标记实现APP内主动截图,同时保留对录屏的禁止:

  1. 设置FLAG_SECURE禁止录屏
    在Android原生的MainActivity中添加以下代码,启动时锁定屏幕内容,阻止系统录屏:
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    // 启用FLAG_SECURE,禁止录屏和系统截图
    window.setFlags(WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE)
}
  1. 实现APP内主动截图功能
    通过MethodChannel给Flutter提供截图能力,临时移除FLAG_SECURE完成截图后再恢复:
// 初始化MethodChannel,与Flutter通信
private val channel = MethodChannel(flutterEngine.dartExecutor.binaryMessenger, "app_screenshot_channel")

override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
    super.configureFlutterEngine(flutterEngine)
    channel.setMethodCallHandler { call, result ->
        if (call.method == "captureScreen") {
            // 临时移除FLAG_SECURE
            window.clearFlags(WindowManager.LayoutParams.FLAG_SECURE)
            val rootView = window.decorView.rootView
            rootView.isDrawingCacheEnabled = true
            val bitmap = Bitmap.createBitmap(rootView.drawingCache)
            rootView.isDrawingCacheEnabled = false
            // 恢复FLAG_SECURE
            window.setFlags(WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE)
            
            // 将Bitmap转为字节数组返回给Flutter
            val stream = ByteArrayOutputStream()
            bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream)
            val byteArray = stream.toByteArray()
            result.success(byteArray)
        } else {
            result.notImplemented()
        }
    }
}
  1. Flutter侧调用截图
    通过MethodChannel调用原生方法,拿到截图后处理上传:
final MethodChannel _screenshotChannel = MethodChannel('app_screenshot_channel');

Future<Uint8List?> captureScreen() async {
  try {
    return await _screenshotChannel.invokeMethod('captureScreen');
  } on PlatformException catch (e) {
    print("截图失败: ${e.message}");
    return null;
  }
}

// 在合规模块的按钮点击时调用
void onUploadScreenshot() async {
  Uint8List? imageBytes = await captureScreen();
  if (imageBytes != null) {
    // 处理上传逻辑
  }
}

iOS 平台实现

iOS系统中,屏幕录制会触发UIScreen.capturedDidChangeNotification通知,但系统截图不会触发该通知,我们可以利用这个差异实现需求:

  1. 监听屏幕录制状态
    在iOS原生的ViewController中注册通知,检测到录屏时通知Flutter隐藏视频内容:
private let channel = FlutterMethodChannel(name: "screen_capture_channel", binaryMessenger: flutterEngine.binaryMessenger)

override func viewDidLoad() {
    super.viewDidLoad()
    // 监听屏幕录制状态变化
    NotificationCenter.default.addObserver(
        self,
        selector: #selector(onScreenCaptureChanged),
        name: UIScreen.capturedDidChangeNotification,
        object: nil
    )
}

@objc private func onScreenCaptureChanged() {
    let isCaptured = UIScreen.main.isCaptured
    // 通知Flutter侧当前录屏状态
    channel.invokeMethod("updateCaptureState", arguments: isCaptured)
}

// 页面销毁时移除通知
deinit {
    NotificationCenter.default.removeObserver(self)
}
  1. Flutter侧处理录屏状态
    接收原生通知,当检测到录屏时显示占位层,隐藏视频内容;录屏结束后恢复:
final MethodChannel _captureChannel = MethodChannel('screen_capture_channel');
bool _isRecording = false;

@override
void initState() {
    super.initState();
    _captureChannel.setMethodCallHandler((call) async {
        if (call.method == "updateCaptureState") {
            setState(() {
                _isRecording = call.arguments as bool;
            });
        }
    });
}

@override
Widget build(BuildContext context) {
    return Stack(
        children: [
            // 你的视频流播放器组件
            VideoStreamPlayer(),
            // 录屏时显示的占位层
            if (_isRecording)
                Container(
                    color: Colors.black,
                    child: const Center(
                        child: Text("禁止录屏", style: TextStyle(color: Colors.white, fontSize: 18)),
                    ),
                ),
        ],
    );
}

注意事项

  • Android的FLAG_SECURE在部分定制ROM上可能存在兼容性问题,需要多机型测试
  • iOS的监听逻辑要确保在页面生命周期内正确注册和移除通知,避免内存泄漏
  • 两种方案都保留了系统截图(iOS)或APP内主动截图(Android)的能力,满足合规模块的上传需求

内容的提问来源于stack exchange,提问作者Ebrahim Mansur

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 18:46:11