# CallKit

برای نمایش و مدیریت تماس پیشنهاد می کنیم از CallKit استفاده کنید. CallKit مدیریت یکپارچه ای برای تماس های برنامه شما و تماس های برنامه های دیگر و سیستم فراهم می آورد.

# مزایا

  • ادغام کردن تماس برنامه شما با سرویس تماس سیستم عامل
  • فراهم کردن ظاهر تماس
  • نمایش تماس برنامه شما زمانی که موبایل قفل می باشد

# پیاده سازی

import CallKit
import AVFoundation
extension CallViewController: CXProviderDelegate {

    func callKitConfig() {

        let cxProviderConfig = CXProviderConfiguration(localizedName: "KavenegarCall Sample")
        cxProviderConfig.maximumCallGroups = 1
        cxProviderConfig.maximumCallsPerCallGroup = 1
        cxProviderConfig.supportsVideo = false
        cxCallProvider = CXProvider(configuration: cxProviderConfig)
        cxCallProvider.setDelegate(self, queue: nil)

        cxCallController = CXCallController()

        cxCallUpdate = CXCallUpdate()
        cxCallUpdate.supportsDTMF = false
        cxCallUpdate.supportsHolding = false
        cxCallUpdate.supportsGrouping = false
        cxCallUpdate.supportsUngrouping = false
        cxCallUpdate.hasVideo = false

    }


    func startOutgoingCall(call: Call) {

        guard let callID = UUID(uuidString: call.id) else  {
            return
        }

        let callHandle = CXHandle(type: .generic, value: call.receptor.userName)
        let startCallAction = CXStartCallAction(call: callID, handle: callHandle)
        startCallAction.isVideo = false
        let transaction = CXTransaction(action: startCallAction)

        cxCallController.request(transaction)  { error in
            if let error = error {
                self.logger.error("StartCallAction transaction request failed: \(error.localizedDescription)")
                return
            }

            self.logger.info("StartCallAction transaction request successful")
            self.audioManeger.configureAudioSession()

        }

    }

    func startIncomingCall(call: Call) {

        guard let callID = UUID(uuidString: call.id) else {
            return
        }

        self.cxCallUpdate.remoteHandle = CXHandle(type: .generic, value: call.caller.userName)

        self.cxCallProvider.reportNewIncomingCall(with: callID, update: cxCallUpdate) { error in
            if let error = error {
                self.logger.error("Failed to report incoming call successfully: \(error.localizedDescription)")
                return
            }

            self.logger.info("Incoming call successfully reported.")
            self.audioManeger.configureAudioSession()
        }

    }


    func endCall(call: Call) {
        guard let uuid = UUID(uuidString: call.id) else {
            return
        }
        self.cxCallProvider.reportCall(with: uuid, endedAt: Date(), reason: .remoteEnded)
    }

    func muteCall(){

        let setMutedCallAction = CXSetMutedCallAction(call: UUID(uuidString: self.call.id)!, muted: avanegar.peerConnection.isMuted)
        let transaction = CXTransaction(action: setMutedCallAction)

        cxCallController.request(transaction) { error in
            if let error = error {
                self.logger.error("CXSetMutedCallAction transaction request failed: \(error.localizedDescription).")
                self.mute()
                return
            }
            self.logger.info("CXSetMutedCallAction transaction request successful")
        }
    }

    func providerDidReset(_ provider: CXProvider) {
        logger.info(provider.debugDescription)
    }

    func provider(_ provider: CXProvider, perform action: CXAnswerCallAction) {
        logger.info("CXAnswerCallAction \(provider.debugDescription, action.debugDescription)")

        do {
            try self.call.accept()
            self.startCommiunication()
            action.fulfill()
        } catch let error {
            logger.error(error.localizedDescription)
        }

    }

    func provider(_ provider: CXProvider, perform action: CXEndCallAction) {
        logger.info("CXEndCallAction \(provider.debugDescription, action.debugDescription)")
        action.fulfill()

        do {
            if self.call.direction == .inbound && self.call.status == .ringing {
                try self.call.reject()
            } else {
                try self.call.hangup()
            }

        }catch let error {
            logger.error("CXEndCallAction \(error.localizedDescription)")
            action.fail()
        }

    }

    func provider(_ provider: CXProvider, perform action: CXStartCallAction) {
        logger.info("CXStartCallAction \(provider.debugDescription, action.debugDescription)")
        action.fulfill(withDateStarted: Date())
    }

    func provider(_ provider: CXProvider, perform action: CXSetMutedCallAction) {
        logger.info("CXSetMutedCallAction \(provider.debugDescription, action.debugDescription)")
        self.mute()
        action.fulfill()
    }

    func provider(_ provider: CXProvider, didActivate audioSession: AVAudioSession) {
        logger.info("didActivate audioSession \(provider.debugDescription, audioSession.debugDescription)")
        audioManeger.configureAudioSession()
    }


    func provider(_ provider: CXProvider, didDeactivate audioSession: AVAudioSession) {
        logger.info("didDeactivate audioSession \(provider.debugDescription, audioSession.debugDescription)")
        audioManeger.configureAudioSession()
    }

    func providerDidBegin(_ provider: CXProvider) {
        logger.info("providerDidBegin \(provider.debugDescription)")
    }

}