Comment get un événement d'appel à l'aide de CTCallCenter: setCallEventHandler: qui s'est produit pendant la suspension de l'application?

La documentation de CTCallCenter: setCallEventHandler: indique que:

Toutefois, des events d'appel peuvent également avoir lieu pendant que votre application est suspendue. Tant qu'il est suspendu, votre application ne reçoit pas d'events d'appel. Lorsque votre application reprend l'état actif, elle reçoit un seul événement d'appel pour chaque appel ayant changé d'état

La partie pertinente à cette question est

Lorsque votre application reprend l'état actif, elle reçoit un seul événement d'appel pour chaque appel ayant changé d'état

Impliquant l'application recevra un événement d'appel pour un appel qui a eu lieu dans le passé pendant la suspension de l'application. Et cela est possible en fonction de la réponse à cette question: Comment l'application TEM Navita reçoit-elle les informations du journal des appels?

Ma question est: si mon application est suspendue et qu'un appel a lieu, alors quand mon application reprend l'état actif, comment peut-elle récupérer l'événement d'appel pour l'appel qui a eu lieu?

J'ai essayé beaucoup, beaucoup d'expériences de code mais n'ai été capable de récupérer aucune information d'appel quand mon application a repris l'état actif.

C'est la chose la plus simple que j'ai essayée: 1) Créez un nouveau projet en utilisant le model d'application de vue unique de Xcode. 2) Ajouter le code ci-dessous à didFinishLaunchingWithOptions 3) Lancer l'application 4) Tâche loin de l'application 5) Passer un appel depuis un autre appareil, répondre à l'appel, raccrocher l'appel de l'un ou l'autre appareil 6) Ramener l'application au premier plan reprenant ainsi l'état actif.

Le code pour s'inscrire aux events d'appel est:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { self.callCenter = [[CTCallCenter alloc] init]; [self.callCenter setCallEventHandler:^(CTCall *call) { NSLog(@"Event handler called"); if ([call.callState isEqualToSsortingng: CTCallStateConnected]) { NSLog(@"Connected"); } else if ([call.callState isEqualToSsortingng: CTCallStateDialing]) { NSLog(@"Dialing"); } else if ([call.callState isEqualToSsortingng: CTCallStateDisconnected]) { NSLog(@"Disconnected"); } else if ([call.callState isEqualToSsortingng: CTCallStateIncoming]) { NSLog(@"Incomming"); } }]; return YES; } 

Avec ce code, je suis en mesure d'get des events d'appel si l'application est au premier plan lorsque l'appel se produit. Mais si je m'absente de l'application avant de passer l'appel, je ne parviens pas à get un événement d'appel lorsque mon application reprend l'état actif, comme indiqué dans la documentation Apple.

D'autres choses que j'ai essayées:

1) La documentation indique que l'object block est dissortingbué sur la queue de répartition globale par défaut, donc j'ai essayé de placer l'logging de setCallEventHandler dans dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{})

2) Appel de setCallEventHandler: dans appBecameActive au lieu de didFinishLaunchingWithOptions

3) Ajout des capacités d'arrière-plan à l'application – via beginBackgroundTaskWithExpirationHandler et / ou des mises à jour d'location en utilisant startUpdatingLocation ou startMonitoringForSignificantLocationChanges.

4) Diverses combinaisons de ce qui précède.

La prime sera accordée une fois que le code sera en cours d'exécution sur mon appareil, ce qui permettra d'get les events d'appel qui ont eu lieu pendant la suspension de l'application.

C'est sur iOS 7.

J'ai trouvé une solution mais je ne sais pas pourquoi ça marche. La seule chose que je peux penser est un bug dans GCD et / ou CoreTelephony.

Fondamentalement, CTCallCenter deux instances de CTCallCenter comme ceci

 void (^block)(CTCall*) = ^(CTCall* call) { NSLog(@"%@", call.callState); }; -(BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions { callCenter1 = [[CTCallCenter alloc] init]; callCenter1.callEventHandler = block; callCenter2 = [[CTCallCenter alloc] init]; callCenter2.callEventHandler = block; return YES; } 

Code similaire à Swift:

 func block (call:CTCall!) { println(call.callState) } func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { //Declare callcenter in the class like 'var callcenter = CTCallCenter()' callcenter.callEventHandler = block return true } 

Pour tester ceci j'ai fait un appel, y ai répondu et l'ai pendu alors que l'application était en arrière-plan. Quand je l'ai lancé, j'ai reçu 3 appels: entrants, connectés, déconnectés.

Dans mon cas, je travaillais sur une application d'entreprise qui n'a pas besoin d'être approuvée par le marché des applications d'Apple – donc si vous développez une application d'entreprise, cette solution est pour vous.

En outre, la réponse choisie n'a pas fonctionné pendant que l'application est l'arrière-plan.

La solution est simple, il suffit simplement d'append 2 capacités (VOIP & Background fetch) dans l'onglet Capabilities:

  • Votre cible de projet -> Capacités -> Modes d'arrière-plan -> Marquer la voix sur IP et l' extraction de fond

entrez la description de l'image ici

Maintenant, votre application est enregistrée dans les appels de framework iOS "delegate", donc la solution snip code OP:

 [self.callCenter setCallEventHandler:^(CTCall *call) { NSLog(@"Event handler called"); if ([call.callState isEqualToSsortingng: CTCallStateConnected]) { NSLog(@"Connected"); } else if ([call.callState isEqualToSsortingng: CTCallStateDialing]) { NSLog(@"Dialing"); } else if ([call.callState isEqualToSsortingng: CTCallStateDisconnected]) { NSLog(@"Disconnected"); } else if ([call.callState isEqualToSsortingng: CTCallStateIncoming]) { NSLog(@"Incomming"); } }]; 

Travailler avec défi et vous recevrez des notifications même si votre application est en arrière-plan.