Saltar al contenido principal

W - I - Evitar capturas de pantalla React-Native

Hay dos enfoques que puede tomar. El primero es prohibir la captura de pantalla en toda la aplicación (más fácil de implementar) y el segundo es manejar los métodos prohibir y permitir desde el código JavaScript (este enfoque requiere que implemente un puente de Android a código JavaScript).

Configuración Android

Prohibir la captura de pantalla en toda la aplicación

Agregue el siguiente código con signos + al archivo MainActivity.java ubicado en:

android/app/src/main/java/com/your-app name/MainActivity.java

Código

package com.your-app-name;

import com.facebook.react.ReactActivity;

+ import android.view.WindowManager;

+ import android.os.Bundle;

public class MainActivity extends ReactActivity {

/**
Returns the name of the main component registered from JavaScript. This is used to schedule
rendering of the component.
*/

@Override
protected String getMainComponentName() {
return "your-app-name";
}

+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+

+ getWindow().setFlags(
+ WindowManager.LayoutParams.FLAG_SECURE,
+ WindowManager.LayoutParams.FLAG_SECURE
+ );
+ }

}

La captura de pantalla está bloqueada ahora en toda la aplicación.

Permitir la captura de pantalla seleccionas usando código JavaScript

En primer lugar, cree un nuevo archivo en esta ruta:

android/app/src/main/java/com/your-app-name/PreventScreenshotModule.java

Nombré mi módulo pero, por supuesto, el nombre del módulo depende del que se le ponga

PreventScreenshotModule.java

Nota: Cambie el nombre real de la aplicación. También asegúrese de cambiar el nombre de los campos "PreventScreenshotModule" en este código en caso de que elija un nombre diferente. Siéntase libre de cambiar los mensajes de salida de Promises también

your-app-name

Código

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("Done. 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("Done. Screenshot taking unlocked.");
} catch (Exception e) {
promise.reject(PREVENT_SCREENSHOT_ERROR_CODE, "Allow screenshot taking failure.");
}
}
});

}

}

Cree otro archivo (de nuevo, el nombre depende de usted) en la misma ruta:

android/app/src/main/java/com/your-app-name/CustomPreventScreenshotPackage.java

Nota: Cambie el nombre real de la aplicación. También asegúrese de editar todos los campos "CustomPreventScreenshotPackage" en este código en caso de que elija un nombre de paquete diferente

your-app-name

Nota: Pegue el nombre de su módulo si lo cambió de "PreventScreenshotModule"

Código

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 CustomPreventScreenshotPackage 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));
}

}

Abra el archivo MainApplication.java ubicado debajo de esta ruta de acceso android/app/src/main/java/com/your-app-name/MainApplication.java

Agregue la importación sobre el archivo y agregue el paquete al método en la clase MainApplication, siga los signos + en el código siguiente.

getPackages()

Nota: Cambie el nombre del paquete si eligió un nombre diferente (tanto en la sección de importación como en el código real).

Código

+

import com.prevent_screenshot.CustomPreventScreenshotPackage;

public class MainApplication extends Application implements ReactApplication {

private final ReactNativeHost mReactNativeHost =
new ReactNativeHost(this) {

...

@Override

protected List<ReactPackage> getPackages() {

@SuppressWarnings("UnnecessaryLocalVariable")
List<ReactPackage> packages = new PackageList(this).getPackages();
// Packages that cannot be autolinked yet can be added manually here, for example:
// packages.add(new MyReactNativePackage());
+ packages.add(new CustomPreventScreenshotPackage());
return packages;

}

Ahora puede acceder a los métodos allow y forbid dentro del código JavaScript; El nombre del módulo depende de su nombre, en este caso es de

PreventScreenshotModule

NativeModules

Ejemplo:

Código

import { NativeModules } from 'react-native';

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

const allowFunction = async () => {

try {

const result = await NativeModules.PreventScreenshotModule.allow();
console.log(result);

} catch (e) {
console.log(e);
}
}

Configuración para iOS

Por comodidad se aconseja abrir los ficheros swift desde XCode para manejar sin mayor problema el código.

Vamos a abrir el fichero AppDelegate.swift de nuestro proyecto iOS.

Dentro de este fichero y dentro de la clase AppDelegate vamos a crear dos funciones que directamente, no evitarán que el usuario pueda hacer capturas de pantalla pero lo que haremos será que cuando la aplicación detecte que está en segundo plano, cambiará la pantalla por una vista no visible con fondo negro.

Código

@UIApplicationMain

class AppDelegate: UIResponder, UIApplicationDelegate, RCTBridgeDelegate {

···

func applicationWillResignActive(_ application: UIApplication) {
self.window?.isHidden = true;
}

func applicationDidBecomeActive(_ application: UIApplication) {
self.window?.isHidden = false;
}
}

// En IOS no se puede evitar la captura de pantalla, solo de grabación

// En android se puede ambos

//*** INSTALL */

expo install expo-screen-capture
expo install expo-permissions
import React, { useEffect } from 'react'
import { usePreventScreenCapture, addScreenshotListener } from 'expo-screen-capture';
import * as Permissions from expo-permissions

export const Screen = () => {
usePreventScreenCapture();

const getCameraCapture = async() => {
const { status } = await Permissions.askAsync(
Permissions.CAMERA_ROLL
)

if (status === 'granted') {

addScreenshotListener( () => {

alert('You took a screenshot')
})
}
}

useEffect( () => {
getCameraCapture()
}, [])

return (
<div>screen</div>
)

}

Paquetes

https://www.npmjs.com/package/react-native-screenshot-prevent

https://www.npmjs.com/package/react-native-screenshot-prevention