Disable screenshot capture for Flutter app
Asked Answered
H

16

58

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?

Hypothesis answered 13/9, 2018 at 15:39 Comment(7)
Is that even possible at all?Revkah
I don't know, thats why I am asking here.Hypothesis
In flutter it's currently unavailable, but you can write native code for Android & iOS as you said and maybe create a request on the GitHub of flutter ;)Lychnis
If it is possible natively in Android and iOS, it should be possible in Flutter by writing a plugin or using channels. But first you must be sure it can be done natively.Vltava
Relevant URL: FLAG_SECURETowne
@Vltava It is possible in Native Android and iOSRopedancer
@Hypothesis It's works for me. You can try my answer. https://mcmap.net/q/328871/-disable-screenshot-capture-for-flutter-appDubitation
S
49

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

Suspensoid answered 14/2, 2022 at 8:29 Comment(11)
This answer works I've tested it, and deserves more votes!Refurbish
@ClarkCluster, why did you copied and pasted my answer?Blatherskite
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).Blatherskite
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.Suspensoid
This makes a screenshot whole black screen on iOS. Great!Wilterdink
Can someone explain the last 2 lines, please?Hyman
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.Concoct
Only on real iOS deviceSuspensoid
i test on real device its not working ios 12.5 versionAugustina
in 2023 May, it works as well, thanks. Still a valid answer.Filippa
IMP NOTE: THIS IS THE INCORRECT WAY TO HANDLE THE PREVENTING THE SCREENSHOT. APPLE IS REJECTING A APP THAT USES THIS TECHNIQUE. #75181508 CHECK THIS LINK FOR MORE CLARIFICATION. EVEN MY APP IS ALSO GET REJECTED DUE TO IT.Poet
F
35

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!

Fiveandten answered 28/12, 2018 at 12:7 Comment(7)
and what about ios?Grisby
Seems there is no real solution for iOS, yet.Closure
What is path of "MainActivity class" file in flutter? Please suggest.Poliomyelitis
For kotlin? MainActivity.kt ?Centennial
@Grisby for iOS maybe mrgulshanyadav.medium.com/…Vaillancourt
it records audio when playing video. tested on android 10 & 11Smoke
pub.dev/packages/flutter_windowmanagerPoliomyelitis
Y
32

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

}
Yankeeism answered 8/4, 2021 at 5:10 Comment(5)
pub.dev/packages/flutter_windowmanagerPoliomyelitis
Good news is, now it supports NULL SAFETY alsoPoliomyelitis
what if I want to allow screenshots but want to hide screen on recent tab window ??? for IOS and AndroidKenn
for IOS, method 2 also not working.Cuspidation
@Dharmendra, now we can't disable screenshot in iOS App.Yankeeism
B
20

Updates on April, 2024: (iOS 17)

On iOS I have disabled taking of screenshots with the help of extension https://mcmap.net/q/138982/-prevent-screen-capture-in-an-ios-app. 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)
         if #available(iOS 17.0, *) {
           field.layer.sublayers?.last?.addSublayer(window.layer)
         } else {
           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)

Full 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)
            if #available(iOS 17.0, *) {
              field.layer.sublayers?.last?.addSublayer(window.layer)
            } else {
              field.layer.sublayers?.first?.addSublayer(window.layer)
            }
        }
    }
}
Blatherskite answered 31/12, 2021 at 13:47 Comment(2)
Can you please share your full Appdelegate.swift file?Toponymy
Is there anyway I can upvote this answer multiple times ?Semitone
N
15

For Android:

  1. add the flutter package called flutter_windowmanager to your pubspec.yaml

  2. 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.

For iOS:

  1. add the flutter plugin called flutter_prevent_screen_capture to your pubspec.yaml

then run flutter pub get.

  1. Define variables like below:
///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;

  1. initialize variables in initstate method:
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();
 }

So you can listen to the screen recording status.

If you want to check the screen recording status once:

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

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

    isRecording = recordStatus;
    setState(() {});
  }

The last thing is don't forget to cancel subscription in dispose method:

@override
  dispose() {
    _screenRecordsSubscription.cancel();
    super.dispose();
  }
Niela answered 17/12, 2020 at 11:58 Comment(6)
I don't acutally know whether it work for IOS but yes it works very well for android.Niela
@Priyanshjain dear, you forgot to call clearFlags in dispose() method - await FlutterWindowManager.clearFlags( FlutterWindowManager.FLAG_SECURE); Otherwise it will restrict to take screenshot to all further screens/pages. Please update your answer. Thanks alot.Poliomyelitis
pub.dev/packages/flutter_windowmanagerPoliomyelitis
Works for Android only, No support for iOSCuspidation
@Cuspidation Yes it works only for AndroidNiela
Currently there's working solution for iOS too.Bisson
P
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
Psia answered 11/3, 2020 at 6:19 Comment(2)
tested using screencapture apps too!Psia
Why are you repeating the same flat twice?Calabar
D
9

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 prevent screenshots and video captures in apps like Netflix and Disney Hotstar.

I have tested it in my application, and it is working perfectly. 😊

Dubitation answered 18/5, 2022 at 6:4 Comment(0)
E
7

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

Exaggerated answered 13/5, 2020 at 3:30 Comment(0)
M
3

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
Myalgia answered 2/4, 2020 at 15:14 Comment(5)
Think twice AppDelegate.swift or AppDelegate.m ?Pushup
AppDelegate.m in case your iOS project is in ObjectiveC. There must be an equivalent for AppDelegate.swift in case your iOS project is in Swift :)Myalgia
what is the [GeneratedPluginRegistrant registerWithRegistry:self]; i'm using native ios codeFloro
This does not work when the app is in the foreground.Wenonawenonah
could you provide for swift also pleaseDacha
H
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.

Histoplasmosis answered 26/9, 2020 at 23:55 Comment(0)
C
2

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.

Cuspidation answered 13/5, 2022 at 9:16 Comment(3)
But when i am try to take screenshot with simulator not work, have you try to take screenshot or video record using real device work or not?Henequen
@Henequen In real device, it worked.Cuspidation
I just integrated and yeah worked ios and android.Henequen
J
1

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

Jayejaylene answered 26/10, 2019 at 13:39 Comment(0)
I
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)
  }
}
Irisation answered 31/3, 2021 at 12:55 Comment(0)
B
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(); 
}
Bigod answered 20/4, 2021 at 21:15 Comment(3)
This is only going to work for android and not iOS.Vargueno
@sagarsuri did you get any solution for iOS.Haemoid
@Haemoid after spending some time I realised that Apple doesn't provide any official API to prevent screenshot capturing or recording. So I have left it out and only implemented it for android.Vargueno
C
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.

Catalysis answered 1/2, 2023 at 16:5 Comment(0)
V
1

for a simple screen lock on iOS and android, there is a plugin

make_secure_screenshot the screenshot will have a black screen.

or a more advanced screen_protector plugin with the ability to install an image

Verge answered 3/4 at 14:28 Comment(1)
While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes. - From ReviewArdennes

© 2022 - 2024 — McMap. All rights reserved.