Flutter:禁用应用程序的屏幕截图捕获

cod*_*ess 5 dart flutter

我正在制作Flutter应用程序,并且需要确保用户无法捕获该应用程序的屏幕截图(任何屏幕)。有什么办法可以在Flutter中实现这一目标,还是需要为Android和IOS编写本机代码?

小智 47

仅在iOS中,只需在AppDelegate中修改即可。并且不再需要任何插件

import UIKit
import Flutter
import Firebase

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
    override func application(_ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions[UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    FirebaseApp.configure()
    self.window.makeSecure() //Add this line 
    GeneratedPluginRegistrant.register(with: self)
    return super.application(application, didFinishLaunchingWithOptions: launchOptions)
  }

}
//And this extension
extension UIWindow {
func makeSecure() {
    let field = UITextField()
    field.isSecureTextEntry = true
    self.addSubview(field)
    field.centerYAnchor.constraint(equalTo: self.centerYAnchor).isActive = true
    field.centerXAnchor.constraint(equalTo: self.centerXAnchor).isActive = true
    self.layer.superlayer?.addSublayer(field.layer)
    field.layer.sublayers?.first?.addSublayer(self.layer)
  }
}
Run Code Online (Sandbox Code Playgroud)

请参阅此处的图片

  • 这个答案有效,我已经测试过了,值得更多投票! (6认同)

Vla*_*lad 14

2023 年 7 月更新

我注意到,苹果开始使用下面的黑客技术拒绝应用程序。所以如果你仍然想阻止截图,我认为可以使用iOS API参数isCaptured 。我还没有测试过它,但作为一个想法,您可以使用 Flutter Method Channels 来获取/设置此属性。

iOS上,我已在扩展/sf/answers/4693842471/的帮助下禁用了截屏。请执行以下步骤:

  1. 添加属性AppDelegate

    var field = UITextField()

  2. didFinishLaunchingWithOptions调用下一个方法时:addSecuredView()

     private func addSecuredView() {
       if (!window.subviews.contains(field)) {
         window.addSubview(field)
         field.centerYAnchor.constraint(equalTo: window.centerYAnchor).isActive = true
         field.centerXAnchor.constraint(equalTo: window.centerXAnchor).isActive = true
         window.layer.superlayer?.addSublayer(field.layer)
         field.layer.sublayers?.first?.addSublayer(window.layer)
     }
    
    Run Code Online (Sandbox Code Playgroud)

    }

  3. 重写委托方法:

     override func applicationWillResignActive(_ application: UIApplication) {
       field.isSecureTextEntry = false
     }
    
     override func applicationDidBecomeActive(_ application: UIApplication) {
       field.isSecureTextEntry = true
     }
    
    Run Code Online (Sandbox Code Playgroud)

现在,当您在应用程序中进行屏幕截图或录制屏幕视频时,您将看到黑色图像或视频。希望它会有所帮助,因为我花了 2 天的时间试图让它发挥作用)

满的AppDelegate

import UIKit
import Flutter

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
    var field = UITextField()

    override func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
    ) -> Bool {
        GeneratedPluginRegistrant.register(with: self)

       #if !DEBUG
       addSecuredView()
       #endif
        
       return super.application(application, didFinishLaunchingWithOptions: launchOptions)
    }

    override func applicationWillResignActive(_ application: UIApplication) {
        field.isSecureTextEntry = false
    }

    override func applicationDidBecomeActive(
      _ application: UIApplication
    ) {
        field.isSecureTextEntry = true
    }

    private func addSecuredView() {
        if (!window.subviews.contains(field)) {
            window.addSubview(field)
            field.centerYAnchor.constraint(equalTo: window.centerYAnchor).isActive = true
            field.centerXAnchor.constraint(equalTo: window.centerXAnchor).isActive = true
            window.layer.superlayer?.addSublayer(field.layer)
            field.layer.sublayers?.first?.addSublayer(window.layer)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


Pri*_*ain 13

对于安卓

  1. 将名为flutter_windowmanager的 flutter 包添加到pubspec.yaml

  2. 在 Flutter 项目的 pubspec.yaml 文件中导入其最新版本并运行 pub get。然后将以下代码添加到initState()要禁用屏幕截图和屏幕录制的小部件的方法中。

     Future<void> secureScreen() async {
         await FlutterWindowManager.addFlags(FlutterWindowManager.FLAG_SECURE); 
      }
    
      @override
      void initState() {
         secureScreen();
         super.initState();
      }
    
      @override
      void dispose(){
         super.dispose();
         await FlutterWindowManager.clearFlags(FlutterWindowManager.FLAG_SECURE);
      }
    
    Run Code Online (Sandbox Code Playgroud)

如果您想让整个应用程序屏幕截图禁用,只需在 main.dart 文件中的函数securescreen(内调用 ) 方法(上面定义) 。main()

对于 iOS

  1. 将名为flutter_prevent_screen_capture的 flutter 插件添加到pubspec.yaml

然后运行 ​​flutter pub get。

  1. 定义变量如下:
 Future<void> secureScreen() async {
     await FlutterWindowManager.addFlags(FlutterWindowManager.FLAG_SECURE); 
  }

  @override
  void initState() {
     secureScreen();
     super.initState();
  }

  @override
  void dispose(){
     super.dispose();
     await FlutterWindowManager.clearFlags(FlutterWindowManager.FLAG_SECURE);
  }
Run Code Online (Sandbox Code Playgroud)
  1. 在 initstate 方法中初始化变量:
///Define a streamSubscription in order to receive changes
  late StreamSubscription<bool> _screenRecordsSubscription;

  ///Get the instance of plugin for multiple use.
  FlutterPreventScreenCapture preventScreenCapture =
      FlutterPreventScreenCapture();

  ///is Recording is set to false initially.
  bool isRecording = false;

Run Code Online (Sandbox Code Playgroud)

这样您就可以收听屏幕录制状态。

如果您想检查一次屏幕录制状态:

updateRecordStatus(bool record) {
   isRecording = record;
   setState(() {});
 }

@override
 void initState() {
   ///Though listening to the screen record, it is recommended to check the screen record status on the first launch.
   checkScreenRecord();

   ///Initialize screenRecordSubscription to regularly listen to the changes
   _screenRecordsSubscription =
       preventScreenCapture.screenRecordsIOS.listen(updateRecordStatus);
   super.initState();
 }
Run Code Online (Sandbox Code Playgroud)

最后一件事是不要忘记在 dispose 方法中取消订阅:

 Future<void> checkScreenRecord() async {
    final recordStatus = await preventScreenCapture.checkScreenRecord();

    debugPrint('Is screen being recorded: $recordStatus');

    isRecording = recordStatus;
    setState(() {});
  }
Run Code Online (Sandbox Code Playgroud)


Tru*_*iya 8

方法1:使用screen_protector这个包

方法二:

整个申请

打开AppDelegate文件并添加UITextField变量。

private var textField = UITextField()
Run Code Online (Sandbox Code Playgroud)

在文件中创建一个函数AppDelegate

// Screenshot Prevent Functions
    private func makeSecureYourScreen() {
        if (!self.window.subviews.contains(textField)) {
            self.window.addSubview(textField)
            textField.centerYAnchor.constraint(equalTo: self.window.centerYAnchor).isActive = true
            textField.centerXAnchor.constraint(equalTo: self.window.centerXAnchor).isActive = true
            self.window.layer.superlayer?.addSublayer(textField.layer)
            textField.layer.sublayers?.first?.addSublayer(self.window.layer)
        }
    }
Run Code Online (Sandbox Code Playgroud)

在函数中调用这个方法didFinishLaunchingWithOptions

makeSecureYourScreen()
Run Code Online (Sandbox Code Playgroud)

代码截图


在特定屏幕中 - 使用方法通道

打开AppDelegate文件并添加UITextField变量。

private var textField = UITextField()
Run Code Online (Sandbox Code Playgroud)

在文件中创建一个函数AppDelegate

// Screenshot Prevent Functions
    private func makeSecureYourScreen() {
        if (!self.window.subviews.contains(textField)) {
            self.window.addSubview(textField)
            textField.centerYAnchor.constraint(equalTo: self.window.centerYAnchor).isActive = true
            textField.centerXAnchor.constraint(equalTo: self.window.centerXAnchor).isActive = true
            self.window.layer.superlayer?.addSublayer(textField.layer)
            textField.layer.sublayers?.first?.addSublayer(self.window.layer)
        }
    }
Run Code Online (Sandbox Code Playgroud)

在函数中调用这个方法didFinishLaunchingWithOptions

makeSecureYourScreen()
Run Code Online (Sandbox Code Playgroud)

另外,在函数中添加您的方法通道代码didFinishLaunchingWithOptions

let controller : FlutterViewController = self.window?.rootViewController as! FlutterViewController
        let securityChannel = FlutterMethodChannel(name: "secureScreenshotChannel", binaryMessenger: controller.binaryMessenger)
        
        securityChannel.setMethodCallHandler({
            (call: FlutterMethodCall, result: @escaping FlutterResult) -> Void in
            if call.method == "secureiOS" {
                self.textField.isSecureTextEntry = true
            } else if call.method == "unSecureiOS" {
                self.textField.isSecureTextEntry = false
            }
        })
Run Code Online (Sandbox Code Playgroud)

Add your code below code to your flutter files to disable the screenshot on a specific screen.

// Declare your method channel varibale here
  var iosSecureScreenShotChannel = const MethodChannel('secureScreenshotChannel');
Run Code Online (Sandbox Code Playgroud)

现在添加代码以initState防止截图

@override
  void initState() {

    // this method to user can't take screenshots of your application
    iosSecureScreenShotChannel.invokeMethod("secureiOS");

    // TODO: implement initState
    super.initState();
  }
Run Code Online (Sandbox Code Playgroud)

添加代码以dispose允许在另一个屏幕上截图。

@override
  void dispose() {

    // this method to the user can take screenshots of your application
    iosSecureScreenShotChannel.invokeMethod("unSecureiOS");

    // TODO: implement dispose
    super.dispose();
  }
Run Code Online (Sandbox Code Playgroud)

Xcode 中的代码截图

Flutter 中的代码截图


您可以禁用屏幕截图和视频捕获,例如Netflix appDisney Hotstar应用程序。

我已经在我的应用程序中尝试过了,效果很好。


Len*_*sus 7

  1. 在Flutter Project的嵌入式android项目目录中找到您的MainActivity类
  2. 将以下导入添加到您的主要活动类中: import android.view.WindowManager.LayoutParams;
  3. 将以下行添加到MainActivity的onCreate方法中: getWindow().addFlags(LayoutParams.FLAG_SECURE);

而已。;)

  • ios呢? (5认同)

Mil*_*mar 7

通过执行以下两个步骤可以非常轻松地防止屏幕截图。

我正在使用 VS 代码。

步骤 1使用路径打开文件“mainActivity.kt”android\app\src\main\kotlin\com\example\auth_email\MainActivity.kt

步骤 2添加两行

(a) import android.view.WindowManager.LayoutParams; 

(b) getWindow().addFlags(LayoutParams.FLAG_SECURE); in MainActivity: FlutterActivity() section
Run Code Online (Sandbox Code Playgroud)

重新启动应用程序

在此输入图像描述


Jay*_*iya 7

对于 Flutter2 项目

方法 1:使用包flutter_windowmanager

方法二:

在 Android 中使用 kotlin

Step 1 使用路径打开文件“mainActivity.kt”

android\app\src\main\kotlin\com\example\auth_email\MainActivity.kt

步骤 2 导入库

import android.view.WindowManager.LayoutParams

import io.flutter.embedding.android.FlutterActivity

import io.flutter.embedding.engine.FlutterEngine

步骤 3 在主要活动类中

class MainActivity: FlutterActivity() {
  override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
    window.addFlags(LayoutParams.FLAG_SECURE)
    super.configureFlutterEngine(flutterEngine)
  }
}
Run Code Online (Sandbox Code Playgroud)

在 iOS Swift 中: AppDelegate.swift 文件

import UIKit
import Flutter

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {

  override func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
  ) -> Bool {
    GeneratedPluginRegistrant.register(with: self)
    return super.application(application, didFinishLaunchingWithOptions: launchOptions)
  }
  
  // <Add>
  override func applicationWillResignActive(
    _ application: UIApplication
  ) {
    self.window.isHidden = true;
  }
  override func applicationDidBecomeActive(
    _ application: UIApplication
  ) {
    self.window.isHidden = false;
  }
  

}
Run Code Online (Sandbox Code Playgroud)

  • 对于IOS,方法2也不起作用。 (2认同)
  • @Dharmendra,现在我们无法在 iOS 应用程序中禁用屏幕截图。 (2认同)

Tee*_*har 6

对我有用的是在 MainActivity.java 文件中编写以下代码。

@Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE);
  }
Run Code Online (Sandbox Code Playgroud)

并导入这些包!

import android.view.WindowManager; 
import android.view.WindowManager.LayoutParams;
import android.os.Bundle; // required for onCreate parameter
Run Code Online (Sandbox Code Playgroud)