I have came across few solutions specific for ios and Android to prevent screen-capturing and taking screenshots. But how do i disable screen-capturing in react native?
The Project Settings dialog box appears. From the left pane, expand the Native tab, and then select the Android Mobile/Tablet sub-tab. In the Miscellaneous section, enable the Disable Application Screenshot check box. Click Done.
Why Do Some Apps Restrict Screenshots? Annoying as it is, developers don't restrict screenshots for no reason. Be it privacy or security, there's always a grain of reason for doing this. Most banking and payment apps block screenshots for security reasons.
Inside /android/app/src/main/java/com/{Project_Name}/MainActivity.java
you may add the following lines. Prevent capture screen by setFlag FLAG_SECURE
, use code below as an example:
import android.os.Bundle;
import android.view.WindowManager;
...
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE);
}
later when you want to remove secure flag
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_SECURE);
overlay screen in AppDelegate.m
, take this example:
- (void)applicationWillResignActive:(UIApplication *)application {
// fill screen with our own colour
UIView *colourView = [[UIView alloc]initWithFrame:self.window.frame];
colourView.backgroundColor = [UIColor whiteColor];
colourView.tag = 1234;
colourView.alpha = 0;
[self.window addSubview:colourView];
[self.window bringSubviewToFront:colourView];
// fade in the view
[UIView animateWithDuration:0.5 animations:^{
colourView.alpha = 1;
}];
}
- (void)applicationDidBecomeActive:(UIApplication *)application {
// grab a reference to our coloured view
UIView *colourView = [self.window viewWithTag:1234];
// fade away colour view from main view
[UIView animateWithDuration:0.5 animations:^{
colourView.alpha = 0;
} completion:^(BOOL finished) {
// remove when finished fading
[colourView removeFromSuperview];
}];
}
So there is little work for the iOS side build on React Native platform. So be patient with me to read the following approach.
I am using the react-native-video package for playing media. My requirement was to show spinner if user has screen recording enabled.
From https://developer.apple.com/documentation/uikit/uiscreen/2921651-captured?language=objc I understood that captured
property is set to YES. I added observer in AppDelegate.m, under didFinishLaunchingWithOptions
method.
[[UIScreen mainScreen] addObserver:self forKeyPath:@"captured" options:NSKeyValueObservingOptionNew context:nil];
Since RN allows communication with Native modules, I decided to add bridge so notify when capture
flag is set to YES.
I created two files ScreenRecordingNotification.h and .m
.h
#import <React/RCTBridgeModule.h>
#import <React/RCTEventEmitter.h>
#ifndef ScreenCaptureNotification_h
#define ScreenCaptureNotification_h
@interface ScreenCaptureNotification : RCTEventEmitter <RCTBridgeModule>
-(void) isScreenCaptureEnabled:(BOOL)isCaptured;
@end
#endif /* ScreenCaptureNotification_h */
and .m looks like
#import <Foundation/Foundation.h>
#import "ScreenCaptureNotification.h"
#import <React/RCTLog.h>
@implementation ScreenCaptureNotification
+ (id)allocWithZone:(NSZone *)zone {
static ScreenCaptureNotification *sharedInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [super allocWithZone:zone];
});
return sharedInstance;
}
RCT_EXPORT_MODULE();
- (NSArray<NSString *> *)supportedEvents {
return @[
@"isScreenCaptureEnabled"];
}
-(void) isScreenCaptureEnabled:(BOOL)isCaptured {
[self sendEventWithName:@"isScreenCaptureEnabled" body:@{@"value": @(isCaptured)}];
}
@end
import #import "ScreenCaptureNotification.h"
in AppDelegate and added the following method.
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
if ([keyPath isEqualToString:@"captured"]){
NSLog(@"Screen Capture is Enabled");
RCTLog(@"Screen Capture is Enabled");
if (@available(iOS 11.0, *)) {
ScreenCaptureNotification *manager = [ScreenCaptureNotification allocWithZone: nil];
[manager isScreenCaptureEnabled:UIScreen.mainScreen.isCaptured];
}
}
}
And also add [[UIScreen mainScreen] addObserver:self forKeyPath:@"captured" options:NSKeyValueObservingOptionNew context:nil];
in didFinishLaunchingWithOptions
.
This concludes changes at iOS side.
addListener() { let bridge = new NativeEventEmitter(NativeModules.ScreenCaptureNotification); this.screenCaptureEnabled = bridge.addListener("isScreenCaptureEnabled",res => { this.setState({ screenCapture: true }) }) }
and
render() {
if (this.state.screenCapture) {
//Show spinner
return <Spinner />
}
return (
<Vido uri ... />
)
}
I am open to suggestions to make changes to this post. Don't forget to upvote if this post helped you.
Prevent Capture Screen
Android
Prevent capture screen by setFlag secure
getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE);
If you want to remove flag secure
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_SECURE);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With