Calls Android v1
Calls Android
Calls
Android
Home
/
Calls
/
Android

Group call

This page explains the key functions of group call consisting of how to create a room and how a user can participate in a group call by entering and exiting a room from your app.

Note: Tutorial is also available on how to build a Kotlin video group chat app.


Create a room

You can choose to create a room that supports up to 6 participants with video or a room that supports up to 100 participants with audio. When a user creates a room in your app, the room’s status becomes OPEN and a ROOM_ID is generated.

You can create a room through the Calls API as shown below by using the createRoom() method.

val params = RoomParams(RoomType.SMALL_ROOM_FOR_VIDEO)
SendBirdCall.createRoom(params, object : RoomHandler {
    override fun onResult(room: Room?, e: SendBirdException?) {
         if (room == null || e != null) {
              // Handle error.
              return
         }

         // `room` is created with a unique identifier `room.roomId`.
    }
})

List of properties

Property nameDescription

type

Type: RoomType
Specifies the type of the room. Valid values are limited to the following:
- SMALL_ROOM_FOR_VIDEO: type of a room that supports audio and video, can have up to 6 participants.
- LARGE_ROOM_FOR_AUDIO_ONLY: type of a room that only supports audio and can have up to 100 participants.


Enter a room

A user can search a room with a specific room ID to participate in a group call at any time. When a user enters a room, a participant is created with a unique participant ID to represent the user in the room.

To enter a room, you must first acquire the room instance from Sendbird server with the room ID. To fetch the most up-to-date room instance from Sendbird server, use the SendBirdCall.fetchRoomById() method. Also, you can use the SendBirdCall.getCachedRoomById() method that returns the most recently cached room instance from Sendbird Calls SDK.

SendBirdCall.fetchRoomById(ROOM_ID, object : RoomHandler {
    override fun onResult(room: Room?, e: SendBirdException?) {
         if (room == null || e != null) {
              // Handle error.
              return
         }

         // `room` with the identifier `ROOM_ID` is fetched from Sendbird Server.
    }
})

val room = SendBirdCall.getCachedRoomById(ROOM_ID)
// Returns the most recently cached room with the identifier `ROOM_ID` from the SDK.
// If there is no such room with the given room ID, `null` is returned.

Note: A user can enter the room using multiple devices or browser tabs. Entering from each device or browser tab will create a new participant.

Once the room is retrieved, call the enter() method to enter the room.

room.enter(params, object : CompletionHandler {
    override fun onResult(e: SendBirdException?) {
        if (e != null) {
            // Handle error.
        }

        // User has successfully entered `room`.
    }
})

Note: Share the room ID with other users for them to enter the room from the client app.


Exit a room

To leave a room, call Room.exit(). On the room handlers of the remaining participants, the RoomListener.onRemoteParticipantExited() method will be called.

room.exit()

Manage custom items

With custom items for group calls, you can store additional information as key-value pairs to a room in the Room object. Custom key-value items are saved as a Map<String, String> and can be updated or deleted as long as the room status is OPEN. Information related to customer service, refund, or inquiry can be added as custom items for better user experience.

Add

When a room is created, users can add custom items in RoomParams as a Map<String, String>. By default, the customItems is an empty Map object.

val customItems: Map<String, String> = mapOf("key" to "value")
val roomParams: RoomParams = RoomParams(ROOM_TYPE)
    .setCustomItems(customItems)
SendBirdCall.createRoom(roomParams, object : RoomHandler {
    override fun onResult(room: Room?, e: SendBirdException?) {

    }
})

Update and delete

Custom items can be updated or deleted as long as the room status is OPEN. If a new custom item has the same key as the existing custom item, the new item will update the value of the existing item. A new item with a new key will be added to the list of custom items. You can update existing custom items by calling the room.updateCustomItems(Map<String, String>, CustomItemsHandler).

You can delete custom items by calling the room.deleteCustomItems(Map<String, String>, CustomItemsHandler) with the list of keys that you want to delete from the existing custom items.

val customItems: Map<String, String> = mapOf("key" to "value")
room.updateCustomItems(items, object : CustomItemsHandler {
    override fun onResult(
        customItems: Map<String, String>?,
        affectedKeys: List<String>?,
        e: SendBirdException?
    ) {

    }
})

val keysToDelete: Set<String> = setOf("key1", "key2")
room.deleteCustomItems(keysToDelete, object : CustomItemsHandler {
    override fun onResult(
        customItems: Map<String, String>?,
        affectedKeys: List<String>?,
        e: SendBirdException?
    ) {

    }
})

Receive events

A participant in a room can receive events from Sendbird server when other participants update or delete custom items in the room. Implement the RoomListener.onCustomItemsUpdated(List<String>) and the RoomListener.onCustomItemsDeleted(List<String>) from the RoomListener to receive events from other participants. Each event contains the list of keys of the changed custom items, such as updatedKeys or deletedKeys.

Custom items can be modified and the events are delivered to the RoomListener only when the room's status is OPEN and there are participants in the room. To check the custom items that had been changed for ended or ongoing calls in a room, you can use the Calls API or the room.fetchCustomItems(CustomItemsHandler?).

interface RoomListener {
    /**
    * An event for when the custom items are updated.
    *
    * @param updatedKeys Update keys.
    * @since 1.8.0
    */
    fun onCustomItemsUpdated(updatedKeys: List<String>)

    /**
    * An event for when the custom items are deleted.
    *
    * @param deletedKeys Delete keys.
    * @since 1.8.0
    */
    fun onCustomItemsDeleted(deletedKeys: List<String>
}

Retrieve a list of rooms

You can retrieve a list of rooms by using the RoomListQuery and the following table shows all supported filters for the RoomListQuery to search for specific rooms you want to retrieve.

List of filters

NameFilters...

setRoomIds

Query results to include rooms that match the specified room IDs.

setType

Query results to include rooms with the specified room type.

setState

Query results to include room with the specified room state.

setRangeForCreatedAt

Query results to include rooms that were created between the specified range of time.

setRangeForCurrentParticipantCount

Query results to include rooms with the specified range of numbers for current participants.

setCreatedByUserIds

Query results to include rooms that were created by specified user IDs.

You can specify the above filters as shown below:

val aWeekAgo = Calendar.getInstance().apply {
    add(Calendar.DAY_OF_YEAR, -7)
}

val params = RoomListQuery.Params()
    .setType(RoomType.LARGE_ROOM_FOR_AUDIO_ONLY)
    .setLimit(50)
    .setState(RoomState.OPEN)
    .setRangeForCurrentParticipantCount(Range.greaterThanOrEqualTo(1))
    .setRangeForCreatedAt(
         Range.greaterThanOrEqualTo(aWeekAgo.timeInMillis)
    )

To retrieve a list of rooms, call the RoomListQuery.next(RoomListQueryResultHandler) method.

val query = SendBirdCall.createRoomListQuery(params)
query.next(object : RoomListQueryResultHandler {
    override fun onResult(rooms: List<Room>, e: SendBirdException?) {
         if (e != null) {
              // Error has occurred.
              return
         }
         ...
    }
})

When a list of rooms is retrieved, you can show the list to a user and allow the user to select a room they want to enter.

rooms[index].enter(EnterParams(), object : CompletionHandler {
    override fun onResult(e: SendBirdException?) {
          // User has entered the room
    }
})

Note: The room data returned from the query is not updated unless the user has entered the room. To update the details about a room, call the SendBirdCall.fetchRoomById() method.


Interact within a room

Participant’s actions, such as turning on or off their microphone or camera, in a room are handled by the participant objects.

To control the media of a local user, you can use the following methods from the Room.localParticipant object:

// Mutes the local participant's microphone.
room.localParticipant?.muteMicrophone()

// Unmutes the local participant's microphone.
room.localParticipant?.unmuteMicrophone()

// Stops the local participant's video.
room.localParticipant?.stopVideo()

// Starts the local participant's video.
room.localParticipant?.startVideo()

// Switches the local participant's front and back cameras.
room.localParticipant?.switchCamera(completionHandler)

Display video view

When there is a participant in the room, a media stream is established between a participant and Sendbird server to support group calls.You can configure the user interface for participants in a room by using the properties in Participant.

Receive media stream

The following is the process of how participants can send and receive media streams in a room:

Step 1: To send a media stream, a participant who would like to send its media stream has to be connected to Sendbird server.

Step 2: To receive a media stream, a participant who would like to receive a media stream from another participant has to be connected to the media server. Once connected, onRemoteParticipantStreamStarted() will be invoked which notifies that the receiving media stream has started.

Step 3: Add a view to show the received media stream.

To receive a video stream from a local participant, configure videoView property as shown below:

room.enter(params, object : CompletionHandler {
    override fun onResult(e: SendBirdException?) {
        if (e != null) {
            // Handle error.
        }

        // User has successfully entered `room`.
        val localParticipantVideoView: SendBirdVideoView = findViewById(R.id.local_participant_video_view)
        room.localParticipant?.videoView = localParticipantVideoView

    }
})

To receive a video stream from a remote participant, configure the videoView property as shown below:

room.addListener(UNIQUE_ID, object : RoomListener {
    ...
    override fun onRemoteParticipantEntered(participant: RemoteParticipant) {
        val remoteParticipantVideoView: SendBirdVideoView = findViewById(R.id.remote_participant_video_view)
        participant.videoView = remoteParticipant
    }
    ...
})

Manage video layout

You can show participants in gallery view as they enter or exit the room by using RecyclerView and GridLayoutManager which dynamically change views. You can set the number of items to be the count of room.participants and the custom ViewHolder to represent each participant.

When the below methods in RoomListener are called, information for room.participants gets updated and the number of items are changed accordingly. To have the custom ViewHolder added or removed, you need to call adapter.notifyDataSetChanged() for the methods.

List of methods

MethodDescription

onRemoteParticipantEntered(participant: RemoteParticipant)

Invoked when a remote participant has entered a room.

onRemoteParticipantExited(participant: RemoteParticipant)

Invoked when a remote participant has exited a room.

onRemoteParticipantStreamStarted(participant: RemoteParticipant)

Invoked when a remote participant has started media streaming.

onRemoteAudioSettingsChanged(participant: RemoteParticipant)

Invoked when a remote participant's audio settings have changed.

onRemoteVideoSettingsChanged(participant: RemoteParticipant)

Invoked when a remote participant's video settings have changed.

Show default image for user

If a participant is not connected to the call or has turned off their video, you can set a default image to show on the screen for that participant. Otherwise, it will be shown as black to other participants. To check whether a participant has turned on their video or is connected to the room for a video call, refer to the isVideoEnabled and the state properties of a Participant object.

It is recommended to show an image such as the user’s profile image as the default image when the onRemoteParticipantEntered() method is invoked.

When the onRemoteParticipantStreamStarted() method is invoked, create a new SendBirdVideoView and set it to the participant by using participant.videoView and remove the default image.


Handle events in a room

A user can receive events of a room that they are currently participating. Users will be notified when other participants enter or leave the room, change their media settings or when the room is deleted.

Add event listener

Add event listener for the user to receive events that occur in a room that the user joins as a participant.

room.addListener(UNIQUE_ID, MyRoomListener())

class MyRoomListener : RoomListener {
}

Receive events on enter and exit

When a participant joins or leaves the room, other participants in the room will receive the following events.

class MyRoomListener : RoomListener {
    ...
    // Called when a remote participant has entered a room.
    override fun onRemoteParticipantEntered(participant: RemoteParticipant) {}

    // Called when a remote participant has exited a room.
    override fun onRemoteParticipantExited(participant: RemoteParticipant) {}
    ...
}

Receive events on media settings

A local participant can change the media settings such as muting their microphone or turning off their camera by using muteMicrophone() or stopVideo(). Other participants will receive events that notify them of the corresponding media setting changes.

class MyRoomListener : RoomListener {
    // Called when a remote participant's video settings have changed.
    override fun onRemoteVideoSettingsChanged(participant: RemoteParticipant) {}

    // Called when a remote participant's audio settings have changed.
    override fun onRemoteAudioSettingsChanged(participant: RemoteParticipant) {}
}

Receive events on deleted room

To delete a room through Calls Platform API, see Delete a room in the Calls API documentation. When a room is deleted, participants in the room will receive the following event.

class MyRoomListener : RoomListener {
   // Called when the room has been deleted.
   override fun onDeleted() {}
}

Remove event listener

To stop receiving events about a room, remove the registered listeners as shown below:

// Removes a listener that have the matching identifier.
room.removeListener(UNIQUE_ID)

// Removes all listeners to stop receiving events about a room.
room.removeAllListeners()

Reconnect to media stream

When a participant loses media stream in a room due to connection issues, Sendbird Calls SDK automatically tries to reconnect the participant’s media streaming in the room. If the Calls SDK fails to reconnect for about 40 seconds, an error will be returned.

class MyRoomListener : RoomListener {
// Called when an error has occurred.
    override fun onError(e: SendBirdException, participant: Participant?) {
        if (e.code == SendBirdError.ERR_LOCAL_PARTICIPANT_LOST_CONNECTION) {
                // handle reconnection failure here.
                // Clear resources for group calls.
          }
     }
}

Note: See the Error codes page for more information.