iOS 9: beginBackgroundTaskWithExpirationHandler est appelé avant le timeout

Je travaille sur l'appel VOIP et l'ajout de soutien à iOS <10. Pour l'appel VOIP entrant lorsque l'application est en arrière-plan, j'utilise UILocalNotification (déconseillé dans iOS 10).

Pour faire un appel 60 secondes (ou 1 minute) j'utilise ce code

count = 0; apnTimer = [NSTimer scheduledTimerWithTimeInterval:3.0 target:self selector:@selector(showIncomingCall:) userInfo:userInfo repeats:YES]; self.backgroundTask = [application beginBackgroundTaskWithExpirationHandler:^{ NSLog(@"ALVOIP : BACKGROUND_HANDLER_NO_MORE_TASK_RUNNING."); [application endBackgroundTask:self.backgroundTask]; self.backgroundTask = UIBackgroundTaskInvalid; }]; -(void)showIncomingCall:(NSTimer *)timer { if (count < 60) { UIApplication *application = [UIApplication sharedApplication]; [application presentLocalNotificationNow:localNotification]; NSLog(@"Time Remaining: %f", [[UIApplication sharedApplication] backgroundTimeRemaining]); count = count + 3; return; } // TIMEOUT : STOP TIMER AND LOCAL NOTIFICATION BACKGROUND TASK [self invalidateCallNotifying]; } -(void)invalidateCallNotifying { [apnTimer invalidate]; if (self.backgroundTask != UIBackgroundTaskInvalid) { [[UIApplication sharedApplication] endBackgroundTask:self.backgroundTask]; self.backgroundTask = UIBackgroundTaskInvalid; } } 

pour étendre le time de traitement en arrière-plan à 1 minute et cela fonctionne dans iOS 10.1.1 (iPhone), mais ne fonctionne pas dans iOS 9.3.5 (iPad). D'une manière ou d'une autre, le gestionnaire invoque 30-33 secondes?

METTRE À JOUR:

J'ai essayé de commenter ce code:

 self.backgroundTask = [application beginBackgroundTaskWithExpirationHandler:^{ NSLog(@"ALVOIP : BACKGROUND_HANDLER_NO_MORE_TASK_RUNNING."); [application endBackgroundTask:self.backgroundTask]; self.backgroundTask = UIBackgroundTaskInvalid; }]; 

Pourtant, je suis capable de faire 30-33 secondes, c'est à dire je ne sais pas pourquoi cela ne fonctionne pas?

Je vous suggère de mettre du code dans cette structure et d'utiliser ce code

 -(void)yourMethod { __block UIBackgroundTaskIdentifier background_task; background_task = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^(void){ [[UIApplication sharedApplication] endBackgroundTask: background_task]; background_task = UIBackgroundTaskInvalid; }]; dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ //Some Methods Calls dispatch_async(dispatch_get_main_queue(), ^{ //View Controller Change }); }); } 

Comme vous construisez une application VOIP, dans info.plist, vous devriez être en mesure de définir UIBackgroundModes sur voip et UIApplicationExitsOnSuspend sur NO pour autoriser les tâches en arrière-plan.

Consultez cette page d'aide Apple sur «Déclarer les tâches d'arrière-plan sockets en charge par votre application» pour plus d'informations.

La dernière fois que j'ai créé une application en arrière-plan (même si c'était pour les services de localization, pas pour une application VoIP), j'ai dû mettre un avertissement sur la list des app stores concernant l'utilisation excessive de la batterie. Je ne suis pas sûr que cela soit pertinent.

Voir aussi cette réponse sur SO.

Au lieu d'utiliser un NSTimer, je vous suggérerais de programmer plusieurs UILocalNotification, chacun ayant un fireDate croissant, puis de définir le dernier son UILocalNotification pour l'intervalle augmenté. Par exemple, dites que votre son peut durer 20 secondes, puis vous programmez 3 UILocalNotification avec fireDate à 0, + 20, + 40 secondes à partir de maintenant.

Bien sûr, si l'user répond à votre appel, vous devez annuler le dernier UILocalNotification.