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!
- Move to android/app/src/main/java/com/your-app-name/
- 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!