Skip to main content
Version: 5.5

Group video call

This page provides a code example for implementing a group video call.

Prerequisites

Before you begin, you must do the following:

Considerations for implementing a group video call

After calling joinConference(), you must check the reason property of the returned PlanetKitConferenceResult.

  • 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 device permissions

An application must acquire the following runtime permissions before starting a group call.

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

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, when the audio description is updated, or when the video status 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.
}

override fun onVideoStatusUpdated(videoStatus: PlanetKitVideoStatus) {
// This is called when the local user's video status is updated.
// Write your own code here.
}
}

Preview the local user's video

The preview feature allows the local user to preview their own video regardless of the group call session.

To starting previewing the local user's video, call startPreview() of PlanetKitCameraManager.

fun startPreviewExample(preview: PlanetKitVideoView)
{
PlanetKit.getCameraManager().startPreview(preview)
}

To stop previewing the local user's video, call stopPreview() of PlanetKitCameraManager.

fun stopPreviewExample(preview: PlanetKitVideoView)
{
PlanetKit.getCameraManager().stopPreview(preview)
}

Join a group call

To join a group call, call PlanetKit.joinConference() with a proper PlanetKitConferenceParam. To build a PlanetKitConferenceParam, use PlanetKitConferenceParam.Builder().

  • To join a group video call, call mediaType() of PlanetKitConferenceParam.Builder with PlanetKitMediaType.AUDIOVIDEO.
  • The local user's initial video state can be set with setInitialMyVideoState() of PlanetKitConferenceParam.Builder.
    • The default value of the initialMyVideoState property is PlanetKitInitialMyVideoState.RESUME.
    • If the local user's initial video state is set to paused by calling setInitialMyVideoState() with PlanetKitInitialMyVideoState.PAUSE, the local user's video is not transmitted. The local user's video can be transmitted by calling resumeMyVideo() after the call is connected.
fun joinConferenceExample(roomId: String, accessToken: String, initialMyVideoState: PlanetKitInitialMyVideoState)
{
val param = PlanetKitConferenceParam.Builder()
.myId(myUserId)
.roomId(roomId)
.myServiceId(serviceId)
.roomServiceId(serviceId)
.accessToken(accessToken)
.mediaType(PlanetKitMediaType.AUDIOVIDEO)
.setInitialMyVideoState(initialMyVideoState)
.build()

val result = PlanetKit.joinConference(param, conferenceListener = object : ConferenceListener {

override fun onConnected(conference: PlanetKitConference,
isVideoHwCodecEnabled: Boolean,
isVideoShareModeSupported: Boolean) {
// This is called when the call is connected.
// Write your own code here.
}

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

override fun onPeerListUpdated(param: PlanetKitConferencePeerListUpdatedParam) {
// This is called when the list of peers is updated.
// The following is an example function. For more information, see the "Manage peers using PlanetKitPeerControl" section.
handlePeerListUpdate(param)
}

override fun onPeersVideoUpdated(conference: PlanetKitConference, param: PlanetKitConferenceVideoUpdateParam) {
// This is called when the video of one or more peers is updated.
// Write your own code here.
}
})

if (result.reason == PlanetKitStartFailReason.NONE) {
// The "result.conference" instance is the main instance to call APIs from now on.
// You must keep it to control this call.
}
else {
// Handle an error by referring to result.reason.
}
}

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(): Boolean
{
var conference = PlanetKit.getConference() ?: return false

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

return true
}

Add a video view for the local user

Call addMyVideoView() to add a video view where the local user's video will be rendered. The rendering of the video starts or stops according to the local user's video status.

fun addMyVideoViewExample(myVideoView: PlanetKitVideoView): Boolean
{
var conference = PlanetKit.getConference() ?: return false

conference.addMyVideoView(myVideoView)

return true
}

Add a video view for a peer

Call addPeerVideoView() to add a video view where the peer's video will be rendered.

fun addPeerVideoViewExample(peer: PlanetKitConferencePeer, peerVideoView: PlanetKitVideoView): Boolean
{
var conference = PlanetKit.getConference() ?: return false

conference.addPeerVideoView(peer, peerVideoView)

return true
}

Create peer control for each peer

When the peer list is updated, create PlanetKitPeerControl for newly added peers and register a PeerControlListener object. You can handle the status change of each peer using the PeerControlListener.

class PeerContainer internal constructor(
peer: PlanetKitConferencePeer
) {
val peerControl: PlanetKitPeerControl = peer.createPeerControl()
?: throw IllegalStateException("Failed to create peer control.")

init {
val peerControlListener = object : PlanetKitPeerControl.PeerControlListener {
override fun onMicMuted(peer: PlanetKitConferencePeer) {
// This is called when the peer's audio is muted.
// Write your own code here.
}

override fun onMicUnmuted(peer: PlanetKitConferencePeer) {
// This is called when the peer's audio is unmuted.
// Write your own code here.
}

override fun onAudioDescriptionUpdated(
peer: PlanetKitConferencePeer,
audioDescription: PlanetKitAudioDescription
) {
// This is called when the peer's audio description is updated.
// Write your own code here. The following is an example of implementation.
val yourOwnThresholdTalkingVolumeLevel = 10
val isPeerTalking =
audioDescription.averageVolumeLevel >= yourOwnThresholdTalkingVolumeLevel
}

override fun onVideoUpdated(
peer: PlanetKitConferencePeer,
videoStatus: PlanetKitVideoStatus,
subgroupName: String?
) {
// This is called when the peer's video is updated.
// Write your own code here. The following is an example of implementation.
when (videoStatus.videoState) {
PlanetKitVideoStatus.VideoState.DISABLED -> {
// The peer's video is disabled.
// The video stops even if you don't call peerControl.stopVideo().
}

PlanetKitVideoStatus.VideoState.ENABLED -> {
// The peer's video is enabled.
// If you call peerControl.startVideo(), the peer's video is received and rendered.
peerControl.startVideo(
PlanetKitVideoResolution.RECOMMENDED,
subgroupName
)
}

PlanetKitVideoStatus.VideoState.PAUSED -> {
// Write your own code for paused video.
}
}
}

override fun onDisconnected(peer: PlanetKitConferencePeer) {
// This is called when the peer is disconnected from the call.
// Write your own code here.
}
}

peerControl.register(peerControlListener)
}
}

// Example function called in the onPeerListUpdated callback.
private val peerContainerList = mutableListOf<PeerContainer>()
fun handlePeerListUpdate(param: PlanetKitConferencePeerListUpdatedParam) {
// Process added peers.
for (addedPeer in param.addedPeers) {
// Create peer control for your class.
peerContainerList.add(PeerContainer(addedPeer))
}

// Process removed peers.
for (removedPeer in param.removedPeers) {
peerContainerList.removeIf {
it.peerControl.peer.isSameMember(removedPeer)
}
}
}

Leave a group call

To leave a group call, call leaveConference().

fun leaveConferenceExample(): Boolean
{
var conference = PlanetKit.getConference() ?: return false

conference.leaveConference()

return true
}