Controlar la captura de pantalla en el conmutador multitarea iOS 7

He estado tratando de encontrar información sobre el nuevo conmutador multitarea en iOS 7 y especialmente la captura de pantalla que el sistema operativo toma cuando la aplicación entra en hibernación.

enter image description here

¿Hay alguna forma de desactivar completamente esta función o captura de pantalla? ¿O puedo ocultar la aplicación completamente del conmutador? La aplicación debe ejecutarse en segundo plano, pero no queremos mostrar ninguna captura de pantalla desde la aplicación.

La captura de pantalla es potencialmente un riesgo para la seguridad, piense en líneas generales para aplicaciones bancarias donde su número de tarjeta o resumen de cuenta estará disponible para cualquiera que haga doble clic en el botón de inicio en el dispositivo.

¿Alguien con alguna idea de esto? Gracias.

En la Guía de progtwigción de aplicaciones para iOS , Apple dice:

Elimine la información confidencial de las vistas antes de pasar al fondo.

Cuando una aplicación pasa a segundo plano, el sistema toma una instantánea de la ventana principal de la aplicación, que luego presenta brevemente al hacer la transición de su aplicación al primer plano. Antes de regresar de su applicationDidEnterBackground: método, debe ocultar u ocultar las contraseñas y otra información personal confidencial que pueda capturarse como parte de la instantánea.

Además de oscurecer / reemplazar información sensible, es posible que también desee decirle a iOS 7 que no tome la instantánea de la pantalla a través de ignoreSnapshotOnNextApplicationLaunch . De acuerdo con la documentación de este método:

Si cree que la instantánea no puede reflejar correctamente la interfaz de usuario de su aplicación cuando se relanza su aplicación, puede llamar a [ ignoreSnapshotOnNextApplicationLaunch ] para evitar que se tome esa imagen instantánea.

Habiendo dicho eso, parece que la captura de pantalla todavía está tomada y, por lo tanto, he presentado un informe de error. Pero debe probar más y ver si el uso de esta configuración ayuda.

Si se allowScreenShot una aplicación empresarial, es posible que también desee examinar la configuración adecuada de allowScreenShot describe en la sección Carga útil de restricciones de la Referencia del perfil de configuración.


Aquí hay una implementación que logra lo que necesitaba. Puede presentar su propio UIImageView , o puede usar un patrón de protocolo delegado para ocultar la información confidencial:

 // SecureDelegate.h #import  @protocol SecureDelegate  - (void)hide:(id)object; - (void)show:(id)object; @end 

Luego le di a mi delegado de aplicaciones una propiedad para eso:

 @property (weak, nonatomic) id secureDelegate; 

Mi controlador de vista lo establece:

 - (void)viewDidLoad { [super viewDidLoad]; AppDelegate *delegate = [[UIApplication sharedApplication] delegate]; delegate.secureDelegate = self; } 

El controlador de vista obviamente implementa ese protocolo:

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

Y, finalmente, mi delegado de aplicación se vale de este protocolo y propiedad:

 - (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:"]; } 

Tenga en cuenta que estoy usando applicationWillResignActive lugar de la applicationDidEnterBackground recomendada, porque, como han señalado otros, no se llama a este último al tocar dos veces en el botón de inicio mientras se ejecuta la aplicación.

Desearía poder usar las notificaciones para manejar todo esto, en lugar del patrón delegado-protocolo, pero en mis pruebas limitadas, las notificaciones no se manejan de manera oportuna, pero el patrón anterior funciona bien.

Esta es la solución con la que trabajé para mi aplicación:

Como dijo Tommy: Puedes usar la aplicación WillResignActive. Lo que hice fue hacer un UIImageView con mi SplashImage y agregarlo como subvista a mi ventana principal-

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

Usé este método en lugar de applicationDidEnterBackground porque applicationDidEnterBackground no se activará si duplica el botón de inicio y se aplicará applicationWillResignActive. Escuché a la gente decir que también se puede desencadenar en otros casos, así que aún estoy probando para ver si da problemas, ¡pero ninguno hasta ahora! 😉

Aquí para eliminar la vista de la imagen:

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

¡Espero que esto ayude!

Sidenote: Probé esto tanto en el simulador como en un dispositivo real: ¡No se mostrará en el simulador, pero sí en un dispositivo real!

Este método rápido y sencillo arrojará una instantánea negra sobre el ícono de su aplicación en el conmutador de aplicaciones iOS7 o posterior.

Primero, tome la ventana de teclas de su aplicación (generalmente configurada en AppDelegate.m en la aplicación: didFinishLaunchingWithOptions), y escúrela cuando su aplicación esté a punto de pasar al segundo plano:

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

Luego, des-oculte la ventana clave de su aplicación cuando su aplicación se vuelva a activar:

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

En este punto, revisa el selector de aplicaciones y verifica que veas una instantánea negra sobre el ícono de tu aplicación. Me di cuenta de que si ejecutas el selector de aplicaciones inmediatamente después de mover tu aplicación a segundo plano, puede haber un retraso de ~ 5 segundos en el que verás una instantánea de tu aplicación (¡la que deseas ocultar!), Después que pasa a una instantánea totalmente negra. No estoy seguro de qué pasa con el retraso; si alguien tiene alguna sugerencia, por favor toque.

Si desea un color que no sea negro en el conmutador, puede hacer algo como esto agregando una subvista con cualquier color de fondo que desee:

 - (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]; } } 

A continuación, elimine esta subvista en color cuando su aplicación se vuelva a activar:

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

Usé la siguiente solución: cuando la aplicación va a renunciar, obtengo la instantánea de la aplicación como una Vista y le agrego desenfoque. Luego agrego esta vista a la ventana de la aplicación

como hacer esto:

  1. en la aplicaciónDelegate justo antes de la implementación agregar línea:

     static const int kNVSBlurViewTag = 198490;//or wherever number you like 
  2. agregue estos métodos:

     - (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; } 
  3. haga que su implementación de aplicaciónDelegate sea la siguiente:

     - (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]; } 

Creé proyectos de ejemplo en Swift y Objective C. Ambos proyectos realizan las siguientes acciones en:

-application: didResignActive – snapshot se crea, se difumina y se agrega a la ventana de la aplicación

-aplicación: la vista de desenfoque willBecomeActive se eliminará de la ventana.

Cómo utilizar:

Objecitve C

  1. Agregue archivos AppDelegate+NVSBlurAppScreen .h y .m a su proyecto

  2. en su método -applicationWillResignActive: agregue la siguiente línea:

     [self nvs_blurPresentedView]; 
  3. en su método -applicationDidEnterBackground: agregue la siguiente línea:

     [self nvs_unblurPresentedView]; 

Rápido

  1. agregue el archivo AppDelegateExtention.swift a su proyecto

  2. en su aplicación la función WillResignActive agrega la siguiente línea:

     blurPresentedView() 
  3. en su función applicationDidBecomeActive agregue la siguiente línea:

     unblurPresentedView() 

si solo usas [self.window addSubview:imageView]; en la función applicationWillResignActive , este imageView no cubrirá UIAlertView, UIActionSheet o MFMailComposeViewController …

La mejor solución es

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

Proporcionar mi propia solución como una “respuesta”, aunque esta solución es muy poco confiable. A veces aparece una pantalla negra como captura de pantalla, a veces el XIB y, a veces, una captura de pantalla de la aplicación. Dependiendo del dispositivo y / o si ejecuto esto en el simulador.

Tenga en cuenta que no puedo proporcionar ningún código para esta solución, ya que hay una gran cantidad de detalles específicos de la aplicación allí. Pero esto debería explicar la esencia básica de mi solución.

En AppDelegate.m en applicationWillResignActive, compruebo si estamos ejecutando iOS7, si lo hacemos, cargaré una nueva vista que está vacía con el logotipo de la aplicación en el centro. Una vez que se llama a applicationDidBecomeActive, vuelvo a lanzar mis vistas antiguas, que se reiniciarán, pero eso funciona para el tipo de aplicación que estoy desarrollando.

Puede usar el activador para configurar el doble clic del botón de inicio para iniciar la multitarea y desactivar el doble clic predeterminado del botón de inicio y el inicio de la ventana de multitarea. Este método se puede usar para cambiar las capturas de pantalla a la imagen predeterminada de la aplicación. Esto es aplicable a aplicaciones con función de protección de contraseña predeterminada.

Xamarin.iOS

Adaptado de https://stackoverflow.com/a/20040270/7561

En lugar de solo mostrar un color, quería mostrar mi pantalla de inicio.

  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(); }