【问题标题】:Disable Screen Capture/ScreenShot in React Native App在 React Native App 中禁用屏幕捕获/ScreenShot
【发布时间】:2019-07-26 15:21:08
【问题描述】:

我遇到了一些专门针对 ios 和 Android 的解决方案,以防止截屏和截屏。但是如何在 react native 中禁用屏幕捕获?

【问题讨论】:

    标签: android ios reactjs react-native screenshot


    【解决方案1】:

    安卓

    内部/android/app/src/main/java/com/{Project_Name}/MainActivity.java

    您可以添加以下行。通过setFlagFLAG_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];
        }];
    }
    

    【讨论】:

    • 你能解释一下iOS解决方案的作用吗?在我的应用上,它只会使应用淡入白屏,从而使应用从后台“无法截屏”,但您仍然可以在应用内截屏
    • 如果转到安全消息屏幕截图不可用,如何处理,否则应该可用。
    • 此解决方案仅在应用程序处于后台时有效。对我来说,当用户截屏时不会调用 applicationWillResignActive
    • import android.os.Bundle; 在 android 顶部添加这一行
    【解决方案2】:

    因此,iOS 端在 React Native 平台上构建的工作很少。所以请耐心阅读以下方法。

    我正在使用 react-native-video 包播放媒体。如果用户启用了屏幕录制,我的要求是显示微调器。

    1. 来自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];

    2. 由于 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
    
    1. 在 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 端的更改到此结束。

    1. 现在您需要在 .js 文件中添加监听器,以便 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 ... /> 
      )
    }
    

    我愿意接受对这篇文章进行更改的建议。如果这篇文章对你有帮助,别忘了点赞。

    【讨论】:

    • 如果用户尝试截屏,捕获属性是否为真?
    • @DhruvilShah 你应该试一试。我尝试了屏幕录制及其按预期工作。
    • @Naren 我试过你的解决方案,但它不起作用,你能分享一下功能组件中 react-native 端的代码
    • @vijaykahar 明白这一点。 React Native 和 iOS 可以使用 bridge 进行通信。当你从 iOS 接收到 React Native 的标志时,你在 redux 中设置标志,它会强制应用重新渲染。在 react 的类文件中,添加 mapStateToProps 以从 redux 获取更新的值。我不能分享代码,但如果你分享你的,我可以检查一下。
    • 显示最近的问题未定义符号:_OBJC_CLASS_$_ScreenCaptureNotification 在 Xcode 12.2 上出现此错误
    【解决方案3】:

    防止截屏

    安卓

    通过 setFlag secure 防止截屏

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

    如果你想删除安全标志

    getWindow().clearFlags(WindowManager.LayoutParams.FLAG_SECURE);
    

    【讨论】:

    • 感谢您的回复。 IOS呢?
    • 你至少可以提一下我们应该把那行代码放在哪里。
    • 这个答案不够清楚,你没有说明我们应该在哪里插入那行代码!
    • @BurimSyla 看看我的答案,以获得该行代码的确切位置。
    【解决方案4】:

    在安卓中

    /android/app/src/main/java/com/{Project_Name}/MainActivity.java

    写一些导入语句

    import android.os.Bundle;
    import android.view.WindowManager;
    

    在 MainActivity 类中通过 setFlag 安全使用下面的代码来防止捕获屏幕

    @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE);
        }
    

    【讨论】:

      【解决方案5】:
      1. 在下面的 appDelegate.m 中添加这一行 didFinishLaunchingWithOptions 当用户正在屏幕记录退出应用程序并且屏幕记录在应用程序未打开时 仅适用于 ios react-native

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-08-30
        • 1970-01-01
        • 2018-06-07
        • 2018-11-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多