Phát hiện và phòng ngừa quay trộm màn hình trong iOS 11

Giả dụ chúng ta có một ứng dụng trả phí để xem video, và với tính năng quay màn hình của iOS 11 thì những kẻ ăn cắp bản quyền hoàn toàn có thể thu lại video đó bằng tính năng này. Do vậy bài viết này tôi sẽ chia sẻ với các bạn cách để xử lý vấn đề trên. (Lưu ý: Ở đây tôi sử dụng code Objective-C được lấy từ project cũ, tuy nhiên thì nó khá là đơn giản và bạn có thể dễ dàng chuyển sang Swift.)

 

Yêu cầu của tôi là muốn hạn chế người dùng quay lại màn hình đang phát video của mình. Tôi đã không thể tìm ra một giải pháp nào chống lại việc quay/chụp ảnh lại màn hình. Đây là mức độ xử lý ở tầng OS và không thể custom/override lại được.

Do đó cách duy nhất là dừng player lại nếu thiết bị phát sinh hiện tượng quay màn hình, và thật may mắn là iOS cung cấp giải pháp cho việc này. Từ iOS 11 trở đi thì class UIScreen đã có một instance property có tên là captured (isCaptured trong Swift). Đây là một biến boolean có vai trò xác định xem nội dung của màn hình có bị sao chép lại hay không.

//Obj-C
@property(nonatomic, readonly, getter=isCaptured) BOOL captured;
// swift
var isCaptured: Bool { get }
Bạn cũng có thể sử dụng property  mirroredScreen có nhiệm vụ phat hiện nếu màn hình đang được xuất ra thiết bị khác. 

Vậy ý tưởng ở đây là chúng ta sẽ kiểm tra biến các biến bool này và stop player lại nếu giá trị của chúng là true.

Chúng ta sẽ tạo một notification có vai trò thông báo khi biến bool này có giá trị true.

//
//  ScreenRecordingDetector.h
//  ScreenCaptureDetector
//
//  Created by Abhilash on 29/12/17.
//  Copyright © 2017 Abhilash. All rights reserved.
//

/*
ScreenRecordingDetector checks for screen capturing as well as airplay mirroring
*/

#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>

extern NSString *kScreenRecordingDetectorRecordingStatusChangedNotification;

@interface ScreenRecordingDetector : NSObject

+(instancetype)sharedInstance;
+ (void)triggerDetectorTimer;
+ (void)stopDetectorTimer;
- (BOOL)isRecording;

@end
//
//  ScreenRecordingDetector.m
//  ScreenCaptureDetector
//
//  Created by Abhilash on 29/12/17.
//  Copyright © 2017 Abhilash. All rights reserved.
//

#import "ScreenRecordingDetector.h"
float const kScreenRecordingDetectorTimerInterval = 1.0;
NSString *kScreenRecordingDetectorRecordingStatusChangedNotification = @"kScreenRecordingDetectorRecordingStatusChangedNotification";

@interface ScreenRecordingDetector()

@property BOOL lastRecordingState;
@property NSTimer *timer;

@end
@implementation ScreenRecordingDetector


+ (instancetype)sharedInstance {
    static ScreenRecordingDetector *sharedInstance = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        sharedInstance = [[self alloc] init];
    });
    return sharedInstance;
}
- (id)init {
    if (self = [super init]) {
        // do some init stuff here..
        self.lastRecordingState = NO; // initially the recording state is 'NO'. This is the default state.
        self.timer = NULL;
    }
    return self;
}
- (BOOL)isRecording {
    for (UIScreen *screen in UIScreen.screens) {
        if ([screen respondsToSelector:@selector(isCaptured)]) {
            // iOS 11+ has isCaptured method.
            if ([screen performSelector:@selector(isCaptured)]) {
                return YES; // screen capture is active
            } else if (screen.mirroredScreen) {
                return YES; // mirroring is active
            }
        } else {
            // iOS version below 11.0
            if (screen.mirroredScreen)
                return YES;
        }
    }
    return NO;
}
+ (void)triggerDetectorTimer {

    ScreenRecordingDetector *detector = [ScreenRecordingDetector sharedInstance];
    if (detector.timer) {
        [self stopDetectorTimer];
    }
    detector.timer = [NSTimer scheduledTimerWithTimeInterval:kScreenRecordingDetectorTimerInterval
                                                           target:detector
                                                         selector:@selector(checkCurrentRecordingStatus:)
                                                         userInfo:nil
                                                          repeats:YES];
}
- (void)checkCurrentRecordingStatus:(NSTimer *)timer {
    BOOL isRecording = [self isRecording];
    if (isRecording != self.lastRecordingState) {
        NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
        [center postNotificationName: kScreenRecordingDetectorRecordingStatusChangedNotification object:nil];
    }
    self.lastRecordingState = isRecording;
}
+ (void)stopDetectorTimer {
    ScreenRecordingDetector *detector = [ScreenRecordingDetector sharedInstance];
    if (detector.timer) {
        [detector.timer invalidate];
        detector.timer = NULL;
    }
}
@end

Sau đó thì chúng ta chỉ cần quan sát biến kScreenRecordingDetectorRecordingStatusChangedNotification và kiểm tra nếu method  isRecording trả về true hoặc false.

Link source code của bài viết:  GITHUB 

 

 

 

Nguồn bài viết: https://medium.com/@abhimuralidharan/detecting-screen-capturing-in-ios-11-cca15881c785

Khóa học lập trình di động tại Techmaster:

Để cài đặt MacOSX lên phần cứng không phải Apple liên hệ chuyên gia cài Hackintosh:

  • Nguyễn Minh Sơn: 01287065634
  • Huỳnh Minh Sơn: 0936225565
  • Website: caidatmacos.com

Bước ngoặt tỷ đô của các ứng dụng di động Bước ngoặt tỷ đô của các ứng dụng di động Techmaster team Blog Home Khai giảng lớp lập trình iOS Swift số 5  - giảng viên Nguyễn Đức Hoàng - Ngô Phan Hải Khai giảng lớp lập trình iOS Swift số 5 - giảng viên Nguyễn Đức Hoàng - Ngô Phan Hải Techmaster team
Nguyễn Duy Khánh

iOS Developer, Former Student and Content Editor of TechMaster