100 votes

Contrôle de la capture d'écran dans le sélecteur multitâche d'iOS 7

J'ai essayé de trouver des informations sur le nouveau sélecteur multitâche d'iOS 7 et notamment sur la capture d'écran que le système d'exploitation effectue lorsque l'application entre en hibernation.

enter image description here

Existe-t-il un moyen de désactiver complètement cette fonctionnalité ou cette capture d'écran ? Ou puis-je cacher complètement l'application dans le sélecteur ? L'application doit fonctionner en arrière-plan, mais nous ne voulons pas montrer de capture d'écran de l'application.

La capture d'écran est potentiellement un risque pour la sécurité, comme c'est le cas pour les applications bancaires où votre numéro de carte ou le résumé de votre compte sera accessible à toute personne qui double-clique sur le bouton d'accueil de l'appareil.

Quelqu'un a-t-il une idée de ce qui se passe ? Merci.

1 votes

Ma solution actuelle consiste à charger une vue vierge avec le logo de l'application lorsque l'application entre en hibernation et à la supprimer lorsque l'application revient, mais cette solution est difficile à gérer et ressemble plus à un hack qu'à une solution élégante. En outre, cette solution échoue de temps en temps en fonction de l'appareil, etc. Elle n'est donc pas vraiment utilisable.

103voto

Rob Points 70987

Sur Préparer votre interface utilisateur à fonctionner en arrière-plan dit Apple :

Préparez votre interface utilisateur pour l'instantané de l'application

À un moment donné, après que votre application est entrée en arrière-plan et que votre méthode de délégation est revenue, UIKit prend un instantané de l'interface utilisateur actuelle de votre application. Le système affiche l'image résultante dans le sélecteur d'application. Il affiche également l'image temporairement lorsque votre application revient au premier plan.

L'interface utilisateur de votre application ne doit pas contenir d'informations sensibles sur les utilisateurs, telles que des mots de passe ou des numéros de carte de crédit. Si votre interface contient de telles informations, supprimez-les de vos vues lorsque vous entrez en arrière-plan. De même, écartez les alertes, les interfaces temporaires et les contrôleurs de vue système qui masquent le contenu de votre application. L'instantané représente l'interface de votre application et doit être reconnaissable par les utilisateurs. Lorsque votre application revient au premier plan, vous pouvez restaurer les données et les vues comme il convient.

Voir Q&A technique QA1838 : empêcher les informations sensibles d'apparaître dans le sélecteur de tâches

En plus de masquer/remplacer les informations sensibles, vous pouvez également indiquer à iOS 7 de ne pas prendre la capture d'écran via ignoreSnapshotOnNextApplicationLaunch dont la documentation dit :

Si vous pensez que l'instantané ne peut pas refléter correctement l'interface utilisateur de votre application lorsque celle-ci est relancée, vous pouvez appeler ignoreSnapshotOnNextApplicationLaunch pour empêcher cette image instantanée d'être prise.

Cela dit, il semble que la capture d'écran soit toujours prise et j'ai donc déposé un rapport de bug. Mais vous devriez effectuer d'autres tests et voir si l'utilisation de ce paramètre est utile.

S'il s'agissait d'une application d'entreprise, vous pourriez également vous pencher sur le paramétrage approprié de l'option allowScreenShot décrit dans le Restrictions Charge utile de la section Référence du profil de configuration.


Voici une implémentation qui permet d'obtenir ce dont j'avais besoin. Vous pouvez présenter votre propre UIImageView ou vous pouvez utiliser un modèle de protocole de délégué pour masquer les informations confidentielles :

//  SecureDelegate.h

#import <Foundation/Foundation.h>

@protocol SecureDelegate <NSObject>

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

@end

J'ai ensuite donné à mon délégué d'application une propriété pour cela :

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

Mon contrôleur de vue le définit :

- (void)viewDidLoad
{
    [super viewDidLoad];

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

Le contrôleur de vue met évidemment en œuvre ce protocole :

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

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

Et, enfin, mon délégué d'application se sert de ce protocole et de cette propriété :

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

Note, j'utilise applicationWillResignActive plutôt que le conseillé applicationDidEnterBackground car, comme d'autres l'ont souligné, cette dernière n'est pas appelée lorsque l'on appuie deux fois sur le bouton d'accueil alors que l'application est en cours d'exécution.

J'aimerais pouvoir utiliser les notifications pour gérer tout cela, plutôt que le modèle de protocole de délégation, mais dans mes tests limités, les notifications ne sont pas traitées de manière suffisamment rapide, mais le modèle ci-dessus fonctionne bien.

0 votes

Merci pour votre solution Rob, votre capacité de recherche de documents est meilleure que la mienne :) Néanmoins, nous avons emprunté une voie légèrement différente, car nous n'avons jamais réussi à faire fonctionner ignoreSnapshotOnNextApplicationLaunch. Il se peut que cela concerne le rapport de bogue que vous avez déposé auprès d'Apple. Pourriez-vous partager votre code d'exemple avec nous ? Au moins pour que nous ayons un point de comparaison. Merci encore !

6 votes

Notez que, comme mentionné ici stackoverflow.com/questions/18937313/ le comportement n'est pas toujours le même dans le simulateur que sur l'appareil !

0 votes

@Rob Vous avez caché des informations confidentielles dans applicationDidEnterBackground mais comment faire pour qu'à partir du premier plan, l'utilisateur appuie deux fois sur le bouton d'accueil, et le multitâche s'affiche. mon application n'est pas encore passée en arrière-plan, donc applicationDidEnterBackground & applicationWillResignActive ne sont pas appelés.

32voto

Laura Points 111

C'est la solution avec laquelle j'ai travaillé pour mon application :

Comme l'a dit Tommy : Vous pouvez utiliser l'applicationWillResignActive. Ce que j'ai fait, c'est créer une UIImageView avec mon SplashImage et l'ajouter en tant que sous-vue à ma fenêtre principale

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

J'ai utilisé cette méthode au lieu de l'applicationDidEnterBackground parce que l'applicationDidEnterBackground ne sera pas déclenchée si vous appuyez deux fois sur le bouton d'accueil, et l'applicationWillResignActive le sera. J'ai entendu des gens dire qu'elle peut être déclenchée dans d'autres cas, donc je continue à tester pour voir si elle donne des problèmes, mais aucun jusqu'à présent ! ;)

Ici pour supprimer l'imageview :

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

J'espère que cela vous aidera !

Note complémentaire : J'ai testé ceci à la fois sur le simulateur et sur un appareil réel : Il ne s'affiche pas sur le simulateur, mais il s'affiche sur un appareil réel !

2 votes

Il y a un inconvénient : applicationWillResignActive est appelé, entre autres, lorsque l'utilisateur tire vers le bas le dock des notifications. Vous faites donc glisser votre doigt de haut en bas et vous voyez cette image, alors que vous vous attendiez à voir le contenu de l'application.

4 votes

Il est préférable de brouiller les informations sensibles sur applicationWillResignActive et de définir imageView sur aplicationDidEnterBackground.

0 votes

Cela fonctionne, mais il y a un bug de rotation lors du déploiement vers iOS7, construit avec xCode6 : stackoverflow.com/questions/26147068/

15voto

John Jacecko Points 589

Cette méthode simple et rapide permet d'obtenir un cliché noir au-dessus de l'icône de votre application dans le sélecteur d'applications iOS7 ou ultérieur.

Tout d'abord, prenez la fenêtre clé de votre application (généralement configurée dans AppDelegate.m dans application:didFinishLaunchingWithOptions), et cachez-la lorsque votre application est sur le point de passer en arrière-plan :

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

Ensuite, démasquez la fenêtre clé de votre application lorsque celle-ci redevient active :

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

À ce stade, lancez le sélecteur d'applications et vérifiez que vous voyez un instantané noir au-dessus de l'icône de votre application. J'ai remarqué que si vous lancez le sélecteur d'applications immédiatement après avoir déplacé votre application en arrière-plan, il peut y avoir un délai d'environ 5 secondes pendant lequel vous verrez un instantané de votre application (celle que vous voulez cacher !), après quoi il passe à un instantané entièrement noir. Je ne suis pas sûr de l'origine de ce délai ; si quelqu'un a des suggestions à faire, merci de nous en faire part.

Si vous voulez une couleur autre que le noir dans le sélecteur, vous pouvez faire quelque chose comme ça en ajoutant une vue secondaire avec la couleur de fond que vous voulez :

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

Ensuite, supprimez cette sous-vue de couleur lorsque votre application redevient active :

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

0voto

Tommie Points 531

Je fournis ma propre solution comme "réponses", bien que cette solution soit très peu fiable. Parfois j'obtiens un écran noir comme la capture d'écran, parfois le XIB et parfois une capture d'écran de l'application elle-même. Cela dépend de l'appareil et/ou du fait que je l'exécute dans le simulateur.

Veuillez noter que je ne peux pas fournir de code pour cette solution car il y a beaucoup de détails spécifiques à l'application. Mais ceci devrait expliquer l'essentiel de ma solution.

Dans AppDelegate.m, sous applicationWillResignActive, je vérifie si nous utilisons iOS7. iOS7, si c'est le cas, je charge une nouvelle vue vide avec le logo de l'application au milieu. logo de l'application au milieu. Une fois que applicationDidBecomeActive est appelé je relancer mes anciennes vues, qui seront réinitialisées - mais cela fonctionne pour le type d'application que je développe.

1 votes

Si vous voyez ce que fait l'application Appareil photo, elle transforme l'image en une image floue lorsqu'elle passe en arrière-plan (vous pouvez voir la transition lorsqu'elle se réduit à l'icône).

0 votes

@Petesh Oui, c'est une belle mise en œuvre, mais la question est de savoir comment ils le font. Je crains une API privée.

0 votes

@Tommie Vous dites "Selon le dispositif et/ou si je l'exécute dans le simulateur". Pour moi, cela apparaît pour fonctionner sur l'appareil (bien que je n'aie pas fait de tests exhaustifs), mais pas sur le simulateur. Vous trouvez que cela ne fonctionne pas sur l'appareil ?

0voto

Fareed.MK Points 1

Vous pouvez utiliser l'activateur pour configurer le double clic du bouton d'accueil pour lancer le multitâche et désactiver le double clic par défaut du bouton d'accueil et le lancement de la fenêtre multitâche. Cette méthode peut être utilisée pour remplacer les captures d'écran par l'image par défaut de l'application. Cette méthode s'applique aux applications dotées d'une fonction de protection par code d'accès par défaut.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X