[Résolu] Mise en veille d'une appli iPhone

Philippe49Philippe49 Membre
avril 2009 modifié dans API UIKit #1
Lorsque l'utilisateur éteint son iPod/iPhone, l'appli reste chargée. Il me semble avoir lu quelque part que les timer ou threads en route étaient alors stoppés, sans reprendre lors du nouvel allumage Tout cela semblant parfaitement logique d'ailleurs ...
Quelqu'un a-t-il des affirmations précises sur ce sujet ?

Conclusions ici

Réponses

  • Philippe49Philippe49 Membre
    avril 2009 modifié #2
    En clair dans applicationWillTerminate: est-il nécessaire d'invalider les timer et threads éventuellement en cours ?
  • muqaddarmuqaddar Administrateur
    10:40 modifié #3
    dans 1240894413:

    En clair dans applicationWillTerminate: est-il nécessaire d'invalider les timer et threads éventuellement en cours ?


    Comment ça ? Si l'appli est fermée par la système, ça ne tue pas tous ses threads ? ??
  • Philippe49Philippe49 Membre
    avril 2009 modifié #4
    Justement, je me demande.
    Ce qui est sur, et tu peux en faire l'expérience, c'est que si tu éteins ton iPod alors que ton appli est en marche, et que tu le rallumes tu te retrouves avec ton appli dans "l'état" où tu l'as laissée.
    Je pense que les threads évidemment ne continuent pas leur action sous extinction de l'iPod (aà¯e, aà¯e , aà¯e la atterie sinon !) , mais que retrouve-t-on à  ce sujet lorsqu'on rallume ?  [EDIT : ben si]

    Je fais l'expérience ...
  • 10:40 modifié #5
    Hmmm je doute fortement qu'il faille faire ça lorsque l'utilisateur ferme pleinement ton application.. ça m'étonnerait énormément de la part d'Apple. Seul les Mobiles iApps ne sont effectivement pas killés, comme Safari, ou Mail. mais pour les applis tierces je suis persuadé que si.. Sinon je devrais éteindre mon téléphone tous les jours :o
  • schlumschlum Membre
    10:40 modifié #6
    dans 1240904490:
    Je pense que les threads évidemment ne continuent pas leur action sous extinction de l'iPod (aà¯e, aà¯e , aà¯e la atterie sinon !) , mais que retrouve-t-on à  ce sujet lorsqu'on rallume ?

    Je fais l'expérience ...


    Mécanisme de veille profonde je suppose... Toute la mémoire RAM est flushée sur le disque et restaurée au réveil  ???
  • AliGatorAliGator Membre, Modérateur
    avril 2009 modifié #7
    http://developer.apple.com/iphone/library/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/ApplicationEnvironment/ApplicationEnvironment.html#//apple_ref/doc/uid/TP40007072-CH7-SW6

    If the user presses the Sleep/Wake button on a device while running your application, the system calls your application delegate's applicationWillResignActive: method, stops the delivery of touch events, and then puts the device to sleep. When the user wakes the device later, the system calls your application delegate's applicationDidBecomeActive: method and begins delivering events to the application again. As you do with other interruptions, you should use these methods to put your application into a sleep state (or pause the game) and wake it up again. While in the sleep state, your application should use as little power as possible.
  • Philippe49Philippe49 Membre
    10:40 modifié #8
    Il faut donc plutôt réagir dans applicationWillResignActive: (ou sa petite soe“ur applicationDidBecomeActive) que dans applicationWillTerminate:


    Dans la référence de cette application, on lit : " When an application is inactive, it is executing "


    <br />applicationWillResignActive:<br />Tells the delegate that the application will become inactive. This method is optional.<br />- (void)applicationWillResignActive:(UIApplication *)application<br />Parameters<br />application<br />The singleton application instance.<br />Discussion<br />The delegate can implement this method to make adjustments when the application transitions from an active state to an inactive state. When an application is inactive, it is executing but is not dispatching incoming events. This occurs when an overlay window pops up or when the device is locked.
    



    Cela semble corroborer la citation ci-dessus While in the sleep state, your application should use as little power as possible sans pour autant que l'on voit ce que cela recouvre.
    Si un thread de chargement d'une URL est en cours est-il interrompu ? supprimé ? retardé ? exécuté ?
    Si l'application a installé un timer avec répétition (c'est mon problème spécifique) celui-ci reprend-il ou est-il supprimé de la pile d'exécution ?

    (Dès que mon @&;*** B) d'iPod voudra bien redevenir réutilisable, je tente) 


  • Philippe49Philippe49 Membre
    avril 2009 modifié #9
    Mon  <3 o:) :kicking: d'iPod m'ayant fait l'honneur de bien vouloir refaire mes applis, je livre les résultats du test sur les timer :<br />

    J'ai un décompteur de secondes (un timer avec répétition timeinterval=1). Je mets en veille, j'attends 20 secondes, le compteur est descendu de 20 unités.
    1) Je me suis jamais posé la question avec Mac OS X ?
    2) Il faudrait voir avec une animation, avec un chargement, un thread.

    [EDIT] Pareil avec une animation, même mis en veille l'appli continue à  faire des NSlog, et l'animation de mes objets se poursuit ...


  • schlumschlum Membre
    10:40 modifié #10
    Ben oui, tout est dans le post d'Ali, ce n'est pas une mise en veille classique... tout continue.
    C'est au programmeur de stopper les tâches consommatrices avec les méthodes données.
    Par exemple, dans une runloop, tester si on est en veille, et si oui, faire un sleep de 2-3 secondes.
  • al33eral33er Membre
    10:40 modifié #11
    dans 1240920590:

    Mon  <3 o:) :kicking: d'iPod m'ayant fait l'honneur de bien vouloir refaire mes applis, je livre les résultats du test sur les timer :<br />

    J'ai un décompteur de secondes (un timer avec répétition timeinterval=1). Je mets en veille, j'attends 20 secondes, le compteur est descendu de 20 unités.
    1) Je me suis jamais posé la question avec Mac OS X ?
    2) Il faudrait voir avec une animation, avec un chargement, un thread.

    [EDIT] Pareil avec une animation, même mis en veille l'appli continue à  faire des NSlog, et l'animation de mes objets se poursuit ...


    Bonjour,

    Je suis l'auteur de iReveil (Radio Reveil sur iPhone) qui se trouve sur le Store Apple. J'ai effectivement un problème avec les TIMER.
    "Ils se mettent en veille". Depuis la version 2.1, Apple a changé sa politique de mise en veille et de consommation d'énergie. Toutes les fonctions hors les 5 fonctions de base de l'iphone (TELEPHONE, SMS, MAIL, IPOD, SAFARI), toutes les autres, se stoppent lors de la mise en veille. Les infos sont effectivement stockés en mémoires et tout est suspendu. Les timers en cours reprennent avec le décalage du temps de la mise en veille.
    Attention, l'arrêt se fait au bout de 30 secondes et non pas immédiatement) (c'est paramétré quelque part dans les fichiers de configuration de l'iphone).

    Attention, aussi au test, quand l'iphone est branché sur le secteur par l'ordi, le dock ou la prise mural, le comportement est différent, les timers ne sont pas arrêtés.

    Si par hasard, vous connaissez une méthode qui permet de faire en sorte que le timer fonctionne même en veille, je suis tout ouà¯e.

    Cela me permettrait de ne pas consommer toute la baterie lorsque le reveil est programmé pour le lendemain.

    Alexandre.
  • 10:40 modifié #12
    Hmm je sais pas si ça peut vous aider, mais je peux contacter l'auteur de FStream sur iPhone (Aligator connaà®t aussi). C'est un lecteur radio et lorsque l'iPhone est en veille, ça continu de lire la radio, donc pas besoin de passer par la désactivation de la mise en veille ducoup.
  • Philippe49Philippe49 Membre
    avril 2009 modifié #13
    Ben oui, ce serait intéressant d'avoir une réponse complète sur ce sujet. Il y a bien app.idleTimerDisabled=YES; qui empêche totalement la mise en veille mais ce n'est pas une solution pour la batterie.

    Confirmation de ce que tu dis Alexandre après l'essai avec le device non branché : le timer s'arrête à  peu près 30 secondes plus tard.

    - (void)viewDidLoad {<br />	[super viewDidLoad];<br />	N=0;<br />	[NSTimer scheduledTimerWithTimeInterval:1. target:self selector:@selector(action:) userInfo:nil repeats:YES];<br />}<br />-(void) action:(NSTimer *) aTimer {<br />	textField.text=[NSString stringWithFormat:@&quot;%d&quot;,N++];<br />}
    
  • 10:40 modifié #14
    J'ai contacté l'auteur de FStream.

    En attendant, tu as essayé de lancer un nouveau thread au moment où tu reçois applicationWillResignActive: ?
  • Philippe49Philippe49 Membre
    10:40 modifié #15
    Pareil
  • apple_julienapple_julien Membre
    10:40 modifié #16
    Bonjour à  tous,

    Personnellement, les seuls cas où j'utilise des Timers dans FStream c'est pour rafraichir l'interface, donc j'ai jamais eu à  constater qu'ils ne fonctionnaient plus pendant la veille (donc al33er, tu as probablement raison !).

    Ce que je peux garantir, c'est que les threads, eux, continuent à  tourner sans problème pendant la mise en veille : j'en utilise un certain nombre pour télécharger le flux audio, le décoder et le jouer. Même en veille, et même non connecté sur le secteur, le flux audio continue d'être entendu.

    Après je sais qu'Apple est très fort, mais il y a une vraie différence entre bloquer des threads et bloquer un Timer :
    - Les threads (préemptifs) sont schedulé niveau kernel : faire une sélection à  ce niveau là  des applications qui ont le droit d'exécuter leurs thread et celles qui n'ont pas le droit ou encore dire quels threads peuvent s'exécuter et quels threads ne peuvent pas, ce n'est vraiment pas simple et je ne vois pas comment ils auraient pu faire ça proprement !
    - Les timers sont schedulés par la NSRunLoop : c'est une source ajoutée dans la liste des sources, et quand la NSRunLoop traite ses sources (c'est à  dire quand l'application n'est pas occupée par le code utilisateur), si le le temps d'un timer arrive à  échéance, un message est envoyé à  l'instance en question.
    Il est dans ce cas très simple pour Apple de spécifier que les sources de type Timer ne doivent pas être exécutés (à  noter que la NSRunLoop continue de tourner, elle, puisque sur FStream les données du flux audio sont reçues via la NSRunLoop, et comme je disais, je continue de recevoir les données même en veille).

    Voilà  ce que je peux dire.
  • Philippe49Philippe49 Membre
    10:40 modifié #17
    Merci de ces précisions. 
  • Philippe49Philippe49 Membre
    mai 2009 modifié #18
    Conclusion

    Ci-joint une application que l'on peut tester sur son device, sous réserve de remplir les formalités et d'avoir un provisionning Profile correspondant évidemment. Elle confirme les affirmations de apple_julien :

    Le device étant sous mode batterie :


    Après une mise en veille de l'appareil et après un délai d'une vingtaine de secondes
    • Les timer sont invalidés
    • Les threads continuent


    Lors de la mise en veille, la méthode applicationWillResignActive: est appelée.
    Lors du réveil, la méthode applicationDidBecomeActive: est appelée.


    Pour répondre à  aAl33er, il ne reste plus qu'à  mettre en place un thread qui tourne en veille  mais pas en continu : [NSThread sleepUntilDate:[NSDate dateWithTimeIntervalSinceNow:60.]]; et trouver le moyen de réveiller le device.
  • al33eral33er Membre
    10:40 modifié #19
    Bonjour,

    Effectivement lorsque de la session audio est active, et que l'iPhone est mis en veille, il n'y a pas de problème, la lecture continu seulement si la categorie de session est mis à  audio.

    UInt32 sessionCategory = kAudioSessionCategory_MediaPlayback;
    AudioSessionSetProperty (
    kAudioSessionProperty_AudioCategory,
    sizeof (sessionCategory),
    &sessionCategory
    );

    Apple a prévu le coup pour l'audio mais pas pour le reste.

    Je vais essayer avec le code de philippe.

    Merci à  vous.

    Alexandre.

  • 10:40 modifié #20
    Lors du réveil, la méthode applicationWillResignActive: est appelée.

    ? :o
  • Philippe49Philippe49 Membre
    avril 2009 modifié #21
    Sorry, écrit trop vite, la méthode applicationDidBecomeActive: est appelée. Rectifié. Merci de ta vigilance.
  • al33eral33er Membre
    avril 2009 modifié #22
    Bon je viens de faire le test avec un thread :

    thread = [[NSThread alloc] initWithTarget:self      selector:@selector(threadAction:) object:nil];
    [thread start];

    -(void)threadAction:(id)object {
    NSAutoreleasePool * pool=[[NSAutoreleasePool alloc] init];
    // Mise en attente du thread jusqu'a l'heure indiquée
    [NSThread sleepUntilDate:futurDateTimerThread];
    [self ouvrirRadio];
    [pool release];
    }

    Lorsque liphone n'est pas en veille, cela fonctionne la radio s'ouvre à  l'heure indiquée. Lorsque l'iPhone est en veille, cela ne se déclenche pas.

    Lorsque j'allume l'iphone, le reveil s'ouvre après un certain temps égal au temps de mise en veille.

    Grrrrr !!!!!

    Si vous avez une idée ?

    Alexandre.
  • Philippe49Philippe49 Membre
    avril 2009 modifié #23
    Alors que si à  la place de   [self ouvrirRadio]; on met l'écriture d'une donnée dans l'appli, cela se fait bien. Le problème est de quitter le mode veille à  partir d'une appli, puis de faire [self ouvrirRadio].
  • schlumschlum Membre
    10:40 modifié #24
    Lancer une session audio qui lit du silence jusqu'au moment du réveil, ça serait trop consommateur ?
  • Philippe49Philippe49 Membre
    10:40 modifié #25
    dans 1241041189:

    Le problème est de quitter le mode veille à  partir d'une appli, puis de faire [self ouvrirRadio].

    Et après un tour sur le "Forum Developper", je n'ai trouvé que "pas possible" ?
  • al33eral33er Membre
    10:40 modifié #26
    dans 1241074485:

    Lancer une session audio qui lit du silence jusqu'au moment du réveil, ça serait trop consommateur ?


    Bonjour,

    Concrètement c'est quoi lire du silence :

    un MP3 sans son;
    une adresse stream vide;
    Autre chose.

    Alexandre.

  • 10:40 modifié #27
    ça me parait bizarre oO
    Je vais tester ça de mon côté... (mais c'est chiant de devoir compiler sur l'iPhone à  chaque fois :( )
  • avril 2009 modifié #28
    Bon j'ai fait un test et ça marche... ça lit meme la musique pendant la veille :D

    Bon je te préviens, le code est pas du tout adapté à  ton cas.. faudra que tu gères le passage nouveau Thread à  main thread etc...

    <br />- (void)applicationDidFinishLaunching:(UIApplication *)application {&nbsp; &nbsp; <br />	<br />	player = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@&quot;Wake Up.mp3&quot; ofType:nil]] error:nil];<br />	[player setDelegate:self];<br />	<br />	// Detach new thread<br />	[NSThread detachNewThreadSelector:	@selector(wake:)<br />							 toTarget:self		<br />						&nbsp;  withObject:[[player retain] autorelease]];&nbsp;  <br />	[window makeKeyAndVisible];<br />}<br />- (void)wake:(id)object<br />{<br />	NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];<br />	<br />	[NSThread sleepForTimeInterval:30.0]; // Sleep for 30 seconds<br />	// Mettre en veille l&#39;iPhone manuellement avant les 30 secondes<br />	NSLog(@&quot;OK&quot;);<br />	[player play];<br />	<br />	[pool release];<br />}<br />
    


    Bon j'ai meme envie de t'adapter un minimum le code :)
  • 10:40 modifié #29
    Bon en fait à  mon avis tu dois simplement gérer le temps dans un thread séparé tout simplement.

    J'ai fait un interval de 10 secondes.. La musique s'arrête lorsque tu met en veille, mais le thread tourne toujours et appelera "playAlarm" dans le mainThread, qui pourra réagir meme en veille.

    Ci-joint le projet.
    Par contre plutôt que de se faire chier à  gérer le thread avec un -init, j'utiliserai plutot le +detachNewThreadSelector:....... mais après ça dépend si t'auras besoin d'invalider le thread pour je ne sais quelle raison.. ce qui est fort probable. Et puis ça ne risquera rien niveau mémoire vu que le thread se charge juste de faire le timing entre les alarmes et d'appeler la méthode playAlarm dans le mainThread.
  • schlumschlum Membre
    10:40 modifié #30
    dans 1241126152:

    dans 1241074485:

    Lancer une session audio qui lit du silence jusqu'au moment du réveil, ça serait trop consommateur ?


    Bonjour,

    Concrètement c'est quoi lire du silence :

    un MP3 sans son;
    une adresse stream vide;
    Autre chose.

    Alexandre.


    Concrètement, je sais pas ce que ça pourrait vouloir dire, c'est juste un concept qui n'est peut-être pas applicable...  ;)
    ça pourrait être un MP3 de 1 seconde lu toutes les 20 secondes, ça suffit peut-être pour maintenir l'état du thread  ???
  • al33eral33er Membre
    10:40 modifié #31
    Merci beaucoup à  vous tous pour cette aide précieuse. Je vais essayer de tester les différentes options.

    Alexandre.
Connectez-vous ou Inscrivez-vous pour répondre.