Kakao i Connect Live 커뮤니티

Ios. remonCall. 연결은성공. 소리안들림

수고하십니다.

remonCall 를 사용하여 앱을 만들고 있습니다.
작업중인 앱을 실행시킨 상태 (foreground) 일때는
voip 받고, callkit 처리하고, channel id 를 이용하여 접속이 되고,
양쪽의 소리도 서로 잘 드립니다.

근데
앱을 kill 시킨상태에서는
voip 받고, callkit 처리하고, channel id 를 이용하여 접속이 되는데,
양쪽의 소리가 서로에게 들리지 않습니다.
remonCall.onInit
remonCall.onComplete
모두 정상적으로 호출되고,
console.remonmonster.com 사이트에서 해당 채널을 조회하면 연결은 잘 된걸로 나옵니다.
(channel id : 1602948380165_nisq0)

어떤 경우에, caller와 callee 가 연결은 되었는데
서로 소리가 안들릴까요?

  • sdk : 2.7.10
  • xcode : 12.0.1
  • language : swift 5
  • ios : 14.0.1

고객사명을 알 수 있을까요?
아니면 [email protected] 으로 문의 부탁합니다.

앱을 kill시킨 상태가 잘 이해가 되지 않습니다.

고객사명 : 당근영어(캐럿글로벌).
앱을 kill 시킨 상태 : 앱을 실행시키지 않은 상태 (foreground 아니고, background 도 아니고)
를 뜻합니다.

수고하십니다.
아직 이 문제가 해결되지 않아서 도움을 요청드립니다.
해당 소스는 아래와 같습니다.
보시고 잘못된 부분이 있으면 알려주시면 고맙겠습니다.

//
// MainVC+PKPush.swift
// CarrotCall
//
// Created by swlee on 2020/10/11.
//

import Foundation
import CallKit
import PushKit
import RemoteMonster

extension MainVC: CXProviderDelegate, PKPushRegistryDelegate {

func providerDidReset(_ provider: CXProvider) {
    
}

func provider(_ provider: CXProvider, perform action: CXAnswerCallAction) {
    doPrint("통화 응답 CXAnswerCallAction channelId = [\(channelId)]");
    action.fulfill()
    self.doRemonInit()
    remonCall.connect(channelId)
}

func provider(_ provider: CXProvider, perform action: CXStartCallAction) {
    doPrint("통화 시작 CXStartCallAction");
    action.fulfill()
}

func provider(_ provider: CXProvider, perform action: CXSetHeldCallAction) {
    doPrint("sender uuid", action.callUUID.uuidString)
    action.fulfill()
}

func provider(_ provider: CXProvider, perform action: CXEndCallAction) {
    doPrint("통화 종료 CXEndCallAction");
    action.fulfill()
    remonCall.closeRemon()
}



func pushRegistry(_ registry: PKPushRegistry, didInvalidatePushTokenFor type: PKPushType) {
    doPrint("pushRegistry didInvalidatePushTokenFor")
}

func pushRegistry(_ registry: PKPushRegistry, didUpdate pushCredentials: PKPushCredentials, for type: PKPushType) {
    doPrint("pushRegistry didUpdate")
    let token = pushCredentials.token.map { String(format: "%02.2hhx", $0) }.joined()
    //let d = NSData(data: pushCredentials.token)
    //print("token is data", d.description)
    doPrint("token is ", token)
    LibLocalData.doPushkitTokenSet(sPushkitToken: token)
}

func pushRegistry(_ registry: PKPushRegistry, didReceiveIncomingPushWith payload: PKPushPayload, for type: PKPushType, completion: @escaping () -> Void) {
    doPrint("pushRegistry didReceiveIncomingPushWith")
    doPrint(payload)
    
    let dicPayload:[AnyHashable: Any] = payload.dictionaryPayload
    if let target:[String: String] = dicPayload["target"] as? [String: String] {
        
        doPrint(target["deviceId"])
        doPrint(target["idKey"])
        doPrint(target["channelId"])
        doPrint(target["idxSchedule"])
        doPrint(target["url"])
        let uuid = UUID()
        doPrint(uuid.uuidString)
        doPrint("-------------------------")
        
        let idKey:String = target["idKey"] ?? ""
        if let channelId_:String = target["channelId"] {
            channelId = channelId_
            update.remoteHandle = CXHandle(type: .generic, value: idKey)
            provider.reportNewIncomingCall(with: uuid, update: update, completion: { error in })
        }
    }
}


func doVoipRegistration() {
    let mainQueue = DispatchQueue.main
    let voipRegistry: PKPushRegistry = PKPushRegistry(queue: mainQueue)
    voipRegistry.delegate = self
    voipRegistry.desiredPushTypes = [.voIP]
}


func doCxProviderInit() {
    if provider != nil {return}
    let cxProviderConf:CXProviderConfiguration = CXProviderConfiguration()
    cxProviderConf.supportsVideo = false
    cxProviderConf.supportedHandleTypes = [.generic]
    cxProviderConf.maximumCallGroups = 1
    cxProviderConf.maximumCallsPerCallGroup = 5
    provider = CXProvider(configuration: cxProviderConf)
    provider.setDelegate(self, queue: nil)
}


func doRemonInit() {
    doPrint("doRemonInit()...")
    
    remonCall.onInit {
        doPrint("********** remonCall.onInit")
        DispatchQueue.main.async {
        }
    }
    
    remonCall.onComplete { () in
        doPrint("********** remonCall.onComplete")
        DispatchQueue.main.async {
            // 녹음 시작
            self.doRecordingStart()
        }
    }
            
    remonCall.onClose { (_) in
        doPrint("********** remonCall.onClose")
        DispatchQueue.main.async {
            self.remonCall.closeRemon()
            self.doRecordingFinish(success: true)
        }
    }
    
    remonCall.onError { (error) in
        doPrint("********** remonCall.onError")
        doPrint(error.localizedDescription)
        DispatchQueue.main.async {
            //error.localizedDescription
            self.doRecordingFinish(success: true)
        }
    }

}

}

도움이 되실지 모르겠습니다만…
remonclient 초기화때에
RemonClient.setAudsioSessionConfiguration() 를 호출하여
webrtc AVAudioSession을 설정하는 정도를 가이드드릴 수 있을것 같습니다.

자답입니다.
혹시 비슷한 현상을 겪으시는 분들을 위하여 적습니다.
provider 의 CXAnserCallAction 에서 AudioSession 설정을 하고
provider 의 didActivate audioSession 에서 remonCall 을 초기화 했습니다.

func provider(_ provider: CXProvider, perform action: CXAnswerCallAction) {
    doPrint("통화 응답 CXAnswerCallAction channelId = [\(channelId)]");
    action.fulfill()
    
    do {
        try AVAudioSession.sharedInstance().setCategory(AVAudioSession.Category.playAndRecord,
                                                        mode: AVAudioSession.Mode.voiceChat,
                                                        options: .mixWithOthers)
        try AVAudioSession.sharedInstance().overrideOutputAudioPort(.speaker)
        try AVAudioSession.sharedInstance().setActive(true)
    } catch {
        doPrint(error)
    }
    
}

func provider(_ provider: CXProvider, didActivate audioSession: AVAudioSession) {
    doPrint("통화 audioSession didActiveate. CXAnswerCallAction channelId = [\(channelId)]");
    self.doRemonInit()
    self.remonCall.connect(self.channelId)
}



func doRemonInit() {
    doPrint("doRemonInit()...")

    remonCall = RemonCall()
    self.remonCall.serviceId = "111"
    self.remonCall.serviceKey = "222"
    self.remonCall.serviceToken = "333"
    self.remonCall.onlyAudio = true
    self.remonCall.audioType = "voice"
    self.remonCall.audioAutoGain = true
    
    remonCall.onInit {
        doPrint("********** remonCall.onInit")
        DispatchQueue.main.async {
        }
    }
            
    remonCall.onComplete { () in
        doPrint("********** remonCall.onComplete")
        DispatchQueue.main.async {
        }
    }
            
    remonCall.onClose { (_) in
        doPrint("********** remonCall.onClose")
        DispatchQueue.main.async {
            self.remonCall.closeRemon()
        }
    }
    
    remonCall.onError { (error) in
        doPrint("********** remonCall.onError")
        doPrint(error.localizedDescription)
        DispatchQueue.main.async {
            //error.localizedDescription
        }
    }

}