防止 iOS 在进入后台之前对应用进行屏幕截图

Posted

技术标签:

【中文标题】防止 iOS 在进入后台之前对应用进行屏幕截图【英文标题】:Prevent iOS from taking screen capture of app before going into background 【发布时间】:2011-11-23 02:53:15 【问题描述】:

大家可能都知道,ios 在将应用程序放到后台之前会对其进行屏幕截图。这通常是为了获得更好的用户体验,例如快速动画以恢复应用等。我不希望我的应用屏幕截图存储在设备上,但我希望多任务仍然存在。

我提出了一个解决方案,但我不确定我是否朝着正确的方向前进。因此,当调用applicationDidEnterBackground 时——我放入了一个将由操作系统捕获的覆盖图像,一旦应用程序进入前台,我将删除覆盖。我不确定这是否可行,但我正在实施这一点。同时,对此的任何其他想法都将帮助我找出解决此问题的最佳方法。

【问题讨论】:

您为什么不希望 iOS 这样做?正如你自己所说,截图是为了执行快速动画...... 我有用户的机密数据.. 所以有一些 3rd 方工具,如 iPhone 资源管理器,您可以进入 iOS 文件系统并提取图像。我不想与这些数据妥协......因此我计划实施这种方法。 这种方法效果很好.. 谢谢大家! 这个屏幕截图将存储在 iPhone 中由 OS 拍摄的什么位置? @Mobilewits 【参考方案1】:

您的方法正是正确且唯一的方法。放置一个覆盖视图并稍后将其删除。如果您的应用程序显示您不希望在任何地方以图像格式缓存的敏感数据,则这样做是有效的。

【讨论】:

【参考方案2】:

你在正确的轨道上。这是 Apple 推荐的方法as noted in the iOS Application Programming Guide:

在移到后台之前从视图中删除敏感信息。当应用程序转换到后台时,系统会拍摄应用程序主窗口的快照,然后在将应用程序转换回时简要显示到前台。在从您的 applicationDidEnterBackground: 方法返回之前,您应该隐藏或隐藏可能作为快照一部分捕获的密码和其他敏感个人信息。

【讨论】:

您知道这些屏幕截图临时存储在设备的哪个位置吗? /Library/Caches/Snapshots/$(BUNDLE_IDENTIFIER)/ 是应用沙箱内的路径。 顺便说一句,您可以使用 Xcode 的 DeviceManager 下载您的应用程序沙盒容器。 Updated Link 现在不应该是applicationWillResignActive吗?【参考方案3】:

我遇到了同样的问题,我的研究使我得到以下答案:

在应用进入后台之前设置一个模糊的屏幕覆盖,一旦应用变为活动状态,请移除此覆盖

如果是iOS 7或更高版本可以使用该功能 忽略SnapshotOnNextApplicationLaunch

参见苹果文档: https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIApplication_Class/Reference/Reference.html#//apple_ref/occ/instm/UIApplication/ignoreSnapshotOnNextApplicationLaunch

我希望这对某人有所帮助。

【讨论】:

ignoreSnapshotOnNextApplicationLaunch 听起来很有趣,但这并不能阻止 iOS 在任何情况下截屏,对吧? 我没有在iOS 8中尝试过这个功能,但在iOS 7中并没有阻止截屏。 我在这里遇到了问题。无论我做什么,我都无法阻止应用程序对不正确的窗口进行快照。 In this page, It Sayeth: “...调用这个方法让 UIKit 知道它应该使用你的应用程序的默认启动图像而不是快照。你必须从你用来保存你应用程序的代码中调用这个方法状态。”(待续) (续上)现在,最后一行是关键。简单地在我的 applicationWillResignActive 回调中调用它是行不通的。但是,我不确定 Apple 所说的“您用来保存应用程序状态的代码。”是什么意思 听起来他们指的是您用于在重启后保持状态的代码【参考方案4】:

在 iOS 7 中,您可以使用 allowScreenShot 一起停止该功能。

见:Apple Developer: Configuration Profile Reference:

allowScreenShot


布尔值
可选的。如果设置为false,用户不能保存屏幕截图,也不能截屏;它还可以防止 Clas-s-room 应用程序观察远程屏幕。默认为true

可用性:在 iOS 9.0 中更新,包括屏幕录制。

【讨论】:

链接失效了,不就是不简单粘贴链接的***指南吗? @ParikksitBhisay(我意识到它已经很老了,但我想提一下,因为我是来处理垃圾邮件的)这是一个简短的,可能是错误的答案,但它是一个答案;它提到了所需的属性。 这仅在设备处于配置管理下时可用 - 例如在企业环境中,它不适用于常规 AppStore 应用程序。【参考方案5】:

需要在应用程序生命周期方法中编写代码,这里我们在应用程序动画到背景时放置一个imageView

-(void)applicationWillResignActive:(UIApplication *)application

    imageView = [[UIImageView alloc]initWithFrame:[self.window frame]];
    [imageView setImage:[UIImage imageNamed:@"Splash_Screen.png"]];
    [self.window addSubview:imageView];

这里是删除imageView的代码:

- (void)applicationDidBecomeActive:(UIApplication *)application

    if(imageView != nil) 
        [imageView removeFromSuperview];
        imageView = nil;
    

它正在工作并经过适当的测试。

【讨论】:

但是图像没有为 iPad 对齐。 小心 'applicationWillResignActive' 在显示警告对话框时也会被调用。可能不是您想要显示此图像视图的时候。 在 iOS 11 中对此进行了测试...它无法间歇性工作【参考方案6】:

Depak Kumar 帖子的改进: 创建一个属性UIImage *snapShotOfSplash;

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 
[[UIApplication sharedApplication] ignoreSnapshotOnNextApplicationLaunch];
snapShotOfSplash =[UIImage imageNamed:@"splash_logo"];


- (void)applicationDidEnterBackground:(UIApplication *)application 


    self.overlayView = [[UIImageView alloc]initWithFrame:[self.window frame]];
    self.overlayView.backgroundColor = [UIColor whiteColor];
    [self.overlayView setImage:snapShotOfSplash];
    [self.overlayView setContentMode:UIViewContentModeCenter];
    [self.window addSubview:self.overlayView];
    [self.window bringSubviewToFront:self.overlayView]; 

- (void)applicationDidBecomeActive:(UIApplication *)application 
if(self.overlayView != nil) 
        [self.overlayView removeFromSuperview];
        self.overlayView = nil;
    

【讨论】:

【参考方案7】:

苹果文档 https://developer.apple.com/library/archive/qa/qa1838/_index.html

注意:您的 -applicationDidEnterBackground: 实现不应启动任何动画(将 NO 传递给任何动画:参数)。从该方法返回后,应用程序窗口的快照会立即被捕获。在拍摄快照之前动画不会完成。

在我声明的 swift 4.2 App 委托中转换的 Apple 代码

func applicationDidEnterBackground(_ application: UIApplication) 
    // Your application can present a full screen modal view controller to
    // cover its contents when it moves into the background. If your
    // application requires a password unlock when it retuns to the
    // foreground, present your lock screen or authentication view controller here.

    let blankViewController = UIViewController()
    blankViewController.view.backgroundColor = UIColor.black

    // Pass NO for the animated parameter. Any animation will not complete
    // before the snapshot is taken.
    window.rootViewController?.present(blankViewController, animated: false)


func applicationWillEnterForeground(_ application: UIApplication) 
    // This should be omitted if your application presented a lock screen
    // in -applicationDidEnterBackground:
    window.rootViewController?.dismiss(animated: false) false

【讨论】:

它还在工作,你可以在应用处于后台时发送截图吗? 它的工作方式是它确实创建了一个子视图等,但是当我添加它时窗口的大小已经很小,因此导致我的视​​图中间出现一个矩形在快照上但不覆盖整个屏幕。我最终按照文档中的建议推送了一个启动屏幕控制器,稍后将其删除... 顺便说一句,我在此使用启动屏幕图像。 它显示“找不到您要查找的页面。” 这很接近,但在 UIAlertController 出现时不起作用。 Going with : // enterBackground [self.window addSubview:self.splashView]; // enterForeground [self.splashView removeFromSuperview];将与 UIAlertController 一起使用【参考方案8】:

AppDelegate 中的工作方法,swift 4.2:

func blurScreen(style: UIBlurEffect.Style = UIBlurEffect.Style.regular) 
    screen = UIScreen.main.snapshotView(afterScreenUpdates: false)
    let blurEffect = UIBlurEffect(style: style)
    let blurBackground = UIVisualEffectView(effect: blurEffect)
    screen?.addSubview(blurBackground)
    blurBackground.frame = (screen?.frame)!
    window?.addSubview(screen!)


func removeBlurScreen() 
    screen?.removeFromSuperview()

在哪里:

weak var screen : UIView? = nil // property of the AppDelegate

在需要的委托方法中调用这些方法:

func applicationWillResignActive(_ application: UIApplication) 
    blurScreen()


func applicationDidBecomeActive(_ application: UIApplication) 
    removeBlurScreen()

【讨论】:

您的style: UIBlurEffect.Style = UIBlurEffect.Style.regular 子句中有错误。 Style is not a member type of UIBlurEffect.【参考方案9】:

在进入后台和反向操作时使用一些动画实现

   - (void)applicationWillResignActive:(UIApplication *)application

     //     fill screen with our own colour
        UIView *colourView = [[UIView alloc]initWithFrame:self.window.frame];
        colourView.backgroundColor = [UIColor blackColor];
        colourView.tag = 1111;
        colourView.alpha = 0;
        [self.window addSubview:colourView];
        [self.window bringSubviewToFront:colourView];

        // fade in the view
        [UIView animateWithDuration:0.5 animations:^
            colourView.alpha = 1;
        ];



- (void)applicationDidBecomeActive:(UIApplication *)application

    // grab a reference to our coloured view
    UIView *colourView = [self.window viewWithTag:1111];
    // fade away colour view from main view
    [UIView animateWithDuration:0.5 animations:^
        colourView.alpha = 0;
     completion:^(BOOL finished) 
        // remove when finished fading
        [colourView removeFromSuperview];
    ];

 

【讨论】:

【参考方案10】:

swift 4.0 版本。

用于自定义图标

首先在 AppDelegate 顶部添加这一行

var imageView: UIImageView?

并添加:

func applicationDidEnterBackground(_ application: UIApplication) 
    imageView = UIImageView(frame: window!.frame)
    imageView?.image = UIImage(named: "AppIcon")
    window?.addSubview(imageView!)


func applicationWillEnterForeground(_ application: UIApplication) 
    if imageView != nil 
        imageView?.removeFromSuperview()
        imageView = nil
    

黑色背景

func applicationDidEnterBackground(_ application: UIApplication) 
    let blankViewController = UIViewController()
    blankViewController.view.backgroundColor = UIColor.black
    window?.rootViewController?.present(blankViewController, animated: false)


func applicationWillEnterForeground(_ application: UIApplication) 
    window?.rootViewController?.dismiss(animated: false)

【讨论】:

完美,谢谢

以上是关于防止 iOS 在进入后台之前对应用进行屏幕截图的主要内容,如果未能解决你的问题,请参考以下文章

如何在后台线程上截取 UIView 的屏幕截图?

绕过 iOS 4 的屏幕截图

如果 App 在后台,iOS 会检测屏幕截图

iOS 屏幕截图为来自后台应用程序的 System.Drawing.Bitmap (Xamarin)

当我的应用在IOS中处于活动状态时如何阻止屏幕截图[关闭]

IOSurface - IOS 私有 API - 在后台捕获屏幕截图