title: How to handle multiple participant and their video/audio feed in twilio video conference in android?
body: <pre><code>I am using twilio video, i want to make a video conference app in android.
  
  Peer to peer connection works fine, but 
  
  1) how can i render/handle audio-video feed of more then one participant in a video room?
  
  2) I am rendering the view of first participant as shown in video quickstart sdk and for more then one i tried inflating views by using participant array size. i have tried inflating views when 2nd participant(in a room that has the room creator and a participant) joins then all three mobile devices stuck and become totally unresponsive and i have to kill the app.
  
  3) So how can i render lets say 4 participants(besides the room creator-local participant) and render their feeds accordingly in the order they
  join the room and handle their removal or disconnection from the room?
  
  The video quick start sample has a comment stating that currently only one participant is handled in the UI, i couldn't find any demo that shows how to handle multiple participants. Is there a way to do it?
  
  Thanks.
  
  here is my code
  </code></pre>
  
  <p>Videoactivity</p>
  
  <p>Room listener</p>
  
  <pre><code>private Room.Listener roomListener() {
          return new Room.Listener() {
              @Override
              public void onConnected(Room room) {
                  localParticipant = room.getLocalParticipant();
                  videoStatusTextView.setText("Connected to " + room.getName());
                  Snackbar.make(connectActionFab,
                          "Local Participant name: " + room.getLocalParticipant().getIdentity(),
                          Snackbar.LENGTH_LONG)
                          .setAction("Action", null).show();
                  setTitle(room.getName());
                  for (RemoteParticipant remoteParticipant : room.getRemoteParticipants()) {
                      addRemoteParticipant(remoteParticipant);
                      break;
                  }
              }
  
              @Override
              public void onConnectFailure(Room room, TwilioException e) {
                  videoStatusTextView.setText("Failed to connect");
                  configureAudio(false);
                  intializeUI();
              }
  
              @Override
              public void onDisconnected(Room room, TwilioException e) {
                  localParticipant = null;
                  videoStatusTextView.setText("Disconnected from " + room.getName());
                  VideoActivity.this.room = null;
                  // Only reinitialize the UI if disconnect was not called from onDestroy()
                  if (!disconnectedFromOnDestroy) {
                      configureAudio(false);
                      intializeUI();
                      moveLocalVideoToPrimaryView();
                  }
              }
  
              @Override
              public void onParticipantConnected(Room room, RemoteParticipant remoteParticipant) {
                  if (thumbnailVideoView.getVisibility() == View.VISIBLE) {
                      addRemoteParticipant(remoteParticipant);
                      Snackbar.make(connectActionFab,
                              "Participant array size " + room.getRemoteParticipants().size()
                                      + "Participant " + remoteParticipant.getIdentity() + "connected to room",
                              Snackbar.LENGTH_LONG)
                              .setAction("Action", null).show();
                  } else {
                      addSecondRemoteParticipant(remoteParticipant);
                      Snackbar.make(connectActionFab,
                              "Participant array size " + room.getRemoteParticipants().size()
                                      + "Second Remote Participant " + remoteParticipant.getIdentity() + "connected to room",
                              Snackbar.LENGTH_LONG)
                              .setAction("Action", null).show();
                      Log.e(TAG, "onSecondParticipantConnected: " + room.getRemoteParticipants().size());
                  }
  
              }
  
              @Override
              public void onParticipantDisconnected(Room room, RemoteParticipant remoteParticipant) {
  
                  Snackbar.make(connectActionFab,
                          "Participant array size " + room.getRemoteParticipants().size()
                                  + "Participant " + remoteParticipant.getIdentity() + "disconnected to room",
                          Snackbar.LENGTH_LONG)
                          .setAction("Action", null).show();
                  removeRemoteParticipant(remoteParticipant);
  
  
              }
  
              @Override
              public void onRecordingStarted(Room room) {
  
                  Log.d(TAG, "onRecordingStarted");
              }
  
              @Override
              public void onRecordingStopped(Room room) {
  
                  Log.d(TAG, "onRecordingStopped");
              }
          };
      }
  </code></pre>
  
  <p>Participant Listner</p>
  
  <pre><code>private RemoteParticipant.Listener remoteParticipantListener() {
          return new RemoteParticipant.Listener() {
              @Override
              public void onAudioTrackPublished(RemoteParticipant remoteParticipant,
                                                RemoteAudioTrackPublication remoteAudioTrackPublication) {
  
                  videoStatusTextView.setText("onAudioTrackPublished");
              }
  
              @Override
              public void onAudioTrackUnpublished(RemoteParticipant remoteParticipant,
                                                  RemoteAudioTrackPublication remoteAudioTrackPublication) {
                 videoStatusTextView.setText("onAudioTrackUnpublished");
              }
  
              @Override
              public void onDataTrackPublished(RemoteParticipant remoteParticipant,
                                               RemoteDataTrackPublication remoteDataTrackPublication) {
                               videoStatusTextView.setText("onDataTrackPublished");
              }
  
              @Override
              public void onDataTrackUnpublished(RemoteParticipant remoteParticipant,
                                                 RemoteDataTrackPublication remoteDataTrackPublication) {
                      videoStatusTextView.setText("onDataTrackUnpublished");
              }
  
              @Override
              public void onVideoTrackPublished(RemoteParticipant remoteParticipant,
                                                RemoteVideoTrackPublication remoteVideoTrackPublication) {
                                    videoStatusTextView.setText("onVideoTrackPublished");
              }
  
              @Override
              public void onVideoTrackUnpublished(RemoteParticipant remoteParticipant,
                                                  RemoteVideoTrackPublication remoteVideoTrackPublication) {
                 videoStatusTextView.setText("onVideoTrackUnpublished");
              }
  
              @Override
              public void onAudioTrackSubscribed(RemoteParticipant remoteParticipant,
                                                 RemoteAudioTrackPublication remoteAudioTrackPublication,
                                                 RemoteAudioTrack remoteAudioTrack) {
  
                  videoStatusTextView.setText("onAudioTrackSubscribed");
              }
  
              @Override
              public void onAudioTrackUnsubscribed(RemoteParticipant remoteParticipant,
                                                   RemoteAudioTrackPublication remoteAudioTrackPublication,
                                                   RemoteAudioTrack remoteAudioTrack) {
  
                  videoStatusTextView.setText("onAudioTrackUnsubscribed");
              }
  
              @Override
              public void onDataTrackSubscribed(RemoteParticipant remoteParticipant,
                                                RemoteDataTrackPublication remoteDataTrackPublication,
                                                RemoteDataTrack remoteDataTrack) {
  
                  videoStatusTextView.setText("onDataTrackSubscribed");
              }
  
              @Override
              public void onDataTrackUnsubscribed(RemoteParticipant remoteParticipant,
                                                  RemoteDataTrackPublication remoteDataTrackPublication,
                                                  RemoteDataTrack remoteDataTrack) {
                 videoStatusTextView.setText("onDataTrackUnsubscribed");
              }
  
              @Override
              public void onVideoTrackSubscribed(RemoteParticipant remoteParticipant,
                                                 RemoteVideoTrackPublication remoteVideoTrackPublication,
                                                 RemoteVideoTrack remoteVideoTrack) {
  
                  videoStatusTextView.setText("onVideoTrackSubscribed");
  
                  if (thumbnailVideoView.getVisibility() == View.GONE) {
                      if(!ifFirstParticipantHasVideoFeed){
                          addRemoteParticipantVideo(remoteVideoTrack);
                          ifFirstParticipantHasVideoFeed=true;
                          Snackbar.make(connectActionFab,
                                  "Participant array size " + room.getRemoteParticipants().size()
                                          + "Participant " + remoteParticipant.getIdentity() + "connected to room",
                                  Snackbar.LENGTH_LONG)
                                  .setAction("Action", null).show();
                      }
                      else {
                          if(ifFirstParticipantHasVideoFeed){
                              addSecondRemoteParticipantVideo(remoteVideoTrackPublication.getRemoteVideoTrack());
                          }
                      }
  
                  }
  
              }
  
              @Override
              public void onVideoTrackUnsubscribed(RemoteParticipant remoteParticipant,
                                                   RemoteVideoTrackPublication remoteVideoTrackPublication,
                                                   RemoteVideoTrack remoteVideoTrack) {
                 videoStatusTextView.setText("onVideoTrackUnsubscribed");
                  removeParticipantVideo(remoteVideoTrack);
              }
  
              @Override
              public void onAudioTrackEnabled(RemoteParticipant remoteParticipant,
                                              RemoteAudioTrackPublication remoteAudioTrackPublication) {
  
              }
  
              @Override
              public void onAudioTrackDisabled(RemoteParticipant remoteParticipant,
                                               RemoteAudioTrackPublication remoteAudioTrackPublication) {
  
              }
  
              @Override
              public void onVideoTrackEnabled(RemoteParticipant remoteParticipant,
                                              RemoteVideoTrackPublication remoteVideoTrackPublication) {
  
              }
  
              @Override
              public void onVideoTrackDisabled(RemoteParticipant remoteParticipant,
                                               RemoteVideoTrackPublication remoteVideoTrackPublication) {
  
              }
          };
      }
  </code></pre>
  
  <p>To add second remote participant i have used below methods</p>
  
  <pre><code>private void addSecondRemoteParticipant(RemoteParticipant remoteParticipant) {
          secondRemoteParticipantIdentity = remoteParticipant.getIdentity();
          videoStatusTextView.setText("Second RemoteParticipant " + remoteParticipantIdentity + " joined");
          Log.e(TAG, "addSecondRemoteParticipant: " + remoteParticipant.getIdentity());
  
  
      if (remoteParticipant.getRemoteVideoTracks().size() &gt; 0) {
          RemoteVideoTrackPublication remoteVideoTrackPublication =
                  remoteParticipant.getRemoteVideoTracks().get(0);
  
  
          if (remoteVideoTrackPublication.isTrackSubscribed()) {
              addSecondRemoteParticipantVideo(remoteVideoTrackPublication.getRemoteVideoTrack());
          }
      }
  
      remoteParticipant.setListener(remoteParticipantListener());
  }
  
  
  private void addSecondRemoteParticipantVideo(RemoteVideoTrack remoteVideoTrack) {
      VideoView video = new VideoView(VideoActivity.this);
      video.setLayoutParams(new FrameLayout.LayoutParams(300, 300));
      video.setVisibility(View.VISIBLE);
      video.setBackgroundColor(getResources().getColor(android.R.color.black));
      linearVideoParent.addView(video);
  
  
      remoteVideoTrack.addRenderer(video);
  
  i have checked in debugging till here, but still i some how video is not getting rendered in the view i created.
  
      Snackbar.make(connectActionFab, "added second participant's video",
              Snackbar.LENGTH_LONG).show();
  
  }
  </code></pre>
  
  <p>I have tried inflating a view run time when second remote participant connects but i can't get the video rendered in it.</p>
  
  <p>It seems that there is a time gap between 
  1) when participant is added/joins the room (which we can listen to from
  participant listener)</p>
  
  <p>and</p>
  
  <p>2) When the participant's video track is subscribed (onVideotrackSubscribed)</p>