Skip to main content
Version: 5.5

1-to-1 audio call

This page provides a code example for making a 1-to-1 audio call.

Prerequisites

Before you begin, you must do the following:

Considerations for implementing a 1-to-1 audio call

To receive call notifications on the callee side, you must implement a notification system or integrate an external push notification system such as Firebase Cloud Messaging (FCM).

You also need to know what information must be delivered to the callee. Refer to Role of the app server, which describes cc_param, the data that must be delivered by your application.

After calling makeCall() or verifyCall(), you must check the reason property of the returned PlanetKitCallResult.

  • If the reason is PlanetKitStartFailReason.NONE, it means success.
  • Otherwise, it means failure and you must take an appropriate action based on the reason.

Request permissions

An application must acquire the following runtime permissions before making calls.

  • Manifest.permission.READ_PHONE_STATE
  • Manifest.permission.RECORD_AUDIO
  • Manifest.permission.BLUETOOTH_CONNECT (For targetSdkVersion 31 or higher only)

Prepare variables

Prepare variables for key properties and an event listener.

PlanetKitMyMediaStatusListener is used to handle the local user's media status change events. You can update the local user's UI based on these events, such as when the mic becomes muted or unmuted, or when the audio description is updated.

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.
}
}

Make an outgoing call (caller side)

To make a call, call PlanetKit.makeCall() with a proper PlanetKitMakeCallParam. To build a PlanetKitMakeCallParam, use 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.
}
}

Respond to an incoming call (callee side)

Android apps typically use Firebase Cloud Messaging (FCM) for the push notification. Android provides a base class called FirebaseMessagingService for receiving messages from FCM.

When you receive a push message, you must parse the cc_param from the message and create a cCParam. This data is a required argument that must be passed when responding to a call.

To respond to a call, build PlanetKitVerifyCallParam and then call 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.
}
}
}

Accept an incoming call (callee side)

In general, the recipient needs time to decide whether to accept a new call after responding to the call. To accept a call, call acceptCall().

Tip

The call variable is the PlanetKitCall instance that has been verified by verifyCall().

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
}

Set the media status listener for the local user (Optional)

Once the call is connected, add the media status listener for the local user depending on your needs.

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

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

return true
}

End a call

To end a call, call endCall().

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

call.endCall()

return true
}