본문으로 건너뛰기
Version: 5.5

1대1 음성 통화

1대1 음성 통화를 구현하는 예제 코드입니다.

필수 조건

시작하기 전에 다음 작업을 수행해야 합니다.

1대1 음성 통화 구현 시 고려 사항

착신자 측에서 통화 알림을 받으려면 알림용 시스템을 구현하거나 FCM(Firebase Cloud Messaging) 같은 외부 푸시 알림 시스템을 연동해야 합니다.

또한 착신자에게 어떤 정보를 전달해야 하는지도 알아야 합니다. 앱 서버의 역할에서 애플리케이션이 전달해야 하는 데이터인 cc_param에 관해 볼 수 있습니다.

makeCall() 또는 verifyCall()을 호출한 다음에는 반환된 PlanetKitCallResultreason 속성을 확인해야 합니다.

  • reasonPlanetKitStartFailReason.NONE인 경우 성공을 의미합니다.
  • 그렇지 않으면 실패를 의미하며 reason에 따라 적절한 조치를 취해야 합니다.

권한 요청

통화하기 전에 다음의 런타임 권한을 획득하세요.

  • Manifest.permission.READ_PHONE_STATE
  • Manifest.permission.RECORD_AUDIO
  • Manifest.permission.BLUETOOTH_CONNECT (targetSdkVersion 31 이상)

변수 준비

주요 속성 및 이벤트 리스너에 대한 변수를 준비합니다.

PlanetKitMyMediaStatusListener는 로컬 사용자의 미디어 상태 변경 이벤트를 처리하는 데 사용됩니다. 마이크가 음소거되거나 음소거 해제되는 경우 또는 오디오 설명이 업데이트되는 경우 등 이벤트를 기반으로 로컬 사용자의 UI를 업데이트할 수 있습니다.

val myUserId = "test user id"      // The local user's user ID
val serviceId = "test service id" // Service ID

// PlanetKitMyMediaStatusListener object
val myMediaStatusListener = object : PlanetKitMyMediaStatusListener {
override fun onMyAudioMuted() {
// This is called when the local user's audio is muted.
// Write your own code here.
}

override fun onMyAudioUnmuted() {
// This is called when the local user's audio is unmuted.
// Write your own code here.
}

override fun onMyAudioDescriptionUpdated(audioDescription: PlanetKitAudioDescription) {
// This is called when the local user's audio description is updated.
// Write your own code here.
}
}

통화 생성(발신 측)

통화를 생성하려면 적절한 PlanetKitMakeCallParam과 함께 PlanetKit.makeCall()을 호출하세요. PlanetKitMakeCallParam을 만들려면 PlanetKitMakeCallParam.Builder()를 사용하세요.

fun makeCallExample(peerId: String, accessToken: String)
{
val makeCallParam = PlanetKitMakeCallParam.Builder()
.myId(myUserId)
.myServiceId(serviceId)
.peerId(peerId)
.peerServiceId(serviceId)
.accessToken(accessToken)
.build()

var result = PlanetKit.makeCall(makeCallParam, makeCallListener = object : MakeCallListener
{
override fun onWaitConnected(call: PlanetKitCall)
{
// This is called after making a call.
// Write your own code here.
}

override fun onConnected(call: PlanetKitCall, param: PlanetKitCallConnectedParam)
{
// This is called after the call is connected.
// Write your own code here.
}

override fun onDisconnected(call: PlanetKitCall, param: PlanetKitDisconnectedParam)
{
// This is called after the call is disconnected.
// Write your own code here.
}
})

if (result.reason == PlanetKitStartFailReason.NONE)
{
// The "result.call" instance is the main instance to call APIs from now on.
// You must keep it to control this call.
// See call.instanceId and PlanetKit.getCall(instanceId).
}
else
{
// result.reason: PlanetKitStartFailReason describes why makeCall failed.
}
}

통화 수신(착신 측)

Android 앱은 보통 푸시 알림용으로 Firebase Cloud Messaging(이하 FCM)을 사용합니다. Android는 FCM으로부터 메시지를 수신할 용도로 FirebaseMessagingService라는 기본 클래스를 제공합니다.

푸시 메시지를 받으면 메시지로부터 cc_param을 파싱하여 cCParam을 생성해야 합니다. 이 데이터는 통화에 응답할 때 전달해야 하는 필수 인자입니다.

통화에 응답하려면 PlanetKitVerifyCallParam을 만든 다음 PlanetKit.verifyCall()을 호출하세요.

class YourFirebaseMessagingService : FirebaseMessagingService()
{
override fun onMessageReceived(message: RemoteMessage)
{

val cCParamStr = message.data["cc_param"]
if (cCParamStr.isNullOrBlank())
{
Log.e("Push", "Empty message from application server")
return
}

val cCParam = PlanetKitCCParam.create(cCParamStr)
if (cCParam == null) {
Log.e(TAG, "Can not create PlanetKitCCParam. Check cCParamStr=$cCParamStr")
return
}

Log.d("Push","ccParam{peerId=${cCParam.peerId}, peerServiceId=${cCParam.peerServiceId}, mediaType=${cCParam.mediaType}")

val verifyCallParam = PlanetKitVerifyCallParam.Builder()
.myId(myUserId)
.serviceId(serviceId)
.cCParam(cCParam)
.build()

val result = PlanetKit.verifyCall(verifyCallParam, verifyListener = object : VerifyListener
{
override fun onVerified(call: PlanetKitCall, peerStartMessage: PlanetKitCallStartMessage?, peerUseResponderPreparation: Boolean)
{
// This is called after verifying a call.
// Write your own code here.
// For example, you can show a notification and switch to your ringing screen.
//
// The "call" is the verified call instance.
// If you send an instance of call through 'Intent of Android',
// then you can use the "call.instanceId".
// You can get the instance of call with the API "PlanetKit.getCall(instanceId)".

}

override fun onDisconnected(call: PlanetKitCall, param: PlanetKitDisconnectedParam)
{
// This is called after the call is disconnected.
// Write your own code here.
}
})

// Store result.call or result.call.instanceId for acceptCall().
if (result.reason == PlanetKitStartFailReason.NONE)
{
// The "result.call" instance is the main instance to call APIs from now on.
// You must keep it to control this call.
// See call.instanceId and PlanetKit.getCall(instanceId).
}
else
{
// result.reason: PlanetKitStartFailReason describes why verifyCall failed.
}
}
}

통화 응답(착신 측)

일반적으로 통화를 수신한 후 통화를 받을 것인지 아닌지 결정할 시간이 필요합니다. 통화에 응답하려면 acceptCall()을 호출하세요.

Tip

call 변수는 verifyCall()에서 검증을 마친 PlanetKitCall 인스턴스입니다.

fun acceptCallExample(instanceId: Int): Boolean
{
var call = PlanetKit.getCall(instanceId) ?: return false

call.acceptCall(listener = object : AcceptCallListener {
override fun onConnected(call: PlanetKitCall, param: PlanetKitCallConnectedParam) {
// This is called after the call is connected.
// Write your own code here.
}

override fun onDisconnected(call: PlanetKitCall, param: PlanetKitDisconnectedParam) {
// This is called after the call is disconnected.
// Write your own code here.
}
}
)

return true
}

로컬 사용자에 대한 미디어 상태 리스너 설정(선택 사항)

통화가 연결되면 필요에 따라 로컬 사용자에 대한 미디어 상태 리스너를 설정하세요.

fun setMyMediaStatusListenerExample(instanceId: Int): Boolean
{
var call = PlanetKit.getCall(instanceId) ?: return false

call.getMyMediaStatus()?.addHandler(myMediaStatusListener, null) {
}

return true
}

통화 종료

통화를 종료하려면 endCall()을 호출하세요.

fun endCallExample(instanceId: Int): Boolean
{
var call = PlanetKit.getCall(instanceId) ?: return false

call.endCall()

return true
}

관련 예제 코드

관련 문서