cover image
Nitish Kumar Singh
Nitish Kumar Singh
Clock Image 8 minutes
Posted on
December 2, 2020

Disable screenshot in flutter


Sometimes for security purpose we don’t want user to take screenshot and share further.

Disabling screenshot also disable screen recoding of that app. You might have noticed this feature in OTT media service i.e Netflix, Amazon Prime, Disney plus and many more.

OTT use this feature so that protected content can only seen by their subscribed customer and it restrict us from screen recoding and re-distributing.

Get Started #

Flutter ask us to select a programming language from available two options

OSNative Language 1Native Language 2
iOSObjective CSwift
AndroidJavaKotlin

We mostly prefer Swift for iOS and Kotlin for android. These two respective company also recommend the same. If you see the default option the it comes with the same.

There is two ways to achieve this

  1. Natively: By touching the native code and touching native programming code.
  2. Non Natively: By not touching the native and using plugin.

Using plugin you can only do for android and for ios you need to go natively.

Using Plugin #

Pub Flutter Windows Manage

This is going to be easy and if you only targeting the android device then this is possibly best solution.

main.dart
import 'package:flutter/material.dart';
import 'package:flutter_windowmanager/flutter_windowmanager.dart';

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

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  bool _isSecureScreen = false;

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Screenshot Secure Demo'),
        ),
        body: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          crossAxisAlignment: CrossAxisAlignment.center,
          children: <Widget>[
            Text(
              _isScreenShotAllowed 
                ? 'Secure Mode' 
                : 'Non Secure Mode'
            ),
            RaisedButton(
              onPressed: _toggleScreenShot,
              child: const Text('Toggle Secure Mode'),
            ),
          ],
        ),
      ),
    );
  }

  Future<void> _toggleScreenShot() async {

        if (_isSecureScreen == true) {
            await FlutterWindowManager
                    .addFlags(FlutterWindowManager.FLAG_SECURE);
        } else {
            await FlutterWindowManager
                    .clearFlags(FlutterWindowManager.FLAG_SECURE);
        }

        setState(() {
            _isSecureScreen = !_isSecureScreen;
        });
    }
}

I personally prefer the native way and because native code is of one line only. By using native code, I become free from one plugin.

Natively in Android #

Let’s open the MainActivity.kt file and have a look at the file. Probably that might looks something similar to this one.

This file might look little different in your case because flutter recently removed some of the boilerplate code.

Case 1 [Newer Project] #

Now flutter provides this boilerplate code in MainActivity.kt file looks like this.

MainActivity.kt
package com.example.demo_app;

import io.flutter.embedding.android.FlutterActivity

class MainActivity: FlutterActivity() {

}

Case 2 [Older Project] #

In past, flutter used to provide this code in MainActivity.kt file.

MainActivity.kt
package com.example.demo_app;

import androidx.annotation.NonNull;
import io.flutter.embedding.android.FlutterActivity;
import io.flutter.embedding.engine.FlutterEngine;
import io.flutter.plugins.GeneratedPluginRegistrant;

class MainActivity: FlutterActivity() {
    override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
        GeneratedPluginRegistrant.registerWith(flutterEngine);
    }
}

For Case 1 Person #

As you have seen above that recent MainActivity.ky file, flutter has removed some code if you compare from previous. It means we need to include that code by yourself.

Add the missing code by seeing the case 2 code and then all of us will have the code.

For Case 2 Person #

There is only one line of code which can do this but in order to add that line we need to add three different imports.

Solution #

Let’s add some code and restrict the user from taking screenshot and screen recording.

MainActivity.kt
package com.example.demo_app;

import androidx.annotation.NonNull;
import io.flutter.embedding.android.FlutterActivity;
import io.flutter.embedding.engine.FlutterEngine;
import io.flutter.plugins.GeneratedPluginRegistrant;

// Added these three import lines
import android.view.WindowManager; 
import android.view.WindowManager.LayoutParams;
import android.os.Bundle;

class MainActivity: FlutterActivity() {
    override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
        GeneratedPluginRegistrant.registerWith(flutterEngine);
        // Added this line
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE);
    }
}

There are various flag and each flag has different capabilities.

iOS #

I don’t know exactly how to disable screenshot and screen recording in iOS.

I have some knowledge which is not very much helpful but can be used for securing. You can disable screenshot while App switcher(while switching from one app to other app). I learnt this from Internet and tested it on emulator.

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

}

As I don’t have iPhone or iPad, so if somehow make something then it will be difficult for me to test. So, I didn’t look on the internet because before telling to the world about something I need to test it and be sure it’s correct.

Conclusion #

Stopping user from taking screenshot or screen recoding is impossible but at some extend we can make it difficult for most of the normal users.

Although it does not guarantee 100% that user will not share but at some extend we make it secure.

Last updated at Wednesday, Dec 9, 2020 by Nitish Kumar Singh
comments powered by Disqus

Subscribe to our Newsletter


Tweet this article