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?
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?
Method 1 (all app screens):
import android.view.WindowManager.LayoutParams;
getWindow().addFlags(LayoutParams.FLAG_SECURE);
Method 2 (for specific screens):
Use FlutterWindowManagerPlugin: https://pub.dev/packages/flutter_windowmanager
Thanks, @Kamlesh!
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
) {
self.window.isHidden = true;
}
override func applicationDidBecomeActive(
_ application: UIApplication
) {
self.window.isHidden = false;
}
}
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)
}
}
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.
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
On iOS I have disabled taking of screenshots with the help of extension https://stackoverflow.com/a/67054892/4899849. Follow next steps:
Add property in AppDelegate:
var field = UITextField()
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)
}
}
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)
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
Flutter
In Whole your Application
Open AppDelegate file and add UITextField variable.
private var textField = UITextField()
Create 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()
In Specific Screen - Using Method Channel Open
AppDelegatefile and addUITextFieldvariable.
private var textField = UITextField()
Create 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 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 for prevent screenshot
@override
void initState() {
// this method to user can't take screenshot your application
iosSecureScreenShotChannel.invokeMethod("secureiOS");
// TODO: implement initState
super.initState();
}
For add code to dispose for allow screenshot in another screen.
@override
void dispose() {
// this method to user can take screenshot your application
iosSecureScreenShotChannel.invokeMethod("unSecureiOS");
// TODO: implement dispose
super.dispose();
}
You can disable screenshots and video captures like the Netflix app and Disney Hotstar app.
I have tried in my application and it's works fine.
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
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.
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)
}
}
pubspec.yaml fileflutter_windowmanager: ^0.0.1+1
flutter pub get
FlutterWindowManager using await and async.StatefulWidget.Future<void> secureScreen() async {
await FlutterWindowManager.addFlags(FlutterWindowManager.FLAG_SECURE);
}
@override
void initState() {
secureScreen();
super.initState();
}
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.
You could maybe listen for the screenshot keys on iOS and when the combination is being pressed blacken the screen.