简体   繁体   English

CallKit:在 GSM 通话断开后恢复保持的 VoIP 通话

[英]CallKit: Resume an on hold VoIP call after GSM call disconnects

I'm experiencing an issue where I'm unable to resume an on hold VoIP call after a GSM call is disconnected by the calling person.我遇到了一个问题,即在主叫方断开 GSM 呼叫后,我无法恢复暂停的 VoIP 呼叫。

Scenario one that works fine :工作正常的场景一

  1. I answer an incoming VoIP call我接听 VoIP 来电
  2. I get a GSM call, press 'hold and accept', which results in provider(_ provider: CXProvider, perform action: CXSetHeldCallAction) being called, allowing me to put the VoIP call on hold我接到一个 GSM 电话,按“保持并接受”,这导致provider(_ provider: CXProvider, perform action: CXSetHeldCallAction)被调用,允许我将 VoIP 通话置于保持状态
  3. I hang up the GSM call which results in provider(_ provider: CXProvider, perform action: CXSetHeldCallAction) being called, allowing me to un-hold the VoIP call我挂断了导致provider(_ provider: CXProvider, perform action: CXSetHeldCallAction)被调用的 GSM 通话,允许我取消保留 VoIP 通话

Scenario two :场景二

  1. I answer an incoming VoIP call我接听 VoIP 来电
  2. I get a GSM call, press 'hold and accept', which results in provider(_ provider: CXProvider, perform action: CXSetHeldCallAction) being called, allowing me to put the VoIP call on hold我接到一个 GSM 电话,按“保持并接受”,这导致provider(_ provider: CXProvider, perform action: CXSetHeldCallAction)被调用,允许我将 VoIP 通话置于保持状态
  3. The caller hangs up the GSM call, but provider(_ provider: CXProvider, perform action: CXSetHeldCallAction) is not called主叫挂断GSM通话,但是provider(_ provider: CXProvider, perform action: CXSetHeldCallAction)没有被调用

In scenario two only provider(_ provider: CXProvider, didDeactivate audioSession: AVAudioSession) is called after the caller hangs up the GSM call.在场景二中,呼叫者挂断 GSM 呼叫后,仅调用provider(_ provider: CXProvider, didDeactivate audioSession: AVAudioSession)

How can we resume a VoIP call after a GSM is disconnected by the caller if provider(_ provider: CXProvider, perform action: CXSetHeldCallAction) is not called?如果provider(_ provider: CXProvider, perform action: CXSetHeldCallAction)未被调用,我们如何在呼叫者断开 GSM 后恢复 VoIP 呼叫?

public func provider(_ provider: CXProvider, perform action: CXSetHeldCallAction)
{
    print("Callkit: provider(_ provider: CXProvider, perform action: CXSetHeldCallAction): \(action.callUUID)")
        
    guard var call = callManager.call(withUUID: action.callUUID) else {
        action.fail()
        return
    }
        
    call.isOnHold = action.isOnHold
    call.isMuted = call.isOnHold
        
    audioRouter.audioDevice.isEnabled = !call.isOnHold
        
    action.fulfill()
}

After A GSM call is ended, applicationDidBecomeActive will be called when returning to the app. GSM通话结束后,返回app时会调用applicationDidBecomeActive At this point we can detect if a call is on hold and resume it.此时,我们可以检测呼叫是否处于保持状态并恢复它。 Other solutions welcome.欢迎其他解决方案。

I ran into this today.我今天遇到了这个。 After some Googling, I was unable to find a solution.经过一些谷歌搜索,我无法找到解决方案。 So strange, I thought, that nobody has solved this.太奇怪了,我想,没有人能解决这个问题。 I was able to find a solution inspired by @Simon, but I think a bit cleaner.我能够找到受@Simon 启发的解决方案,但我认为更简洁一些。

In your CallViewController, AppDelegate, or similar, set yourself as the CXCallObserver's delegate.在您的 CallViewController、AppDelegate 或类似内容中,将您自己设置为 CXCallObserver 的委托。

CXCallController.shared.callObserver.setDelegate(self, queue: .main)

Then later, you want to detect if there is exactly one active call, it's "yours" (whatever that means for you. For me it's stored in self.call.id ) and that it's on hold.然后,您想检测是否恰好有一个活动呼叫,它是“您的”(无论这对您意味着什么。对我来说,它存储在self.call.id中)并且它处于暂停状态。 If so, you can request an update to "unhold" it, and your code elsewhere that handles func provider(_ provider: CXProvider, perform action: CXSetHeldCallAction) will get invoked, and hopefully your app handles it correctly.如果是这样,您可以请求更新以“取消保留”它,并且您在其他地方处理func provider(_ provider: CXProvider, perform action: CXSetHeldCallAction)的代码将被调用,并希望您的应用程序正确处理它。

  //MARK: - CXCallObserverDelegate
  
  func callObserver(_ callObserver: CXCallObserver, callChanged call: CXCall) {
    guard let activeCall = callObserver.calls.first,
          1 == callObserver.calls.count,
          activeCall.uuid == self.call.id,
          true == activeCall.isOnHold else {
      return
    }
    let transaction = CXTransaction(action: CXSetHeldCallAction(call: activeCall.uuid, onHold: false))
    CXCallController.shared.request(transaction) { error in
      if let error = error {
        //handle it?
      }
    }
  }

When you get an incoming call, from say, WhatsApp, and your app is put on hold, CXCallObserver.shared.calls will return two calls.当您接到来自 WhatsApp 的来电,并且您的应用程序被搁置时, CXCallObserver.shared.calls将返回两个呼叫。 One will be "yours" on hold, and the other will be "the WhatsApp call" not on hold.一个将是“您的”暂停,另一个将是“WhatsApp 通话”而不是暂停。 Once the WhatsApp call is terminated on the other end, CXCallObserver.shared.calls will only return one call, yours, but it will still be on hold.一旦 WhatsApp 呼叫在另一端终止, CXCallObserver.shared.calls将只返回一个呼叫,即您的呼叫,但仍将处于保持状态。 This seems like a fairly egregious bug in CallKit.这似乎是 CallKit 中一个相当严重的错误。 But what do I know?但我知道什么?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM