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

时间:2014-01-17 20:58:30

标签: ios core-telephony

CTCallCenter的文档:setCallEventHandler:声明:

  

但是,您的应用程序也可以进行呼叫事件   暂停。暂停时,您的应用程序无法接收   通话活动。当您的应用程序恢复活动状态时,它   每次更改状态的调用都会收到一个调用事件

与此问题相关的部分是

  

当您的应用程序恢复活动状态时,它会收到一个   每次更改状态的呼叫都会调用事件

暗示应用程序将在应用程序暂停时收到过去发生的呼叫的呼叫事件。根据这个问题的答案,这是可能的:How does the Navita TEM app get call log information?

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

我尝试了很多很多代码实验,但是当我的应用程序恢复活动状态时,无法检索任何调用信息。

这是我尝试过的最简单的事情: 1)使用Xcode单视图应用程序模板创建一个新项目。 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;
}

使用此代码,如果应用程序在调用发生时位于前台,我可以获取调用事件。但是,如果我在拨打电话之前离开应用程序,那么当我的应用程序下一次恢复活动状态时,我无法收到呼叫事件 - 正如它在Apple文档中所说的那样。

我尝试过的其他事情:

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

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

3)向应用添加背景功能 - 通过beginBackgroundTaskWithExpirationHandler和/或使用startUpdatingLocation或startMonitoringForSignificantLocationChanges进行位置更新。

4)以上的各种组合。

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

这是在iOS 7上。

2 个答案:

答案 0 :(得分:14)

我找到了一个解决方案,但我不知道它为什么会起作用。我唯一能想到的是GCD和/或CoreTelephony中的错误。

基本上,我像这样分配了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
    }

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

答案 1 :(得分:3)

在我的情况下,我正在开发一个企业应用,它不需要Apple的应用市场批准 - 所以如果您开发企业应用这个解决方案是给你的。

此外,当应用为背景时,所选答案

解决方案很简单,基本上你只需要在Capabilities选项卡中添加2个功能(VOIP& Background fetch):

  • 您的项目目标 - >能力 - >背景模式 - >标记 IP语音& 后台提取

enter image description here

现在,您的应用已注册到iOS框架调用“委托”,因此OP代码剪辑解决方案:

[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");
         }
     }];  

即使您的应用处于后台,您也会获得通知。