How to Create a Custom Plugin to Disable Screenshots in Flutter

Flutter is known for its flexibility in creating custom plugins to extend its capabilities. If you want to protect sensitive app content by disabling screenshots, you can achieve this by creating a custom plugin that interacts with native code on Android and iOS. This blog will walk you through the process of building a custom Flutter plugin to disable screenshots.

Why Disable Screenshots?

In some apps, such as financial applications, messaging apps, or any app dealing with sensitive data, preventing screenshots and screen recordings is critical for privacy and security. By creating a custom plugin, you gain granular control over this functionality.

Steps to Create a Custom Plugin for Screenshot Disabling

Step 1: Create a New Flutter Plugin

Start by creating a new plugin project using the Flutter CLI:

flutter create --template=plugin --platforms=android,ios screenshot_protector
This will generate a folder named screenshot_protector with the following structure:

lib/: Contains the Dart code.
android/: Contains the Android-specific implementation.
ios/: Contains the iOS-specific implementation.

Step 2: Implement Android-Specific Code

On Android, you can disable screenshots using the FLAG_SECURE window flag.

Open the file: android/src/main/java/com/example/screenshot_protector/ScreenshotProtectorPlugin.java.
  
  java

package com.example.screenshot_protector;

import android.app.Activity;
import android.view.WindowManager;

import androidx.annotation.NonNull;

import io.flutter.embedding.engine.plugins.FlutterPlugin;
import io.flutter.embedding.engine.plugins.activity.ActivityAware;
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;

/** ScreenshotProtectorPlugin */
public class ScreenshotProtectorPlugin implements FlutterPlugin, MethodChannel.MethodCallHandler, ActivityAware {
    private MethodChannel channel;
    private Activity activity;

    @Override
    public void onAttachedToEngine(@NonNull FlutterPluginBinding flutterPluginBinding) {
        channel = new MethodChannel(flutterPluginBinding.getBinaryMessenger(), "screenshot_protector");
        channel.setMethodCallHandler(this);
    }

    @Override
    public void onMethodCall(@NonNull MethodCall call, @NonNull MethodChannel.Result result) {
        if (call.method.equals("enableProtection")) {
            if (activity != null) {
                activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_SECURE);
                result.success(null);
            } else {
                result.error("NO_ACTIVITY", "Activity is not attached", null);
            }
        } else if (call.method.equals("disableProtection")) {
            if (activity != null) {
                activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_SECURE);
                result.success(null);
            } else {
                result.error("NO_ACTIVITY", "Activity is not attached", null);
            }
        } else {
            result.notImplemented();
        }
    }

    @Override
    public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) {
        channel.setMethodCallHandler(null);
    }

    @Override
    public void onAttachedToActivity(@NonNull ActivityPluginBinding binding) {
        activity = binding.getActivity();
    }

    @Override
    public void onDetachedFromActivityForConfigChanges() {
        activity = null;
    }

    @Override
    public void onReattachedToActivityForConfigChanges(@NonNull ActivityPluginBinding binding) {
        activity = binding.getActivity();
    }

    @Override
    public void onDetachedFromActivity() {
        activity = null;
    }
}

Step 3: Implement iOS-Specific Code

On iOS, you can use the isSecure property of UIWindow to disable screenshots.

Open the file: ios/Classes/ScreenshotProtectorPlugin.m

Add the following implementation:

objc

#import "ScreenshotProtectorPlugin.h"
#if __has_include()
#import 
#else
#import "screenshot_protector-Swift.h"
#endif

@implementation ScreenshotProtectorPlugin {
    UIWindow *mainWindow;
}

+ (void)registerWithRegistrar:(NSObject*)registrar {
    FlutterMethodChannel* channel = [FlutterMethodChannel
        methodChannelWithName:@"screenshot_protector"
              binaryMessenger:[registrar messenger]];
    ScreenshotProtectorPlugin* instance = [[ScreenshotProtectorPlugin alloc] init];
    [registrar addMethodCallDelegate:instance channel:channel];
}

- (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result {
    if ([@"enableProtection" isEqualToString:call.method]) {
        [self enableScreenProtection];
        result(nil);
    } else if ([@"disableProtection" isEqualToString:call.method]) {
        [self disableScreenProtection];
        result(nil);
    } else {
        result(FlutterMethodNotImplemented);
    }
}

- (void)enableScreenProtection {
    mainWindow = [UIApplication sharedApplication].keyWindow;
    mainWindow.secureTextEntry = YES;
}

- (void)disableScreenProtection {
    mainWindow = [UIApplication sharedApplication].keyWindow;
    mainWindow.secureTextEntry = NO;
}

Step 4: Create a Dart Interface

In lib/screenshot_protector.dart, create a Dart interface to call the native code:

dart

import 'dart:async';
import 'package:flutter/services.dart';

class ScreenshotProtector {
  static const MethodChannel _channel = MethodChannel('screenshot_protector');

  static Future enableProtection() async {
    await _channel.invokeMethod('enableProtection');
  }

  static Future disableProtection() async {
    await _channel.invokeMethod('disableProtection');
  }
}

Step 5: Use the Plugin in Your Flutter App

In your Flutter app, import the plugin and call the enableProtection or disableProtection methods where needed.

dart

import 'package:flutter/material.dart';
import 'package:screenshot_protector/screenshot_protector.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: HomeScreen(),
    );
  }
}

class HomeScreen extends StatefulWidget {
  @override
  _HomeScreenState createState() => _HomeScreenState();
}

class _HomeScreenState extends State {
  @override
  void initState() {
    super.initState();
    ScreenshotProtector.enableProtection();
  }

  @override
  void dispose() {
    ScreenshotProtector.disableProtection();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Screenshot Protection')),
      body: Center(
        child: Text('Screenshot protection is enabled'),
      ),
    );
  }
}

Testing Your Plugin

Run the app on both Android and iOS devices.

Try to take a screenshot or record the screen. The functionality should now be disabled.

Conclusion

Creating a custom plugin in Flutter allows you to leverage platform-specific features and extend your app’s capabilities. With this custom plugin, you can easily disable screenshots and screen recordings in your Flutter apps, enhancing privacy and security.