[iOS]防止用户截屏
昨天,产品找我新增需求,说老板觉得应用内信息很重要,要求添加限制用户用手机截屏。
当时我是拒绝的,告诉他这个无法实现,Home+Power截屏是系统操作在应用中干预不了。他有些不信任就去给苹果客服打电话咨询,客服回答说以前见过有应用是将截屏图替换为白色或黑色图片。
现在使用的设备iOS11.2.1,Xcode Version 9.2。
编辑相册中最新照片的方法iOS8之后就已经失效,框架“Photos”也在iOS10之后失效。
搜索发现UIApplication中
仅有用户截屏后的通知,应用中只会收到已经截屏的通知并没办法干预。
// This notification is posted after the user takes a screenshot (for example by pressing both the home and lock screen buttons)
UIKIT_EXTERN NSNotificationName const UIApplicationUserDidTakeScreenshotNotification NS_AVAILABLE_IOS(7_0);
虽然无法直接干预,但可以知道用户截屏了就可以用其它的方式来限制用户行为。
#import "AppDelegate.h"
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(userDidTakeScreenshotNotification:)
name:UIApplicationUserDidTakeScreenshotNotification object:nil];
return YES;
}
// Home+Power键截屏后通知响应的方法
- (void)userDidTakeScreenshotNotification:(NSNotification *)notification {
// 下面这张图与硬件截的图并不是同一张,这里再次使用代码截屏是为了获取用户截屏图片。
UIImage *image = [self imageWithScreenshot];
/*
如果APP对保密要求比较高,这里可以将图片编码后上传到服务器,这样有需要时也可以提供一个追查方法。
如果是自己的APP,再霸道一点的,这里监控到用户的截屏行为,应用直接强制退出登录并封号处理也是可以的。
*/
}
// 代码截屏
- (UIImage *)imageWithScreenshot {
CGSize imageSize = CGSizeZero;
UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation;
if (UIInterfaceOrientationIsPortrait(orientation)) {
imageSize = [UIScreen mainScreen].bounds.size;
} else {
imageSize = CGSizeMake([UIScreen mainScreen].bounds.size.height, [UIScreen mainScreen].bounds.size.width);
}
UIGraphicsBeginImageContextWithOptions(imageSize, NO, 0);
CGContextRef context = UIGraphicsGetCurrentContext();
for (UIWindow *window in [[UIApplication sharedApplication] windows]) {
CGContextSaveGState(context);
CGContextTranslateCTM(context, window.center.x, window.center.y);
CGContextConcatCTM(context, window.transform);
CGContextTranslateCTM(context, -window.bounds.size.width * window.layer.anchorPoint.x, -window.bounds.size.height * window.layer.anchorPoint.y);
if (orientation == UIInterfaceOrientationLandscapeLeft) {
CGContextRotateCTM(context, M_PI_2);
CGContextTranslateCTM(context, 0, -imageSize.width);
} else if (orientation == UIInterfaceOrientationLandscapeRight) {
CGContextRotateCTM(context, -M_PI_2);
CGContextTranslateCTM(context, -imageSize.height, 0);
} else if (orientation == UIInterfaceOrientationPortraitUpsideDown) {
CGContextRotateCTM(context, M_PI);
CGContextTranslateCTM(context, -imageSize.width, -imageSize.height);
}
if ([window respondsToSelector:@selector(drawViewHierarchyInRect:afterScreenUpdates:)]) {
[window drawViewHierarchyInRect:window.bounds afterScreenUpdates:YES];
} else {
[window.layer renderInContext:context];
}
CGContextRestoreGState(context);
}
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
NSData *imageData = UIImagePNGRepresentation(image);
UIImage *screenImage = [UIImage imageWithData:imageData];
return screenImage;
}
@end
之前搜索时,看到一个帖子:
可以通过 Configuration Profile 来实现
allowScreenShot (Boolean)
Optional. When false, users are unable to save a screenshot of the display.
文档:
https://developer.apple.com/library/ios/featuredarticles/iPhoneConfigurationProfileRef/Introduction/Introduction.html
可以通过 Configuration Profile 来实现
allowScreenShot (Boolean)
Optional. When false, users are unable to save a screenshot of the display.
文档:
https://developer.apple.com/library/ios/featuredarticles/iPhoneConfigurationProfileRef/Introduction/Introduction.html
了解了一下,还不是非常明白。
Configuration Profiles
http://nshipster.cn/configuration-profiles/
http://nshipster.cn/configuration-profiles/
Xcode-利用Configuration实现多个配置
https://www.jianshu.com/p/650c923255b0
https://www.jianshu.com/p/650c923255b0