47

I am making a Flutter app and I need to make sure the user is not able to capture screenshot of the app (any screen). Is there any way to achieve this in Flutter or do I need to write native code for both Android and IOS?

codeinprogress
  • 3,193
  • 7
  • 43
  • 69

15 Answers15

42

It's only in iOS,just modify in AppDelegate. And no more plugins

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)
  }
}

See image here

ClarkCluster
  • 446
  • 4
  • 7
  • 6
    This answer works I've tested it, and deserves more votes! – Aziz Mar 02 '22 at 05:06
  • @ClarkCluster, why did you copied and pasted my answer? – Volodymyr Mar 07 '22 at 06:46
  • NOTE: you should change value of `isSecureTextEntry` in app lifecycle methods as I did in my answer. Otherwise you will get side effect: "red screen". Actions: go to background, switch to another app and back to your app (preview of your app will be red). – Volodymyr Mar 07 '22 at 16:06
  • Yes sir, it just not work in my case, I figure out in my way as ur code really help me a lot, also I don't know should changed lifecycle methods, thanks for tips sir. – ClarkCluster Mar 08 '22 at 01:16
  • 1
    This makes a screenshot whole black screen on iOS. Great! – Vincent Gigandet Jul 13 '22 at 16:16
  • Can someone explain the last 2 lines, please? – asclepix Sep 28 '22 at 17:49
  • Does it work on simulator? I implemented this code on a new created flutter project and ran on a simulator. Unfortunately it did not work. – ZhangLei Dec 01 '22 at 08:53
  • Only on real iOS device – ClarkCluster Dec 20 '22 at 09:57
  • i test on real device its not working ios 12.5 version – joshua Feb 12 '23 at 09:10
  • 1
    in 2023 May, it works as well, thanks. Still a valid answer. – alperefesahin May 18 '23 at 13:19
  • IMP NOTE: THIS IS THE INCORRECT WAY TO HANDLE THE PREVENTING THE SCREENSHOT. APPLE IS REJECTING A APP THAT USES THIS TECHNIQUE. https://stackoverflow.com/questions/75181008/flutter-ios-prevent-screenshot#:~:text=takes%20a%20screenshot.-,Duplicating%20system%2Dprovided%20interfaces%20does%20not%20provide%20the%20simple%2C%20innovative,provided%20screenshot%20interface%20and%20functionality.%22 CHECK THIS LINK FOR MORE CLARIFICATION. EVEN MY APP IS ALSO GET REJECTED DUE TO IT. – kunj kanani Jun 16 '23 at 05:15
33

Android

Method 1 (all app screens):

  1. Locate your MainActivity (.java or .kt) class inside the embedded android project dir in your Flutter Project,
  2. Add the following import to your main activity class:
import android.view.WindowManager.LayoutParams;
  1. Add the following line to your MainActivity's onCreate method:
getWindow().addFlags(LayoutParams.FLAG_SECURE);

Method 2 (for specific screens):

Use FlutterWindowManagerPlugin: https://pub.dev/packages/flutter_windowmanager

Thanks, @Kamlesh!

Lennon Jesus
  • 471
  • 4
  • 8
26

For Flutter2 project

Method 1 : using package flutter_windowmanager

Method 2 :

in Android with kotlin

Step 1 Open the file "mainActivity.kt" using the path

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

Step 2 Import Library

import android.view.WindowManager.LayoutParams
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine

Step 3 In main activity class

class MainActivity: FlutterActivity() {
  override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
    window.addFlags(LayoutParams.FLAG_SECURE)
    super.configureFlutterEngine(flutterEngine)
  }
}

In iOS Swift : AppDelegate.swift file

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
  ) {
    window?.rootViewController?.view.endEditing(true)
    self.window.isHidden = true;
  }
  override func applicationDidBecomeActive(
    _ application: UIApplication
  ) {
    self.window.isHidden = false;
  }
  

}
Guillaume Roux
  • 6,352
  • 1
  • 13
  • 38
Jay Kukadiya
  • 553
  • 6
  • 9
12

The simplest way to do this is to use a flutter package called flutter_windowmanager

Works only for Android, not for IOS!

First import its latest version in pubspec.yaml file of your Flutter project and run pub get. Then add the below code inside the widget's initState() method for which you want to disable screenshot and screen recording.

    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);
     }

If you want to make your whole app screenshot disable just call securescreen() method (defined above) inside your main() function in main.dart file.

Priyansh jain
  • 1,065
  • 10
  • 17
9

What worked for me was writing the below code in MainActivity.java file.

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

and importing these packages!

import android.view.WindowManager; 
import android.view.WindowManager.LayoutParams;
import android.os.Bundle; // required for onCreate parameter
Teekam Suthar
  • 529
  • 1
  • 9
  • 20
9

Updates on July, 2023:

I noticed, that Apple started rejecting apps using the hack below. So if you still want to prevent screenshot I think that iOS API parameter isCaptured may be used. I haven't tested it but as an idea you can use Flutter Method Channels to get/set this property.

On iOS I have disabled taking of screenshots with the help of extension https://stackoverflow.com/a/67054892/4899849. Follow next steps:

  1. Add property in AppDelegate:

    var field = UITextField()

  2. in didFinishLaunchingWithOptions call next method: 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)
     }
    

    }

  3. override delegate methods:

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

Now, when you make a screenshot in the app or record a screen video you will see a black image or video. Hope, it will help cuz I spent 2 days trying to make it work)

Volodymyr
  • 1,192
  • 21
  • 42
8

Flutter

Method 1: Using this package screen_protector

Method 2:

In Whole your Application

Open AppDelegate file and add UITextField variable.

private var textField = UITextField()

Create a function in AppDelegate file.

// 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)
        }
    }

Call this method into the didFinishLaunchingWithOptions function.

makeSecureYourScreen()

Code Screenshot


In Specific Screen - Using Method Channel

Open AppDelegate file and add UITextField variable.

private var textField = UITextField()

Create a function in AppDelegate file.

// 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)
        }
    }

Call this method into the didFinishLaunchingWithOptions function.

makeSecureYourScreen()

Also, add your method channel code in the didFinishLaunchingWithOptions function.

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
            }
        })

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');

Now add code to initState to prevent screenshot

@override
  void initState() {

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

    // TODO: implement initState
    super.initState();
  }

For add code to dispose to allow screenshots on another screen.

@override
  void dispose() {

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

    // TODO: implement dispose
    super.dispose();
  }

Code Screenshot in Xcode

Code Screenshot in Flutter


You can disable screenshots and video captures like the Netflix app and Disney Hotstar app.

I have tried it in my application and it works fine.

6

Screenshots can be prevented very easily by following below two steps.

I am using VS code.

Step 1 Open the file "mainActivity.kt" using the path android\app\src\main\kotlin\com\example\auth_email\MainActivity.kt

Step 2 Add the two lines

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

(b) getWindow().addFlags(LayoutParams.FLAG_SECURE); in MainActivity: FlutterActivity() section

Restart the app

enter image description here

deadshot
  • 8,881
  • 4
  • 20
  • 39
Milan Kumar
  • 151
  • 2
  • 5
2

This works for iOS. In your Runner > AppDelegate.m:

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application
    didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
  [GeneratedPluginRegistrant registerWithRegistry:self];
  // Override point for customization after application launch.
  return [super application:application didFinishLaunchingWithOptions:launchOptions];
}

- (void)applicationWillResignActive:(UIApplication *)application{
    self.window.hidden = YES;
}

- (void)applicationDidBecomeActive:(UIApplication *)application{
    self.window.hidden = NO;
}

@end
Rafa0809
  • 1,733
  • 21
  • 24
2

If you are using kotlin

open MainActivity.kt

Add below code at end of imports

import android.view.WindowManager.LayoutParams

Add below code at end of super.onCreate(savedInstanceState)

window.addFlags(LayoutParams.FLAG_SECURE)

Its done.

Gökberk Yağcı
  • 376
  • 1
  • 4
  • 10
1

try to use

for android edit MainActivity.kt

package com.package.app_name

import android.view.WindowManager.LayoutParams
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine

class MainActivity: FlutterActivity() {
override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
    window.addFlags(LayoutParams.FLAG_SECURE)
    super.configureFlutterEngine(flutterEngine)
  }
}
GJJ2019
  • 4,624
  • 3
  • 12
  • 22
1
  1. define this package inside pubspec.yaml file

flutter_windowmanager: ^0.0.1+1

  1. get dependencies

flutter pub get

  1. You need to call a method of FlutterWindowManager using await and async.
  2. You have to add a few lines of code in your StatefulWidget.
Future<void> secureScreen() async { 
  await FlutterWindowManager.addFlags(FlutterWindowManager.FLAG_SECURE);
}

@override 
void initState() {
  secureScreen();
  super.initState(); 
}
Nagual
  • 1,576
  • 10
  • 17
  • 27
1

https://pub.dev/packages/screen_protector

use this one. works for Android, iOS both. In iOS, screenshot will be captured but output will be black screen.

Dharmendra
  • 189
  • 3
  • 11
1

You can use the flutter_windowmanager: ^0.2.0 package to disable screenshot capture in a Flutter app. To do this, add the following code in your main.dart file:

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await FlutterWindowManager.addFlags(FlutterWindowManager.FLAG_SECURE);
  runApp(MyApp());
}

This will add the FLAG_SECURE flag to your app, which will prevent screenshots from being captured. Note that this will only work on Android devices.

0

You could maybe listen for the screenshot keys on iOS and when the combination is being pressed blacken the screen.