famfamfam
famfamfam

Reputation: 535

Swift callkit sometimes can't activate loudspeaker after received call (only incoming call)

after follow @Marco comment, i updated code like below, but still not working, the loudspeaker sometimes can not enabled

Before report new call/ user accepted call I called the 2 methods below:

configureAudioSessionToDefaultSpeaker()
func configureAudioSessionToDefaultSpeaker() {
    let session = AVAudioSession.sharedInstance()
        do {
            try session.setCategory(AVAudioSession.Category.playAndRecord, mode: .default)
            try session.setActive(true)
            try session.setMode(AVAudioSession.Mode.voiceChat)
            try session.setPreferredSampleRate(44100.0)
            try session.setPreferredIOBufferDuration(0.005)
        } catch {
            print("Failed to configure `AVAudioSession`: \(error)")
        }
}

I updated more code:

func startCallWithPhoneNumber(call : CallInfoModel) {
        
        configureAudioSessionToDefaultSpeaker()
        currentCall = call
        if let unwrappedCurrentCall = currentCall {
            let handle = CXHandle.init(type: .generic, value: unwrappedCurrentCall.CallerDisplay ?? UNKNOWN)
            let startCallAction = CXStartCallAction.init(call: unwrappedCurrentCall.uuid, handle: handle)
            let transaction = CXTransaction.init()
            transaction.addAction(startCallAction)
            requestTransaction(transaction: transaction)
            
            self.provider?.reportOutgoingCall(with: startCallAction.callUUID, startedConnectingAt: nil)
            
        }
    }
 func provider(_ provider: CXProvider, perform action: CXAnswerCallAction) {
        
            
        configureAudioSessionToDefaultSpeaker()

        delegate?.callDidAnswer()
        action.fulfill()
        currentCall?.isAccepted = true
        let sb = UIStoryboard(name: "main", bundle: nil)
        let vc = sb.instantiateViewController(withIdentifier: "SingleCallVC") as! SingleCallVC
        vc.modalPresentationStyle = .fullScreen
        vc.callObj = currentCall
        vc.isIncoming = true
        let appDelegate = AppDelegate.shared
        appDelegate.window?.rootViewController?.present(vc, animated: true, completion: nil)
        
    }

My call almost work normally but sometime loudspeaker can not be enabled. I read many documents but nothing worked for me. Could someone give me some advice? Thanks.

Upvotes: 1

Views: 1972

Answers (2)

Hamer
Hamer

Reputation: 1383

I've had success with enabling the speaker using the method below.

let audioQueue = DispatchQueue(label: "audio")    

func setSpeaker(_ isEnabled: Bool) {
    audioQueue.async {
        defer {
            AVAudioSession.sharedInstance().unlockForConfiguration()
        }
        
        AVAudioSession.sharedInstance().lockForConfiguration()
        do {
            try AVAudioSession.sharedInstance().overrideOutputAudioPort(isEnabled ? .speaker : .none)
        } catch {
            debugPrint(error.localizedDescription)
        }
    }
}

// Enables the audio speaker.
setSpeaker(true)

// Disables the audio speaker.
setSpeaker(false)

Upvotes: 1

Marco
Marco

Reputation: 1686

You're configuring the AudioSession two times. The RTCAudioSession it's a proxy of AVAudioSession. You should do only one configuration to avoid unexpected results. RTCAudioSession should expose all the methods of the AVAudioSession, so you should be able to make all the configurations you want inside configureRtcAudioSession() and eliminate configureAudioSessionToDefaultSpeaker() or viceversa. I'm not sure if it will solve your issue but at least it should help to avoid unexpected behaviors.

Upvotes: 1

Related Questions