Block screenshots in React Native for specific screens (Android)

Hey folks!
Today we will understand how we can disable screenshots and screen recordings on specific screens in React Native (Android). There can be screens in your app which have sensitive data and we need to not allow the user to take the screenshot.
We need to write Native Modules to achieve this.

Let’s do some coding now!

  1. Move to android/app/src/main/java/com/your-app-name/
  2. Create a file PreventScreenshotModule.java or any name you want.
package com.your-app-name;

import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.Promise;

import android.view.WindowManager;

import static com.facebook.react.bridge.UiThreadUtil.runOnUiThread;

public class PreventScreenshotModule extends ReactContextBaseJavaModule {
    private static final String PREVENT_SCREENSHOT_ERROR_CODE = "PREVENT_SCREENSHOT_ERROR_CODE";
    private final ReactApplicationContext reactContext;

    PreventScreenshotModule(ReactApplicationContext context) {
        super(context);
        reactContext = context;
    }

    @Override
    public String getName() {
        return "PreventScreenshotModule";
    }

    @ReactMethod
    public void forbid(Promise promise) {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                try {
                    getCurrentActivity().getWindow().addFlags(WindowManager.LayoutParams.FLAG_SECURE);
                    promise.resolve("Screenshot taking locked.");
                } catch(Exception e) {
                    promise.reject(PREVENT_SCREENSHOT_ERROR_CODE, "Forbid screenshot taking failure.");
                }
            }
        });
    }

    @ReactMethod
    public void allow(Promise promise) {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                try {
                    getCurrentActivity().getWindow().clearFlags(WindowManager.LayoutParams.FLAG_SECURE);
                    promise.resolve("Screenshot taking unlocked.");
                } catch (Exception e) {
                    promise.reject(PREVENT_SCREENSHOT_ERROR_CODE, "Allow screenshot taking failure.");
                }
            }
        });
    }
}

3. Now it’s time to create PreventScreenshotPackage.java in the same directory as above android/app/src/main/java/com/your-app-name/

package com.your-app-name;

import com.facebook.react.ReactPackage;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.uimanager.ViewManager;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;

public class PreventScreenshotPackage implements ReactPackage {

    @Override
    public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
        return Collections.emptyList();
    }

    @Override
    public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
        return Arrays.<NativeModule>asList(new PreventScreenshotModule(reactContext));
    }
}

4. Add this package to your MainApplication.java

@Override
protected List<ReactPackage> getPackages() {
    @SuppressWarnings("UnnecessaryLocalVariable")
    List<ReactPackage> packages = new PackageList(this).getPackages();
    packages.add(new PreventScreenshotPackage());

    return packages;
}

Now it’s time to access the methods defined in PreventScreenshotModule.java in your component/screen.

To access this, we’ll create a custom hook.

5. Navigate to src/hooks/ and create a hook with whatever name you like. I’m creating useCustomScreenshot.js

import { useEffect } from 'react';
import { NativeModules } from "react-native";
import { useNavigation } from "@react-navigation/native";

const useCustomScreenshot = () => {
  const navigation = useNavigation();

  const forbidScreenshot = async () => {
    try {
      const result = await NativeModules.PreventScreenshotModule.forbid();
      console.log(result);
    } catch (e) {
      console.log(e);
    }
  };

  const allowScreenshot = async () => {
    try {
      const result = await NativeModules.PreventScreenshotModule.allow();
      console.log(result);
    } catch (e) {
      console.log(e);
    }
  };

  useEffect(() => {
    navigation.addListener('blur', () => {
      // when user moves to some other screen 'blur' event will be triggered, 
      // again enable screenshot
      allowScreenshot();
    });
  }, []);

  return { allowScreenshot, forbidScreenshot };
};

export default useCustomScreenshot;

6. Now move to the screen where you need to disable the screen and use this piece of code there.

import React from "react";
import { View } from "react-native";
import { useFocusEffect } from "@react-navigation/native";

const HomeScreen = () => {
  const { forbidScreenshot } = useCustomScreenshot();

  useFocusEffect(
    useCallback(() => {
      forbidScreenshot();
    }, [])
  );

  return (
    <View style={styles.container}>
      <Text>Home</Text>
    </View>
  );
};

Done! This is all you need to make things work.

Note: This will also record a black screen while screen recording and show a black screen when the screen is shared on a call.

Happy Coding!

Latest

SENTRY integration in your React Native App for Error/Crash tracking

Sentry captures data by using an SDK within your...

Recall the concepts of useCallback.

useCallback hook is one of the best hooks offered...

Value of Comments in the code!!

During my journey of Software Development, I am always...

YOLO:Bullet Paced Algorithm

http://sh017.hostgator.tempwebhost.net/media/33949d0e61af4b50f374c534713f56b3 According to world health organization, more than 1.35 million...

Featured

Developing Enterprise Application in Node.js – CJS Vs ESM

Node.js is a popular runtime environment for building server-side...

Integrating your web react applications with their React Native(android and IOS) apps using QR code

Integrating a web application with Android and iOS apps...

YOLO: Bullet Paced Algorithm – popular choice for object detection in autonomous vehicles 

According to world health organization, more than 1.35 million...

Importance of Test Scalar Tool

TestScalar is quick to access, convenient to execute, easy to track. Our popular web-based test planning software lets you focus on what matters: meeting...

From Requirements to Reporting: How to Use a Test Case Management Tool to Ace Your Software Testing

The Software Testing Life Cycle (STLC) is a process that describes the stages of testing software. It includes planning, design, execution, and reporting of...

YOLO:Bullet Paced Algorithm

http://sh017.hostgator.tempwebhost.net/media/33949d0e61af4b50f374c534713f56b3 According to world health organization, more than 1.35 million people die every year because of vehicle accidents . Vehicle safety features started with passive safety...

LEAVE A REPLY

Please enter your comment!
Please enter your name here