【问题标题】:How to ensure a CallKit Call is connected before Call is answered?如何在接听电话之前确保已连接 CallKit 电话?
【发布时间】:2020-03-23 08:47:50
【问题描述】:

我有一个带有 Sinch Video 集成的 VOIP 应用程序。如果应用程序从后台运行,则会有一个大约 1 - 3 秒的窗口,其中 VOIP 推送被发送,但 Sinch 呼叫尚未连接。 (iOS13要求立即上报VOIP Push)。

在 Apple 的文档中,他们给出了以下提示:

Responding to VoIP Notifications from PushKit

如果呼叫的接收者在应用程序与您的服务器建立连接之前应答,请不要立即执行发送给您的代理的 provider:performAnswerCallAction: 方法的 CXAnswerCallAction 对象。相反,等到您建立连接然后完成对象。当它等待您的应用完成请求时,来电界面让用户知道呼叫正在连接,但尚未准备好。

Facetime 也可以观察到这种行为,通常是在短时间内 CallKit 显示正在连接...

我终其一生都无法弄清楚如何正确遵循 Apple 文档中的这一建议。

我有什么办法可以按照标准让 AnswerCallAction 总是将接听过程延迟 2 秒?

这是我相关的提供者委托方法:

func provider(_ provider: CXProvider, perform action: CXAnswerCallAction) {
    if (!(CommunicationService.shared?.tellGuardAnswerCallAction())!){
        action.fail()
        print("CXCallDelegate CXProvider: ERROR Answering Call")
        return
    }
    self.callManager.removeAll()
    CommunicationService.shared?.cDotAnswer()
    action.fulfill()        
}

如果我在 Sinch 呼叫和 UIKit 呼叫连接之前接听电话,则呼叫将无法工作。所以理想情况下,我总是会给代码大约 1-2 秒的时间来连接或检查 Sinch 呼叫是否已连接,然后再继续执行 action.fulfill()

【问题讨论】:

    标签: sinch callkit cxprovider


    【解决方案1】:

    在我自己的情况下,如果手机被锁定并且我没有在 2 秒内调用 action.fulfill(),它会突然结束通话。

    最后几天后,最终的解决方案是使用 DispatchGroup。 DispatchGroup 将使 CallKit 等待完成。您可以阅读有关调度组的更多信息。

       let myGroup = DispatchGroup()
       myGroup.enter()
       let info = getInfoFromTheWeb()
       //When you get info from simple call
       myGroup.leave()
      //When your call leave() function following code will be execute
      myGroup.notify(queue: DispatchQueue.main) {
             action.fulfill
            }
    

    【讨论】:

      【解决方案2】:

      我也遇到过同样的问题。仅当应用处于后台且设备处于锁定状态时才会出现此问题。

      修复很简单。 Call Kit 报告新来电后,您需要在 performAnswerCallAction 方法中填写接听操作。

      - (void)provider:(CXProvider *)provider performAnswerCallAction:(CXAnswerCallAction *)action {
      
       UIApplicationState applicationState = [[UIApplication
       sharedApplication] applicationState];
       
       if(applicationState == 2){
       
               double delayInSeconds = 3.0;
               dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
               dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
                   NSLog(@"provider:performAnswerCallAction Fullfilled in Application Background State : %@", uuid);
                   [action fulfill];
               });
           }else{
               NSLog(@"provider:performAnswerCallAction Fullfilled in Application Foreground State : %@", uuid);
               [action fulfill];
       }
      
      }
      
      }
      

      Apple 建议我们等到连接建立后再执行 PerformAnswerAction。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-08-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-12-10
        • 2012-05-13
        • 1970-01-01
        相关资源
        最近更新 更多