Skip to main content
Version: 0.1.x

Render Participant - Android

In this guide, we will take a look at how to render the participant's video on the screen.

info
  • Here the participant's video is displayed using VideoView, but you may also use SurfaceViewRender for the same.
  • For VideoView, SDK version should be 0.1.13 or higher.
  • To know more about VideoView, please visit here

Steps to render panticipant

Step 1: Create a new layout for the participant view named item_participant.xml in the res/layout folder.

item_participant.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="200dp"
android:background="#616161"
tools:layout_height="200dp">

<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:background="#99000000"
android:contentDescription="webcam_turned_off"
android:gravity="center"
android:padding="4dp"
android:src="@drawable/ic_outline_videocam_off_24"
app:tint="@color/white" />

<live.videosdk.rtc.android.VideoView
android:id="@+id/participantView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone" />

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:background="#99000000"
android:orientation="horizontal">

<TextView
android:id="@+id/tvName"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:padding="4dp"
android:textColor="@color/white" />

</LinearLayout>
</FrameLayout>

Step 2: Now, Create a recycler view adapter named ParticipantAdapter which will show the participant list. Create PeerViewHolder in the adapter which will extend RecyclerView.ViewHolder

ParticipantAdapter.kt
class ParticipantAdapter(meeting: Meeting) : RecyclerView.Adapter<ParticipantAdapter.PeerViewHolder>() {

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PeerViewHolder {
return PeerViewHolder(
LayoutInflater.from(parent.context)
.inflate(R.layout.item_participant, parent, false)
)
}

override fun onBindViewHolder(holder: PeerViewHolder, position: Int) {
}

override fun getItemCount(): Int {
return 0
}

class PeerViewHolder(view: View) : RecyclerView.ViewHolder(view) {
// 'VideoView' to show Video Stream
var participantView: VideoView = view.findViewById(R.id.participantView)
var tvName: TextView = view.findViewById(R.id.tvName)
}
}

Step 3: Next, we will render a list of Participant for the meeting. We will initialize this list in the constructor of the ParticipantAdapter

ParticipantAdapter.kt
class ParticipantAdapter(meeting: Meeting) :
RecyclerView.Adapter<ParticipantAdapter.PeerViewHolder>() {

// creating a empty list which will store all participants
private val participants: MutableList<Participant> = ArrayList()

init {
// adding the local participant(You) to the list
participants.add(meeting.localParticipant)

// adding Meeting Event listener to get the participant join/leave event in the meeting.
meeting.addEventListener(object : MeetingEventListener() {
override fun onParticipantJoined(participant: Participant) {
// add participant to the list
participants.add(participant)
notifyItemInserted(participants.size - 1)
}

override fun onParticipantLeft(participant: Participant) {
var pos = -1
for (i in participants.indices) {
if (participants[i].id == participant.id) {
pos = i
break
}
}
// remove participant from the list
participants.remove(participant)
if (pos >= 0) {
notifyItemRemoved(pos)
}
}
})
}

// replace getItemCount() method with following.
// this method returns the size of total number of participants
override fun getItemCount(): Int {
return participants.size
}
//...
}

Step 4: Now, We have listed our participants. Let's set up the view holder to display a participant video.

PartipantAdapter.kt
class ParticipantAdapter(meeting: Meeting) :
RecyclerView.Adapter<ParticipantAdapter.PeerViewHolder>() {

// replace onBindViewHolder() method with following.
override fun onBindViewHolder(holder: PeerViewHolder, position: Int) {
val participant = participants[position]

holder.tvName.text = participant.displayName

// adding the initial video stream for the participant into the 'VideoView'
for ((_, stream) in participant.streams) {
if (stream.kind.equals("video", ignoreCase = true)) {
holder.participantView.visibility = View.VISIBLE
val videoTrack = stream.track as VideoTrack
holder.participantView.addTrack(videoTrack)
break
}
}

// add Listener to the participant which will update start or stop the video stream of that participant
participant.addEventListener(object : ParticipantEventListener() {
override fun onStreamEnabled(stream: Stream) {
if (stream.kind.equals("video", ignoreCase = true)) {
holder.participantView.visibility = View.VISIBLE
val videoTrack = stream.track as VideoTrack
holder.participantView.addTrack(videoTrack)
}
}

override fun onStreamDisabled(stream: Stream) {
if (stream.kind.equals("video", ignoreCase = true)) {
holder.participantView.removeTrack()
holder.participantView.visibility = View.GONE
}
}
})
}
}

Step 5: Final step is to add this adapter to the MeetingActivity

MeetingActivity.kt
override fun onCreate(savedInstanceState: Bundle?) {
//Meeting Setup...
//...
val rvParticipants = findViewById<RecyclerView>(R.id.rvParticipants)
rvParticipants.layoutManager = GridLayoutManager(this, 2)
rvParticipants.adapter = ParticipantAdapter(meeting!!)
}

Mirror Local Video View

If you wish to show the mirror view of the local participant, you can set setMirror property to true of VideoView class.

PartipantAdapter.kt
class ParticipantAdapter(meeting: Meeting) :
RecyclerView.Adapter<ParticipantAdapter.PeerViewHolder>() {

override fun onBindViewHolder(holder: PeerViewHolder, position: Int) {
//...
holder.tvName.text = participant.displayName
holder.participantView.setMirror(true)
//...
}
}
Sample of mirror view video

mirror view

API Reference

The API references for all the methods and events utilised in this guide are provided below.

Got a Question? Ask us on discord