在 React Native App 中禁用屏幕 Capture/ScreenShot
Disable Screen Capture/ScreenShot in React Native App
我遇到了一些针对 ios 和 Android 的解决方案,以防止屏幕捕获和截屏。但是如何在 React Native 中禁用屏幕捕获?
防止截屏
Android
通过 setFlag secure 防止捕获屏幕
getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE);
如果你想删除安全标志
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_SECURE);
Android
里面/android/app/src/main/java/com/{Project_Name}/MainActivity.java
您可以添加以下行。通过 setFlag FLAG_SECURE
防止截屏,以下面的代码为例:
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);
}
稍后当您想要删除安全标志时
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_SECURE);
iOS
在AppDelegate.m
中叠加屏幕,举个例子:
- (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];
}];
}
在android
/android/app/src/main/java/com/{Project_Name}/MainActivity.java
写一些导入语句
import android.os.Bundle;
import android.view.WindowManager;
通过 MainActivity 中代码下方的 setFlag 安全使用来防止捕获屏幕 class
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE);
}
所以在 React Native 平台上构建 iOS 方面的工作很少。所以请耐心看完下面的做法
我正在使用 react-native-video 包来播放媒体。如果用户启用了屏幕录制,我的要求是显示微调器。
从https://developer.apple.com/documentation/uikit/uiscreen/2921651-captured?language=objc了解到captured
属性设置为YES。我在 AppDelegate.m 中添加了观察者,在 didFinishLaunchingWithOptions
方法下。
[[UIScreen mainScreen] addObserver:self forKeyPath:@"captured" options:NSKeyValueObservingOptionNew context:nil];
由于 RN 允许与 Native 模块通信,我决定添加网桥以便在 capture
标志设置为 YES 时通知。
我创建了两个文件 ScreenRecordingNotification.h 和 .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 */
.m 看起来像
#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
在 AppDelegate 中导入 #import "ScreenCaptureNotification.h"
并添加以下方法。
- (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];
}
}
}
并在didFinishLaunchingWithOptions
中添加[[UIScreen mainScreen] addObserver:self forKeyPath:@"captured" options:NSKeyValueObservingOptionNew context:nil];
。
iOS 侧的更改到此结束。
- 现在您需要在 .js 文件中添加 Listener 以通知 iOS 发送。收到通知后,您可以决定如何处理它。大致如下所示。
addListener() {
let bridge = new NativeEventEmitter(NativeModules.ScreenCaptureNotification);
this.screenCaptureEnabled = bridge.addListener("isScreenCaptureEnabled",res => {
this.setState({ screenCapture: true })
})
}
和
render() {
if (this.state.screenCapture) {
//Show spinner
return <Spinner />
}
return (
<Vido uri ... />
)
}
我愿意接受对此 post 进行更改的建议。如果post对您有帮助,别忘了点个赞。
- 在下面的 appDelegate.m 中添加此行
didFinishLaunchingWithOptions 当用户正在录制屏幕时退出应用程序并且如果正在录制屏幕则应用程序未打开
仅用于 ios react-native
您的应用中的屏幕截图错误
把这个完整的代码放在你的
android/app/src/main/javacom/mainactivity/java
package com.Yourprojectname;
import com.facebook.react.ReactActivity;
import android.os.Bundle;
import android.view.WindowManager;
public class MainActivity extends ReactActivity {
@Override
protected String getMainComponentName() {
return "YOUR PROJECT NAME";
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().setFlags(
WindowManager.LayoutParams.FLAG_SECURE,
WindowManager.LayoutParams.FLAG_SECURE
);}}
我遇到了一些针对 ios 和 Android 的解决方案,以防止屏幕捕获和截屏。但是如何在 React Native 中禁用屏幕捕获?
防止截屏
Android
通过 setFlag secure 防止捕获屏幕
getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE);
如果你想删除安全标志
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_SECURE);
Android
里面/android/app/src/main/java/com/{Project_Name}/MainActivity.java
您可以添加以下行。通过 setFlag FLAG_SECURE
防止截屏,以下面的代码为例:
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);
}
稍后当您想要删除安全标志时
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_SECURE);
iOS
在AppDelegate.m
中叠加屏幕,举个例子:
- (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];
}];
}
在android
/android/app/src/main/java/com/{Project_Name}/MainActivity.java
写一些导入语句
import android.os.Bundle;
import android.view.WindowManager;
通过 MainActivity 中代码下方的 setFlag 安全使用来防止捕获屏幕 class
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE);
}
所以在 React Native 平台上构建 iOS 方面的工作很少。所以请耐心看完下面的做法
我正在使用 react-native-video 包来播放媒体。如果用户启用了屏幕录制,我的要求是显示微调器。
从https://developer.apple.com/documentation/uikit/uiscreen/2921651-captured?language=objc了解到
captured
属性设置为YES。我在 AppDelegate.m 中添加了观察者,在didFinishLaunchingWithOptions
方法下。[[UIScreen mainScreen] addObserver:self forKeyPath:@"captured" options:NSKeyValueObservingOptionNew context:nil];
由于 RN 允许与 Native 模块通信,我决定添加网桥以便在
capture
标志设置为 YES 时通知。
我创建了两个文件 ScreenRecordingNotification.h 和 .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 */
.m 看起来像
#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
在 AppDelegate 中导入
#import "ScreenCaptureNotification.h"
并添加以下方法。- (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]; } } }
并在didFinishLaunchingWithOptions
中添加[[UIScreen mainScreen] addObserver:self forKeyPath:@"captured" options:NSKeyValueObservingOptionNew context:nil];
。
iOS 侧的更改到此结束。
- 现在您需要在 .js 文件中添加 Listener 以通知 iOS 发送。收到通知后,您可以决定如何处理它。大致如下所示。
addListener() { let bridge = new NativeEventEmitter(NativeModules.ScreenCaptureNotification); this.screenCaptureEnabled = bridge.addListener("isScreenCaptureEnabled",res => { this.setState({ screenCapture: true }) }) }
和
render() {
if (this.state.screenCapture) {
//Show spinner
return <Spinner />
}
return (
<Vido uri ... />
)
}
我愿意接受对此 post 进行更改的建议。如果post对您有帮助,别忘了点个赞。
- 在下面的 appDelegate.m 中添加此行 didFinishLaunchingWithOptions 当用户正在录制屏幕时退出应用程序并且如果正在录制屏幕则应用程序未打开 仅用于 ios react-native
您的应用中的屏幕截图错误 把这个完整的代码放在你的
android/app/src/main/javacom/mainactivity/java
package com.Yourprojectname;
import com.facebook.react.ReactActivity;
import android.os.Bundle;
import android.view.WindowManager;
public class MainActivity extends ReactActivity {
@Override
protected String getMainComponentName() {
return "YOUR PROJECT NAME";
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().setFlags(
WindowManager.LayoutParams.FLAG_SECURE,
WindowManager.LayoutParams.FLAG_SECURE
);}}