iOS6, iOS7에서 사용자의 화면캡쳐(Screenshot) 감지하기

불현듯 Snapchat이 사용자의 화면 캡쳐를 어떻게 감지하는지 궁금해졌다.  구글링 및 간단한 데모를 통해 알아본 바를 정리한다.

iOS 디바이스는 홈 + 전원 버튼을 같이 누름으로써 디바이스에 보여지고 있는 화면을 사진으로 앨범에 저장할 수 있다.

사용자의 이러한 행동을 코드 내에서 감지할 수 있는 방법은 iOS 7 전후가 다르다.

iOS 7 이전 버전에서는 사용자가 스크린 캡쳐를 하면 화면의 touch 행위가 취소된다. touch가 취소되면 touchesCancelled:withEvent: 메소드가 호출되는데 이를 이용하면 사용자의 스크린 캡쳐를 감지할 수 있다.

Snapchat에서 사진을 보려면 화면을 계속 누르고 있어야 한다. 화면을 계속 누르는 행위를 하고 있기 때문에, 사진을 보는 중에 스크린 캡쳐가 발생하면 touch 취소 이벤트가 발생하게 된다.

iOS 7에서 사용자의 스크린 캡쳐는 touch에 아무런 영향을 미치지 않도록 바뀌었다. 따라서 위에서 설명한 방식으로는 스크린 캡쳐를 감지할 수 없다. 대신 Apple은 UIApplicationUserDidTakeScreenshotNotification을 별도로 정의하여 좀 더 명확하게 사용자의 스크린 캡쳐를 감지할 수 있도록 하였다.

UIApplicationUserDidTakeScreenshotNotification

Posted when the user presses the Home and Lock buttons to take a screenshot.

This notification does not contain a userInfo dictionary. This notification is posted after the screenshot is taken.

Availability

  • Available in iOS 7.0 and later.

Declared In

UIApplication.h

아래는 확인을 위해 작성한 데모 코드 중 일부다. (싱글뷰 프로젝트를 하나 만들었다. 기본으로 생성되는 UIViewController의 내부 코드다.)

- (void)viewDidLoad{

[super viewDidLoad];

// Do any additional setup after loading the view from its nib.

    // iOS7 판단
    if(floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_6_1){

       // UIApplicationDidTakeScreenshotNotification을 등록, iOS7만 지원
       [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didUserTakenScreenShot:) name:UIApplicationUserDidTakeScreenshotNotification object:nil];

    }

}

// NSNotificationCenter에 등록한 selector
// UIApplicationUserDidTakeScreenshotNotification이 발생하면 호출됨
-(void)didUserTakenScreenShot:(NSNotification*)noti{

    // 간단히 alert을 띄움
    [self showScreenShotAlert];

}

-(void)showScreenShotAlert{

    UIAlertView *alert = [[UIAlertView alloc]initWithTitle:nil message:@"User did take screen shot" delegate:nil cancelButtonTitle:@"ok" otherButtonTitles:nil, nil];

    [alert show];

}

// 화면을 누르면 색을 변화시킴
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{

    self.view.backgroundColor = [UIColor yellowColor];

}

// iOS7 이전에서 화면을 누르고 있는 중에 스크린 캡쳐가 발생하면 호출됨
-(void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event{

    // 색상을 검은색으로 바꿈. 디바이스에 저장되는 사진도 막을 수 있는지 확인해보기 위해 배경 색상을 변경
    self.view.backgroundColor = [UIColor blackColor];

}

// 화면에서 손을 떼면 호출됨.
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{

    // 실수로 손을 뗀 후 스크린 캡쳐를 하게 되는 경우를 확인하기 위해 별도의 색상을 지정.
    self.view.backgroundColor = [UIColor whiteColor];

}

테스트 코드는 간단하다. (iOS6와 iOS7 모두 테스트)

iOS 7에서 스크린 캡쳐를 하면 didUserTakenScreenShot:이 호출되고 alert이 발생한다. touchesCancelled:withEvent:는 호출되지 않는다.

iOS 6에서는 화면을 누르면 배경색이 노란색으로 변경되고, 손을 떼지 않은 상태에서 스크린 캡쳐를 하면 배경색이 검정색으로 바뀌면서 검정색 화면이 앨범에 저장된다. 만약 UIImageView가 있다면, 배경색을 검정색으로 바꾸는 대신 removeFromSuperview를 통해 이미지가 저장되는 것을 막을 수 있다.

iOS 6에서는 이처럼 화면이 저장되기 전의 화면을 컨트롤 할 수 있지만 (테스트 결과 100%는 아닌 것 같다. 가끔 노란색 화면이 앨범에 저장되기도 하였다.) , iOS 7에서는 화면이 그대로 앨범에 저장된다. UIApplicationUserDidTakeScreenshotNotification이 스크린캡쳐 후에 호출되기 때문이다. iOS 7에서 캡쳐되는 화면을 변경하는 방법은 아직 없는 듯 하다. (아직 발견되지 않은 듯 하다.)

* Reference

Advertisements
Leave a comment

2 Comments

  1. Elvis

     /  April 29, 2015

    좋은 정보 감사합니다.
    위의 방법으로 하면 정말 아이폰에서 화면캡쳐를 방지할 수 있나요?
    행복하세요~

    Reply
    • iOS7 이후론 ‘방지’가 아닌 ‘감지’가 가능하다는 것으로 알고 있습니다. 화면캡쳐는 막지 못하되 캡쳐한 사실을 알 수 있는 것이죠.

      Reply

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: