Pages

Tuesday, May 13, 2014

Detect User take Screenshots when app is active


Many a times it may happen that during iOS application development, we may require to know if user has taken any screenshot in the application’s active state or not. We may consider it as a security reason or as a feature of iOS app to inform the user that you have taken a snap of application.

In iOS6  or ealier when a screenshot is taken, it cancels all the touches on the screen. So using this technique, you can detect the screenshots. All you have to do is, implement the UIView touches cancel method or the UILongPressGestureRecognizer method and
you have to make user touch the screen. So when user will take screenshot, the touch by the user will get cancelled and the UIView touchesCancel method (or long press action method with cancel state) will be called. So in that method, you can take the relevant steps to protect your data.

Lets first see how can implements this

    •    In the AppDelegate.m class add Long press gesture to the window in the     application’s didFinishLaunching method.
    •    Considering user has touched the screen. Now when the screenshot will be taken, the touch will be cancelled and the long press action method will be called with the cancelled state.
    •    But you have to keep in mind that the touch can also be cancelled when the state of the application will resign the active state. So for this, you can maintain the state of the application and accordingly work around. You can take a flag and set/reset it based on application’s state and use that flag in the long press action method. If it is TRUE, then only consider the screenshot detection.
    •    Here is the implementation,

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];

    self.viewController = [[ViewController alloc] initWithNibName:@"ViewController" bundle:nil];
    self.window.rootViewController = self.viewController;

    self.isActive = YES; // this flag will indicate whether the application is in active state or not

    UILongPressGestureRecognizer * gest = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPress:)];
    gest.minimumPressDuration = 0.1;
    [self.window addGestureRecognizer:gest];

    [self.window makeKeyAndVisible];
    return YES;
}

- (void)longPress:(UIGestureRecognizer *)gest {

    if (gest.state == UIGestureRecognizerStateCancelled && self.isActive) {
        UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"Detected" message:@"You have captured a screenshot!" delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles:nil];
        [alert show];
    }

}

- (void)applicationWillResignActive:(UIApplication *)application
{
    self.isActive = NO;
}

- (void)applicationDidEnterBackground:(UIApplication *)application
{
    self.isActive = YES;
}

This solution will work on all iOS version but not in iOS 7. In all the iOS versions below iOS 7, the active touches are getting cancelled whenever the screenshot is taken. But now in the latest released iOS 7, the active touches are no longer getting cancelled so this technique is not work. However, iOS 7 provides a brand-new notification for this event: UIApplicationUserDidTakeScreenshotNotification. Just subscribe to it as usual to know when a screenshot was taken.Notification will be posted when user presses Home + Sleep to print screen.


- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
  [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(userDidTakeScreenshot:) name:UIApplicationUserDidTakeScreenshotNotification object:nil];

  return YES;
}

- (void)userDidTakeScreenshot:(NSNotification *)notification
{

    NSLog(@"userDidTakeScreenshot");
}

but disadvantage of this method is fire after the screen sort is capture.

No comments:

Post a Comment