Xcode: Garder l’application toujours active et détecter l’inactivité de l’utilisateur

mardi 2 juillet 2013

Dans le cadre d’un de mes projets, mon client voulait que l’application soit toujours active et qu’après 5 minutes d’inactivité l’application retourne sur la home.
Voici un code qui permet de garder l’application toujours active:

    // ALWAYS AWAKE APP
    UIApplication *myapp = [UIApplication sharedApplication];
    myapp.idleTimerDisabled = YES;

Maintenant, il nous reste la gestion de l’inactivité de l’utilisateur.
Tout d’abord on créé une sous classe Objective-C de UIApplication qui se nommera TIMERUIApplication. Voici le contenu du .h:

#import <UIKit/UIKit.h>

#define kApplicationTimeoutInMinutes 5
#define kApplicationDidTimeoutNotification @"AppTimeOut"

@interface TIMERUIApplication : UIApplication{
    NSTimer     *myidleTimer;
}

-(void)resetIdleTimer;
-(void)idleTimerExceeded;
-(void)sendEvent:(UIEvent *)event;

@end

La variable kApplicationTimeoutInMinutes défini le temps d’inactivité ici 5 minutes (car multiplié par soixante dans la fonction).
Voici le contenu du .m:


#import "TIMERUIApplication.h"

@implementation TIMERUIApplication

//here we are listening for any touch. If the screen receives touch, the timer is reset
-(void)sendEvent:(UIEvent *)event
{
    [super sendEvent:event];
    
    if (!myidleTimer)
    {
        [self resetIdleTimer];
    }
    
    NSSet *allTouches = [event allTouches];
    if ([allTouches count] > 0)
    {
        UITouchPhase phase = ((UITouch *)[allTouches anyObject]).phase;
        if (phase == UITouchPhaseBegan)
        {
            [self resetIdleTimer];
        }
        
    }
}
//as labeled...reset the timer
-(void)resetIdleTimer
{
    if (myidleTimer)
    {
        [myidleTimer invalidate];
    }
    //convert the wait period into minutes rather than seconds
    int timeout = kApplicationTimeoutInMinutes * 60;
    myidleTimer = [NSTimer scheduledTimerWithTimeInterval:timeout target:self selector:@selector(idleTimerExceeded) userInfo:nil repeats:NO];
    
}
//if the timer reaches the limit as defined in kApplicationTimeoutInMinutes, post this notification
-(void)idleTimerExceeded
{
    [[NSNotificationCenter defaultCenter] postNotificationName:kApplicationDidTimeoutNotification object:nil];
}

@end

Cette classe va gérer le Timer d’inactivité et de savoir si l’utilisateur à interagit ou non avec le device.
Ensuite, il faut aller dans le main.m de l’application qui se trouve dans le dossier Supporting Files de votre projet. Il doit ressembler à ceci:

#import <UIKit/UIKit.h>

#import "AppDelegate.h"
#import "TIMERUIApplication.h"

int main(int argc, char *argv[])
{
    @autoreleasepool {
        return UIApplicationMain(argc, argv, NSStringFromClass([TIMERUIApplication class]), NSStringFromClass([AppDelegate class]));
    }
}

Maintenant, il faut ajouter dans AppDelegate.h:

#import "TIMERUIApplication.h"

Et dans le AppDelegate.m, il faut ajouter dans la fonction didFinishLaunchingWithOptions

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationDidTimeout:) name:kApplicationDidTimeoutNotification object:nil];

Il ne reste plus que la fonction qui sera appelé quand le timeout aura expiré:

#pragma - INACTIVITY FUNCTION
-(void)applicationDidTimeout:(NSNotification *) notif
{
    //NSLog (@"time exceeded!!");
    [self goHome];
}

Je me suis inspiré du lien suivant

Tags: UIApplication