控制iOS 7多任务切换器中的屏幕截图

时间:2013-09-23 12:37:00

标签: ios ios7

我一直在尝试查找有关iOS 7中新的多任务切换器的一些信息,特别是当应用程序进入休眠状态时操作系统的屏幕截图。

enter image description here

有没有办法完全关闭此功能或屏幕截图?或者我可以从切换器中完全隐藏应用程序吗?该应用需要在后台运行,但我们不希望从应用中显示任何屏幕截图。

截图可能存在安全风险,请考虑银行应用程序,其中双击设备上的主页按钮的任何人都可以使用您的卡号或帐户摘要。

任何对此有任何见解的人?感谢。

8 个答案:

答案 0 :(得分:95)

App Programming Guide for iOS中,Apple说:

  

在移至后台之前从视图中删除敏感信息。

     

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

除了隐藏/替换敏感信息之外,您可能还想告诉iOS 7不要通过ignoreSnapshotOnNextApplicationLaunch拍摄屏幕快照。根据这个方法的the documentation

  

如果您认为在重新启动应用时快照无法正确反映应用的用户界面,则可以调用[ignoreSnapshotOnNextApplicationLaunch]以防止拍摄快照图像。

话虽如此,似乎仍然拍摄了屏幕快照,因此我提交了一份错误报告。但是你应该进一步测试,看看使用这个设置是否有帮助。

如果这是一个企业应用,您可能还需要查看配置文件参考的Restrictions Payload部分中列出的allowScreenShot的相应设置。


这是一个实现我所需要的实现。您可以展示自己的UIImageView,也可以使用委托协议模式来隐藏机密信息:

//  SecureDelegate.h

#import <Foundation/Foundation.h>

@protocol SecureDelegate <NSObject>

- (void)hide:(id)object;
- (void)show:(id)object;

@end

然后我为我的app委托了一个属性:

@property (weak, nonatomic) id<SecureDelegate> secureDelegate;

我的视图控制器设置它:

- (void)viewDidLoad
{
    [super viewDidLoad];

    AppDelegate *delegate = [[UIApplication sharedApplication] delegate];
    delegate.secureDelegate = self;
}

视图控制器显然实现了该协议:

- (void)hide:(id)object
{
    self.passwordLabel.alpha = 0.0;
}

- (void)show:(id)object
{
    self.passwordLabel.alpha = 1.0;
}

最后,我的app委托使用了这个协议和属性:

- (void)applicationWillResignActive:(UIApplication *)application
{
    [application ignoreSnapshotOnNextApplicationLaunch];  // this doesn't appear to work, whether called here or `didFinishLaunchingWithOptions`, but seems prudent to include it

    [self.secureDelegate hide:@"applicationWillResignActive:"];  // you don't need to pass the "object", but it was useful during my testing...
}

- (void)applicationDidBecomeActive:(UIApplication *)application
{
    [self.secureDelegate show:@"applicationDidBecomeActive:"];
}

注意,我使用applicationWillResignActive而不是建议的applicationDidEnterBackground,因为正如其他人所指出的那样,当应用程序运行时双击主页按钮时不会调用后者。

我希望我可以使用通知来处理所有这些,而不是代理协议模式,但在我的有限测试中,通知不会及时处理,但上述模式工作正常。 / p>

答案 1 :(得分:31)

这是我为我的应用程序工作的解决方案:

正如汤米所说:你可以使用applicationWillResignActive。我做的是使用我的SplashImage制作UIImageView并将其作为子视图添加到我的主窗口 -

(void)applicationWillResignActive:(UIApplication *)application
{
    imageView = [[UIImageView alloc]initWithFrame:[self.window frame]];
    [imageView setImage:[UIImage imageNamed:@"Portrait(768x1024).png"]];
    [self.window addSubview:imageView];
}

我使用此方法而不是applicationDidEnterBackground,因为如果您双击主页按钮将不会触发applicationDidEnterBackground,而applicationWillResignActive将会触发。我听人说虽然它也可以在其他情况下触发,所以我还在测试它是否会产生问题,但到目前为止还没有! ;)

此处删除imageview:

- (void)applicationDidBecomeActive:(UIApplication *)application
{
    if(imageView != nil) {
        [imageView removeFromSuperview];
        imageView = nil;
    }
}

希望这有帮助!

旁注:我在模拟器和真实设备上测试了它:它不会在模拟器上显示,但它会在真实设备上显示!

答案 2 :(得分:14)

这种快速简便的方法会在iOS7或更高版本的应用切换器中的应用图标上方生成黑色快照。

首先,拿你的应用程序的关键窗口(通常在应用程序中的AppDelegate.m中设置:didFinishLaunchingWithOptions),并在你的应用程序即将进入后台时隐藏它:

- (void)applicationWillResignActive:(UIApplication *)application
{
    if(isIOS7Or8)
    {
        self.window.hidden = YES;
    }
}

然后,当您的应用再次激活时,取消隐藏应用的关键窗口:

- (void)applicationDidBecomeActive:(UIApplication *)application
{
    if(isIOS7Or8)
    {
        self.window.hidden = NO;
    }
}

此时,请检查应用切换器并确认您在应用的图标上方看到黑色快照。我注意到,如果您在将应用程序移动到后台后立即启动应用程序切换器,可能会有~5秒的延迟,您将看到应用程序的快照(您要隐藏的应用程序的快照!),之后它转换为全黑快照。我不确定延迟是怎么回事;如果有人有任何建议,请加入。

如果您想在切换台中使用黑色以外的颜色,可以通过添加具有您喜欢的任何背景颜色的子视图来执行此类操作:

- (void)applicationWillResignActive:(UIApplication *)application
{
    if(isIOS7Or8)
    {
        UIView *colorView = [[[UIView alloc] initWithFrame:self.window.frame] autorelease];
        colorView.tag = 9999;
        colorView.backgroundColor = [UIColor purpleColor];
        [self.window addSubview:colorView];
        [self.window bringSubviewToFront:colorView];
    }
}

然后,当您的应用再次变为有效时,请移除此颜色子视图:

- (void)applicationDidBecomeActive:(UIApplication *)application
{
    if(isIOS7Or8)
    {
        UIView *colorView = [self.window viewWithTag:9999];
        [colorView removeFromSuperview];
    }
}

答案 3 :(得分:3)

我使用了以下解决方案: 当应用程序要辞职时,我将appWindow快照视为一个视图,并为其添加模糊。然后我将此视图添加到应用程序窗口

如何做到这一点:

    在appDelegate中
  1. 就在实现添加行之前:

    float: left;
  2. 添加此方法:

    static const int kNVSBlurViewTag = 198490;//or wherever number you like
    
  3. 让你的appDelegate实现如下:

    - (void)nvs_blurPresentedView
        {
            if ([self.window viewWithTag:kNVSBlurViewTag]){
                return;
            }
            [self.window addSubview:[self p_blurView]];
        }
    
        - (void)nvs_unblurPresentedView
        {
            [[self.window viewWithTag:kNVSBlurViewTag] removeFromSuperview];
        }
    
        #pragma mark - Private
    
        - (UIView *)p_blurView
        {
            UIView *snapshot = [self.window snapshotViewAfterScreenUpdates:NO];
    
            UIView *blurView = nil;
            if ([UIVisualEffectView class]){
                UIVisualEffectView *aView = [[UIVisualEffectView alloc]initWithEffect:[UIBlurEffect effectWithStyle:UIBlurEffectStyleDark]];
                blurView        = aView;
                blurView.frame  = snapshot.bounds;
                [snapshot addSubview:aView];
            }
            else {
                UIToolbar *toolBar  = [[UIToolbar alloc] initWithFrame:snapshot.bounds];
                toolBar.barStyle    = UIBarStyleBlackTranslucent;
                [snapshot addSubview:toolBar];
            }
            snapshot.tag = kNVSBlurViewTag;
            return snapshot;
        }
    
  4. 我在SwiftObjective C中创建了示例项目。 两个项目都在:

    中执行以下操作

    -application:didResignActive - 快照已创建,模糊并添加到应用窗口

    -application:willBecomeActive 模糊视图正在从窗口中删除。

    使用方法:

    目标C

    1. - (void)applicationWillResignActive:(UIApplication *)application { // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. //... //your code //... [self nvs_blurPresentedView]; } - (void)applicationWillEnterForeground:(UIApplication *)application { // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. //... //your code //... [self nvs_unblurPresentedView]; } .h和.m文件添加到您的项目中

    2. 你的-applicationWillResignActive:方法中的
    3. 添加以下行:

      AppDelegate+NVSBlurAppScreen
    4. 你的-applicationDidEnterBackground:方法中的
    5. 添加以下行:

      [self nvs_blurPresentedView];
      
    6. <强>夫特

      1. 将AppDelegateExtention.swift文件添加到您的项目中

      2. 在您的applicationWillResignActive函数中
      3. 添加以下行:

        [self nvs_unblurPresentedView];
        
      4. applicationLidBecomeActive函数中的
      5. 添加以下行:

        blurPresentedView()
        

答案 4 :(得分:2)

如果仅在[self.window addSubview:imageView];函数中使用applicationWillResignActive,则此imageView不会涵盖UIAlertView,UIActionSheet或MFMailComposeViewController ......

最佳解决方案是

- (void)applicationWillResignActive:(UIApplication *)application
{
    UIWindow *mainWindow = [[[UIApplication sharedApplication] windows] lastObject];
    [mainWindow addSubview:imageView];
}

答案 5 :(得分:0)

提供我自己的解决方案作为“答案”,尽管这种解决方案非常不可靠。有时候我会得到一个黑屏作为屏幕截图,有时候是XIB,有时是应用程序本身的屏幕截图。取决于设备和/或我是否在模拟器中运行。

请注意我无法提供此解决方案的任何代码,因为它中有很多特定于应用程序的详细信息。但这应该解释我的解决方案的基本要点。

  

在applicationWillResignActive下的AppDelegate.m中,我会检查是否存在   运行iOS7,如果我们加载一个空的新视图   app-logo位于中间。一旦applicationDidBecomeActive被调用i   重新启动我的旧视图,这将被重置 - 但这适用于   我正在开发的应用程序类型。

答案 6 :(得分:0)

您可以使用激活器配置双击主页按钮以启动多任务处理并禁用默认双击主页按钮并启动多任务窗口。此方法可用于将屏幕截图更改为应用程序的默认图像。这适用于具有默认密码保护功能的应用。

答案 7 :(得分:-1)

Xamarin.iOS

改编自https://stackoverflow.com/a/20040270/7561

我不想只显示颜色,而是展示我的启动画面。

 public override void DidEnterBackground(UIApplication application)
 {
    //to add the background image in place of 'active' image
    var backgroundImage = new UIImageView();
    backgroundImage.Tag = 1234;
    backgroundImage.Image = UIImage.FromBundle("Background");
    backgroundImage.Frame = this.window.Frame;
    this.window.AddSubview(backgroundImage);
    this.window.BringSubviewToFront(backgroundImage);
}

public override void WillEnterForeground(UIApplication application)
{
    //remove 'background' image
    var backgroundView = this.window.ViewWithTag(1234);
    if(null != backgroundView)
        backgroundView.RemoveFromSuperview();
}