如何使用CTCallCenter获取呼叫事件:setCallEventHandler:应用程序被挂起时发生的事件?

CTCallCenter的文档:setCallEventHandler:声明:

但是,通话事件也可能在您的应用程序被暂停时发生。 它被暂停时,您的应用程序不会收到通话事件。 当您的应用程序恢复活动状态时,它会为每个改变状态的呼叫接收一个呼叫事件

这个问题的相关部分是

当您的应用程序恢复活动状态时,它会为每个改变状态的呼叫接收一个呼叫事件

暗示该应用程序将收到一个呼叫事件的过去发生的应用程序被暂停时发生。 根据这个问题的答案,这是可能的: Navita TEM应用程序如何获得通话logging信息?

我的问题是:如果我的应用程序被暂停,并且发生了一个调用,那么当我的应用程序恢复活动状态时,如何检索发生的调用事件?

我已经尝试了许多代码实验,但是当我的应用程序恢复到活动状态时,却无法检索到任何呼叫信息。

这是我尝试过的最简单的事情:1)使用Xcode单一视图应用程序模板创build一个新项目。 2)添加如下代码到didFinishLaunchingWithOptions 3)启动应用程序4)任务离开应用程序5)拨打另一个设备的电话,接听电话,挂断来自任一设备的呼叫6)将应用程序带回前台从而恢复活动状态。

注册通话事件的代码是:

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

有了这个代码,我可以获得通话事件,如果应用程序在前台发生呼叫。 但是如果我在拨打电话之前离开应用程序,那么当我的应用程序下一次恢复到活动状态时,我无法获得通话事件 – 正如它在苹果文档中所述的那样。

其他的东西,我试过了:

1)文档指出,块对象是在默认优先级的全局调度队列上调度的,所以我试着把dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{})的setCallEventHandler的注册

2)调用setCallEventHandler:在appBecameActive而不是didFinishLaunchingWithOptions

3)向应用程序添加背景能力 – 通过beginBackgroundTaskWithExpirationHandler和/或位置更新使用startUpdatingLocation或startMonitoringForSignificantLocationChanges。

4)以上的各种组合。

一旦我的代码在我的设备上运行,即可以获得在应用程序暂停时发生的通话事件,即可获得赏金。

这是在iOS 7上。

我find了一个解决scheme,但我不知道为什么它的工作。 只有我能想到的是GCD和/或CoreTelephony中的一个bug。

基本上,我这样分配两个CTCallCenter实例

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

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 } 

为了testing这个,我拨打了一个电话,回答了这个问题,然后在应用程序处于后台时挂起了它。 当我启动它时,我收到3个呼叫事件:传入,连接,断开连接。

就我而言,我正在开发一个企业应用程序 ,不需要苹果应用程序市场的批准,所以如果您开发一个企业应用程序,这个解决scheme是为您服务的。

另外,当应用程序是背景时,select的答案不起作用。

解决scheme很简单,基本上你只需要在Capabilities选项卡中添加2个function(VOIP和Background fetch):

  • 您的项目目标 – >function – >背景模式 – >标记语音IP后台获取

在这里输入图像说明

现在,你的应用程序被注册到iOS框架调用“委托”,所以OP代码片段解决scheme:

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

即使你的应用程序在后台,你将会收到通知。