1

I'm trying to implement a video chatting app using CallKit. The problem I'm running into is even when it's a video call, the proximity sensor is still triggering the blacking out of the screen. It was my assumption that this wouldn't be the case for video calls. Is there some configuration option I'm missing??

public class CallManager: NSObject {

  private let provider: CXProvider
  private let callController: CXCallController
  private var callAction: CXCallAction?

  private static var providerConfiguration: CXProviderConfiguration = {
    let config = CXProviderConfiguration(localizedName: "Hello")
    config.supportsVideo = true
    config.maximumCallsPerCallGroup = 1
    config.includesCallsInRecents = false
    config.supportedHandleTypes = [.generic]
    return config
  }()

  override init() {
    provider = CXProvider(configuration: CallManager.providerConfiguration)
    callController = CXCallController()
    super.init()
    provider.setDelegate(self, queue: nil)
  }

  public func setProviderDelegate(_ delegate: CXProviderDelegate) {
    provider.setDelegate(delegate, queue: nil)
  }

  public func startCall() {
    let cxhandle = CXHandle(type: .generic, value: "My Call")
    let startCallAction = CXStartCallAction(call: UUID(), handle: cxhandle)
    startCallAction.isVideo = true
    callAction = startCallAction
    let transaction = CXTransaction(action: startCallAction)
    requestTransaction(transaction, completion: { [weak self] error in
      if let error = error {
        self?.callAction = nil
        self?.loggingService.error("failed to start a call: \(error)")
      }
    })
  }

  public func endCall() {
    guard let currentCallAction = callAction else { return }

    let endCallAction = CXEndCallAction(call: currentCallAction.callUUID)
    let transaction = CXTransaction(action: endCallAction)
    requestTransaction(transaction) { [weak self] error in
      if let error = error {
        self?.loggingService.error("failed to end a call: \(error)")
      }
    }
  }

  fileprivate func requestTransaction(_ transaction: CXTransaction, completion: @escaping (Error?) -> Void) {
    callController.request(transaction) { error in
      completion(error)
    }
  }
}

extension CallManager: CXProviderDelegate {

  public func providerDidReset(_ provider: CXProvider) {
  }

  public func provider(_ provider: CXProvider, perform action: CXStartCallAction) {
    action.fulfill()
  }

  public func provider(_ provider: CXProvider, perform action: CXEndCallAction) {
    action.fulfill()
  }
}

I tried setting supportsVideo flag to true.. and using .playAndRecord AVAudioSession category with mode .videoChat.

I'm pretty sure Facebook messenger uses CallKit and their video calls don't black out with proximity changes.

1 Answers1

3

I think it's an audio route problem. The proximity sensor is automatically enabled when the output audio route is set to the receiver (the speaker on top of the screen that you take to the ear). In any other case (loudspeaker, headset, etc.) the proximity sensor is disabled. So you probably only have to change the output audio route.

Marco
  • 1,572
  • 1
  • 10
  • 21
  • Ah! When I use AirPods, the proximity sensor doesn't get triggered. But it's definitely still getting triggered with the loudspeaker which is a problem. Any ideas why? – Nick Bolton Apr 10 '22 at 11:00
  • Are you sure that you haven't selected the receiver with a very high volume instead of the loudspeaker? I've never experienced this problem with the loudspeaker on. – Marco Apr 11 '22 at 10:24
  • The speaker definitely is selected. The other oddity .. is when I select headphones, the proximity sensor is never fired, even if the audio route goes back to headset. – Nick Bolton Apr 12 '22 at 14:49
  • Have you tried to listen to the `AVAudioSession.routeChangeNotification` notification and print out the audio route to find out what it's really going on? – Marco Apr 13 '22 at 09:33