iOS 应用如何检测用户截屏
本文为迁移文章,原发布时间为 2013-10-02 10:32:00
微信可以检测到用户截屏行为(Home + Power),并在稍后点击附加功能按钮时询问用户是否要发送刚才截屏的图片,这个用户体验非常好。
我注意到这个功能很久了,一直很好奇这是如何做到的。但最近实在是太忙了,没有时间整理出来,现在国庆放假了,整理一下我的想法。
我首先想到的是否能够检测到用户按下了 Home 键和 Power 键,因为截图需要两个按钮同时按下,但后面我发现这样做是不行的。因为截屏是按下(TouchDown)而非按下再松开(TouchUp),所以应用的状态不会发生任何改变,相关的代理方法和通知都不会触发,然后我试了第二种方法。
第二种是注册通知,这是最简单的方法,在 iOS 4.0 之前,系统会发送 PictureWasTakenNotification
这个通知来告知开发者发生了截屏行为,但这明显不符合我们现在 Apps 的要求。所以通过通知来检测用户截屏,也是不可行的。
在 iOS 7 之后,注册通知来检测用户截屏已经变为可行的了,在 iOS 7 Beta4 引入了新的 API ,其中就包括了截屏检测的通知 UIApplicationUserDidTakeScreenshotNotification
,这也就意味着在 iOS 7 中,我们只需要注册这个通知就可以了。非常简单。
第三种是应用启动后在后台循环检测相册内最新一张照片,看它的是否符合截屏的特征。这种方法可行,但这是个笨方法,需要用户允许你的程序访问相册才可以,并且一直在后台循环会消耗更多的系统资源。Github 上有一个开源库 ShotBlocker 做了这个功能。我使用 Instruments 检测在 iPhone 4S 、 iOS 6.1.3 的环境下 CPU 占用为 %2。
实际上,还有另外一种检测用户截屏的方法,就是使用 touchesCancelled:withEvent:
这个方法。在 iOS 7 之前,如果用户截屏,系统会自动取消屏幕上的所有 touch 事件,那么我们就可以检测这个方法的调用,然后加载本地最新图片再加以判断来实现我们的目的。但在 iOS 7 之后,截屏不再会取消屏幕的 touch 事件,所以导致了 Snapchat 和 Facebook Poke 之类的应用在 iOS 7 刚发布时依赖于系统这个行为的功能受到影响。