How to Make a 1-on-1 Video Chat Android Java App with Video SDK

Utpalsinh Parmar
Video SDK
Published in
10 min readJul 6, 2023

Introduction

Remote communication has become the most important part of communication after the pandemic. It’s highly likely that it will play a significant role in future too. Today’s mobile applications often include voice or video calling functionality. But it’s extremely complex and takes a lot of time to build. This is where Video SDK comes into the picture.

Video SDK is a platform that allows developers to create rich in-app experiences such as embed real-time video, voice, real-time recording, live streaming and real-time messaging.

Video SDK is available for JavaScript, ReactJS, React-Native, IOS, Android and Flutter to be integrated seamlessly. Video SDK also provides a Pre-built SDK that enables opportunity to integrate real time communication with your application with just 10 minutes!

Let’s create one-to-one video calling app using Video SDK.
But first, we need to create Video SDK account and generate token.

Prerequisites

First of all, Your development environment should meet the following requirements:

Setup the project

Step 1: Create new Project

Let’s start by creating new project. In Android Studio, create a new project with an Empty Activity.
Then, provide a name. We will name it as OneToOneDemo.

Step 2: Integrate Video SDK

  • Add the repository to settings.gradle file.
dependencyResolutionManagement{
repositories {
// ...
google()
mavenCentral()
maven { url 'https://jitpack.io' }
maven { url "https://maven.aliyun.com/repository/jcenter" }
}
}
  • Add the following dependencies in build.gradle file.
dependencies {
implementation 'live.videosdk:rtc-android-sdk:0.1.13'
// library to perform Network call to generate a meeting id
implementation 'com.amitshekhar.android:android-networking:1.0.2'
// other app dependencies
}

If your project has set android.useAndroidX = true, then set android.enableJetifier = true in the gradle.properties file to migrate your project to AndroidX and avoid duplicate class conflict.

Step 3: Add permissions into your project

In /app/Manifests/AndroidManifest.xml, add the following permissions after </application>.

<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.CAMERA" />

Getting Started with the Code!

Structure of project
We’ll create two screens. First screen will be Joining screen that allows user to create/join the meeting, and another one is Meeting screen that will show participants like Whatsapp view.

Our project structure would look like this.

app
├── java
│ ├── packagename
│ ├── JoinActivity
│ ├── MeetingActivity
├── res
│ ├── layout
│ │ ├── activity_join.xml
│ │ ├── activity_meeting.xml

You have to set JoinActivity as Launcher activity.

Creating Joining Screen

Create a new Activity named JoinActivity

Creating UI for Joining Screen

The Joining screen will include :

  1. Create Button — Creates a new meeting.
  2. TextField for Meeting Id — Contains the meeting Id you want to join.
  3. Join Button — Joins the meeting with the meetingId provided.

In /app/res/layout/activity_join.xml file, replace the content with the following.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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="match_parent"
android:gravity="center"
android:orientation="vertical"
tools:context=".JoinActivity">
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/material_toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:contentInsetStart="0dp"
android:background="?attr/colorPrimary"
app:titleTextColor="@color/white" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical">

<Button
android:id="@+id/btnCreateMeeting"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:text="Create Meeting" />
<TextView
style="@style/TextAppearance.AppCompat.Headline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="OR" />
<com.google.android.material.textfield.TextInputLayout style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginVertical="16dp"
android:hint="Enter Meeting ID">
<EditText
android:id="@+id/etMeetingId"
android:layout_width="250dp"
android:layout_height="wrap_content" />
</com.google.android.material.textfield.TextInputLayout>
<Button
android:id="@+id/btnJoinMeeting"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Join Meeting" />
</LinearLayout>
</LinearLayout>

Integration of Create Meeting API

  • You need to create a field sampleToken in JoinActivity that holds the generated token from the Video SDK dashboard. This token will be used in Video SDK config as well as generating meetingId.
public class JoinActivity extends AppCompatActivity {
//Replace with the token you generated from the VideoSDK Dashboard
private String sampleToken = "";
@Override
protected void onCreate(Bundle savedInstanceState) {
//...
}
}
  • On Join Button onClick event, it will naviagte to MeetingActivity with token and meetingId.
public class JoinActivity extends AppCompatActivity {
//Replace with the token you generated from the VideoSDK Dashboard
private String sampleToken ="";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_join);
final Button btnCreate = findViewById(R.id.btnCreateMeeting);
final Button btnJoin = findViewById(R.id.btnJoinMeeting);
final EditText etMeetingId = findViewById(R.id.etMeetingId);
//set title
Toolbar toolbar = findViewById(R.id.material_toolbar);
toolbar.setTitle("OneToOneDemo");
setSupportActionBar(toolbar);
btnCreate.setOnClickListener(v -> {
// we will explore this method in the next step
createMeeting(sampleToken);
});
btnJoin.setOnClickListener(v -> {
Intent intent = new Intent(JoinActivity.this, MeetingActivity.class);
intent.putExtra("token", sampleToken);
intent.putExtra("meetingId", etMeetingId.getText().toString());
startActivity(intent);
});
}
private void createMeeting(String token) {
}
}
  • For Create Button, under createMeeting method we will generate meetingId by calling API and navigate to MeetingActivity with token and generated meetingId.
public class JoinActivity extends AppCompatActivity {
//...onCreate

private void createMeeting(String token) {
// we will make an API call to VideoSDK Server to get a roomId
AndroidNetworking.post("https://api.videosdk.live/v2/rooms")
.addHeaders("Authorization", token) //we will pass the token in the Headers
.build()
.getAsJSONObject(new JSONObjectRequestListener() {
@Override
public void onResponse(JSONObject response) {
try {
// response will contain `roomId`
final String meetingId = response.getString("roomId");
// starting the MeetingActivity with received roomId and our sampleToken
Intent intent = new Intent(JoinActivity.this, MeetingActivity.class);
intent.putExtra("token", sampleToken);
intent.putExtra("meetingId", meetingId);
startActivity(intent);
} catch (JSONException e) {
e.printStackTrace();
}
}
@Override
public void onError(ANError anError) {
anError.printStackTrace();
Toast.makeText(JoinActivity.this, anError.getMessage(), Toast.LENGTH_SHORT).show();
}
});
}
}
  • Our App is completely based on audio and video commutation, that’s why we need to ask for runtime permissions RECORD_AUDIO and CAMERA. So, we will implement permission logic on JoinActivity.
public class JoinActivity extends AppCompatActivity {
private static final int PERMISSION_REQ_ID = 22;

private static final String[] REQUESTED_PERMISSIONS = {
Manifest.permission.RECORD_AUDIO,
Manifest.permission.CAMERA
};
private boolean checkSelfPermission(String permission, int requestCode) {
if (ContextCompat.checkSelfPermission(this, permission) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, REQUESTED_PERMISSIONS, requestCode);
return false;
}
return true;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
//... button listeneres
checkSelfPermission(REQUESTED_PERMISSIONS[0], PERMISSION_REQ_ID);
checkSelfPermission(REQUESTED_PERMISSIONS[1], PERMISSION_REQ_ID);
}
}

You’ll get Unresolved reference: MeetingActivity error, but don't worry. It will be solved automatically once you create MeetingActivity.

  • We’re done the Joining screen now, and it is time to create the participant’s view in the Meeting screen.

Step 4: Creating Meeting Screen

Create a new Activity named MeetingActivity.

Creating the UI for Meeting Screen

In /app/res/layout/activity_meeting.xml file, replace the content with the following.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:id="@+id/mainLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:animateLayoutChanges="true"
android:gravity="center"
android:orientation="vertical"
tools:context=".MeetingActivity">

<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/material_toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="@color/black"
app:contentInsetStart="0dp"
app:titleTextColor="@color/white">
<LinearLayout
android:id="@+id/meetingLayout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="14dp"
android:layout_marginTop="10dp"
android:orientation="horizontal">
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView
android:id="@+id/txtMeetingId"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:fontFamily="sans-serif-medium"
android:textColor="@color/white"
android:textFontWeight="600"
android:textSize="16sp" />
<ImageButton
android:id="@+id/btnCopyContent"
android:layout_width="22dp"
android:layout_height="22sp"
android:layout_marginLeft="7dp"
android:layout_toRightOf="@+id/txtMeetingId"
android:backgroundTint="@color/black"
android:src="@drawable/ic_outline_content_copy_24" />
</RelativeLayout>
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end"
android:layout_marginEnd="10dp">
<ImageButton
android:id="@+id/btnSwitchCameraMode"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:background="@color/black"
android:contentDescription="Switch Camera mode"
android:src="@drawable/ic_baseline_flip_camera_android_24" />
</LinearLayout>
</com.google.android.material.appbar.MaterialToolbar>
<FrameLayout
android:id="@+id/participants_frameLayout"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="@color/black">
<androidx.cardview.widget.CardView
android:id="@+id/ParticipantCard"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginLeft="12dp"
android:layout_marginTop="3dp"
android:layout_marginRight="12dp"
android:layout_marginBottom="3dp"
android:backgroundTint="#2B3034"
android:visibility="gone"
app:cardCornerRadius="8dp"
app:strokeColor="#2B3034">
<ImageView
android:layout_width="150dp"
android:layout_height="150dp"
android:layout_gravity="center"
android:src="@drawable/ic_baseline_person_24" />
<live.videosdk.rtc.android.VideoView
android:id="@+id/participantView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone" />
</androidx.cardview.widget.CardView>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
</FrameLayout>
<androidx.cardview.widget.CardView
android:id="@+id/LocalCard"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginLeft="12dp"
android:layout_marginTop="3dp"
android:layout_marginRight="12dp"
android:layout_marginBottom="3dp"
android:backgroundTint="#1A1C22"
app:cardCornerRadius="8dp"
app:strokeColor="#1A1C22">
<ImageView
android:id="@+id/localParticipant_img"
android:layout_width="150dp"
android:layout_height="150dp"
android:layout_gravity="center"
android:src="@drawable/ic_baseline_person_24" />
<live.videosdk.rtc.android.VideoView
android:id="@+id/localView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone" />
</androidx.cardview.widget.CardView>
</FrameLayout>
<!-- add bottombar here-->
</LinearLayout>
<com.google.android.material.bottomappbar.BottomAppBar
android:id="@+id/bottomAppbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:animateLayoutChanges="true"
android:backgroundTint="@color/black"
android:gravity="center_horizontal"
android:paddingVertical="5dp"
tools:ignore="BottomAppBar">

<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingStart="16dp"
android:paddingEnd="16dp">
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/btnLeave"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="Leave Meeting"
android:src="@drawable/ic_end_call"
app:backgroundTint="#FF5D5D"
app:fabSize="normal"
app:tint="@color/white" />
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/btnMic"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="90dp"
android:layout_toEndOf="@+id/btnLeave"
android:contentDescription="Toggle Mic"
android:src="@drawable/ic_mic_off"
app:backgroundTint="@color/white"
app:borderWidth="1dp"
app:fabSize="normal" />
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/btnWebcam"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="90dp"
android:layout_toEndOf="@+id/btnMic"
android:backgroundTint="@color/white"
android:contentDescription="Toggle Camera"
android:src="@drawable/ic_video_camera_off"
app:backgroundTint="@color/white"
app:borderWidth="1dp"
app:fabSize="normal" />
</RelativeLayout>
</com.google.android.material.bottomappbar.BottomAppBar>

Copy required icons from here and paste in your project’s res/drawable folder.

Initializing the Meeting

After getting token and meetingId from JoinActivity, we need to...

  • Initialize Video SDK
  • Configure Video SDK with token.
  • Initialize the meeting with required params such as meetingId, participantName, micEnabled, webcamEnabled,participantId and map of CustomStreamTrack.
  • Join the room with meeting.join() method.
public class MeetingActivity extends AppCompatActivity {
private static Meeting meeting;
private boolean micEnabled = true;
private boolean webcamEnabled = true;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_meeting);
//
Toolbar toolbar = findViewById(R.id.material_toolbar);
toolbar.setTitle("");
setSupportActionBar(toolbar);
//
String token = getIntent().getStringExtra("token");
final String meetingId = getIntent().getStringExtra("meetingId");
// set participant name
String localParticipantName = "Alex";
// Initialize VideoSDK
VideoSDK.initialize(getApplicationContext());
// pass the token generated from api server
VideoSDK.config(token);
// create a new meeting instance
meeting = VideoSDK.initMeeting(
MeetingActivity.this, meetingId, localParticipantName,
micEnabled, webcamEnabled, null, null
);
// join the meeting
if (meeting != null) meeting.join();
//
TextView textMeetingId = findViewById(R.id.txtMeetingId);
textMeetingId.setText(meetingId);
// copy meetingId to clipboard
((ImageButton) findViewById(R.id.btnCopyContent)).setOnClickListener(v -> copyTextToClipboard(meetingId));
}
private void copyTextToClipboard(String text) {
ClipboardManager clipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
ClipData clip = ClipData.newPlainText("Copied text", text);
clipboard.setPrimaryClip(clip);
Toast.makeText(MeetingActivity.this, "Copied to clipboard!", Toast.LENGTH_SHORT).show();
}
}

Step 5: Handle Local Participant Media

We need to implement clicks for the following Views:

  • Mic Button
  • Webcam Button
  • Switch Camera Button
  • Leave Button

Add the following implementation:

public class MeetingActivity extends AppCompatActivity {

private FloatingActionButton btnWebcam, btnMic, btnLeave;
private ImageButton btnSwitchCameraMode;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_meeting);
//
btnMic = findViewById(R.id.btnMic);
btnWebcam = findViewById(R.id.btnWebcam);
btnLeave = findViewById(R.id.btnLeave);
btnSwitchCameraMode = findViewById(R.id.btnSwitchCameraMode);
//...
// actions
setActionListeners();
}
private void setActionListeners() {
// Toggle mic
btnMic.setOnClickListener(view -> toggleMic());
// Toggle webcam
btnWebcam.setOnClickListener(view -> toggleWebCam());
// Leave meeting
btnLeave.setOnClickListener(view -> {
// this will make the local participant leave the meeting
meeting.leave();
});
// Switch camera
btnSwitchCameraMode.setOnClickListener(view -> {
//a participant can change stream from front/rear camera during the meeting.
meeting.changeWebcam();
});
}
}
private void toggleMic() {
if (micEnabled) {
// this will mute the local participant's mic
meeting.muteMic();
} else {
// this will unmute the local participant's mic
meeting.unmuteMic();
}
micEnabled = !micEnabled;
// change mic icon according to micEnable status
toggleMicIcon();
}

@SuppressLint("ResourceType")
private void toggleMicIcon() {
if (micEnabled) {
btnMic.setImageResource(R.drawable.ic_mic_on);
btnMic.setColorFilter(Color.WHITE);
Drawable buttonDrawable = btnMic.getBackground();
buttonDrawable = DrawableCompat.wrap(buttonDrawable);
//the color is a direct color int and not a color resource
if (buttonDrawable != null) DrawableCompat.setTint(buttonDrawable, Color.TRANSPARENT);
btnMic.setBackground(buttonDrawable);
} else {
btnMic.setImageResource(R.drawable.ic_mic_off);
btnMic.setColorFilter(Color.BLACK);
Drawable buttonDrawable = btnMic.getBackground();
buttonDrawable = DrawableCompat.wrap(buttonDrawable);
//the color is a direct color int and not a color resource
if (buttonDrawable != null) DrawableCompat.setTint(buttonDrawable, Color.WHITE);
btnMic.setBackground(buttonDrawable);
}
}
private void toggleWebCam() {
if (webcamEnabled) {
// this will disable the local participant webcam
meeting.disableWebcam();
} else {
// this will enable the local participant webcam
meeting.enableWebcam();
}
webcamEnabled = !webcamEnabled;
// change webCam icon according to webcamEnabled status
toggleWebcamIcon();
}

@SuppressLint("ResourceType")
private void toggleWebcamIcon() {
if (webcamEnabled) {
btnWebcam.setImageResource(R.drawable.ic_video_camera);
btnWebcam.setColorFilter(Color.WHITE);
Drawable buttonDrawable = btnWebcam.getBackground();
buttonDrawable = DrawableCompat.wrap(buttonDrawable);
//the color is a direct color int and not a color resource
if (buttonDrawable != null) DrawableCompat.setTint(buttonDrawable, Color.TRANSPARENT);
btnWebcam.setBackground(buttonDrawable);
} else {
btnWebcam.setImageResource(R.drawable.ic_video_camera_off);
btnWebcam.setColorFilter(Color.BLACK);
Drawable buttonDrawable = btnWebcam.getBackground();
buttonDrawable = DrawableCompat.wrap(buttonDrawable);
//the color is a direct color int and not a color resource
if (buttonDrawable != null) DrawableCompat.setTint(buttonDrawable, Color.WHITE);
btnWebcam.setBackground(buttonDrawable);
}
}

Setting up Local participant view

To set up participant view, we have to implement all the methods of the ParticipantEventListener abstract Class and add the listener to Participant class using the addEventListener() method of Participant Class. ParticipantEventListener class have two methods :

  • onStreamEnabled - Whenever a participant enables mic/webcam in meeting, This event will be triggered and return Stream.
  • onStreamDisabled - Whenever a participant disables mic/webcam in meeting, This event will be triggered and return Stream.
public class MeetingActivity extends AppCompatActivity {

private VideoView localView;
private VideoView participantView;
private CardView localCard, participantCard;
private ImageView localParticipantImg;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_meeting);
//...
localCard = findViewById(R.id.LocalCard);
participantCard = findViewById(R.id.ParticipantCard);
localView = findViewById(R.id.localView);
participantView = findViewById(R.id.localParticipant);
localParticipantImg = findViewById(R.id.localParticipant_img);
//...
// setup local participant view
setLocalListeners();
}
private void setLocalListeners() {
meeting.getLocalParticipant().addEventListener(new ParticipantEventListener() {
@Override
public void onStreamEnabled(Stream stream) {
if (stream.getKind().equalsIgnoreCase("video")) {
VideoTrack track = (VideoTrack) stream.getTrack();
localView.setVisibility(View.VISIBLE);
localView.addTrack(track);
localView.setZOrderMediaOverlay(true);
localCard.bringToFront();
}
}
@Override
public void onStreamDisabled(Stream stream) {
if (stream.getKind().equalsIgnoreCase("video")) {
localView.removeTrack();
localView.setVisibility(View.GONE);
}
}
});
}
}

Setting up Remote participant view

private final ParticipantEventListener participantEventListener = new ParticipantEventListener() {
// trigger when participant enabled mic/webcam
@Override
public void onStreamEnabled(Stream stream) {
if (stream.getKind().equalsIgnoreCase("video")) {
localView.setZOrderMediaOverlay(true);
localCard.bringToFront();
VideoTrack track = (VideoTrack) stream.getTrack();
participantView.setVisibility(View.VISIBLE);
participantView.addTrack(track);
}
}

// trigger when participant disabled mic/webcam
@Override
public void onStreamDisabled(Stream stream) {
if (stream.getKind().equalsIgnoreCase("video")) {
participantView.removeTrack();
participantView.setVisibility(View.GONE);
}
}
};

Handle meeting events & manage participant’s view

  • Add MeetingEventListener for listening events such as Meeting Join/Left and Participant Join/Left.
public class MeetingActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_meeting);
//...

// handle meeting events
meeting.addEventListener(meetingEventListener);
}
private final MeetingEventListener meetingEventListener = new MeetingEventListener() {
@Override
public void onMeetingJoined() {
// change mic,webCam icon after meeting successfully joined
toggleMicIcon();
toggleWebcamIcon();
}
@Override
public void onMeetingLeft() {
if (!isDestroyed()) {
Intent intent = new Intent(MeetingActivity.this, JoinActivity.class);
startActivity(intent);
finish();
}
}
@Override
public void onParticipantJoined(Participant participant) {
// Display local participant as miniView when other participant joined
changeLocalParticipantView(true);
Toast.makeText(MeetingActivity.this, participant.getDisplayName() + " joined",
Toast.LENGTH_SHORT).show();
participant.addEventListener(participantEventListener);
}
@Override
public void onParticipantLeft(Participant participant) {
// Display local participant as largeView when other participant left
changeLocalParticipantView(false);
Toast.makeText(MeetingActivity.this, participant.getDisplayName() + " left",
Toast.LENGTH_SHORT).show();
}
};
}
  • changeLocalParticipantView(isMiniView: Boolean) function first checks whether the video of a local participant is displayed as a MiniView or a LargeView.
  • If the meeting has only one participant (local participant), then local participant is displayed as LargeView.
  • When another participant (other than the local participant) joins, changeLocalParticipantView(true) is called. And as a result, the local participant is shown as MiniView, while the other participant is shown as LargeView.
private void changeLocalParticipantView(boolean isMiniView) {
if(isMiniView)
{
// show localCard as miniView
localCard.setLayoutParams(new CardView.LayoutParams(300, 430, Gravity.RIGHT | Gravity.BOTTOM));
ViewGroup.MarginLayoutParams cardViewMarginParams = (ViewGroup.MarginLayoutParams) localCard.getLayoutParams();
cardViewMarginParams.setMargins(30, 0, 60, 40);
localCard.requestLayout();
// set height-width of localParticipant_img
localParticipantImg.setLayoutParams(new FrameLayout.LayoutParams(150, 150, Gravity.CENTER));
participantCard.setVisibility(View.VISIBLE);
}else{
// show localCard as largeView
localCard.setLayoutParams(new CardView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
ViewGroup.MarginLayoutParams cardViewMarginParams = (ViewGroup.MarginLayoutParams) localCard.getLayoutParams();
cardViewMarginParams.setMargins(30, 5, 30, 30);
localCard.requestLayout();
// set height-width of localParticipant_img
localParticipantImg.setLayoutParams(new FrameLayout.LayoutParams(400, 400, Gravity.CENTER));
participantCard.setVisibility(View.GONE);
}
}

Destroying everything

We need to release resources when the app is closed and is no longer being used. Override the onDestroy with following code:

protected void onDestroy() {
if(meeting !=null)
{
meeting.removeAllListeners();
meeting.getLocalParticipant().removeAllListeners();
meeting.leave();
meeting = null;
}
if (participantView != null) {
participantView.setVisibility(View.GONE);
participantView.releaseSurfaceViewRenderer();
}
if (localView != null) {
localView.setVisibility(View.GONE);
localView.releaseSurfaceViewRenderer();
}
super.onDestroy();
}

java.lang.IllegalStateException: This Activity already has an action bar supplied by the window decor. Do not request Window.FEATURE_SUPPORT_ACTION_BAR and set windowActionBar to false in your theme to use a Toolbar instead.
If you face this error at Runtime, Include these lines in
theme.xml file.
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>

App Demo

Tadaa!! Our app is ready. Easy, isn’t it?
Install and run the app on two different devices and make sure that they are connected to the internet.

This app only supports 2 participants, it does not manage more than 2 participants. If you want to handle more than 2 participant then checkout our Group call example here.

Conclusion

  • In this blog, we have learned what video SDK is, how to obtain an access token from the Video SDK dashboard, and how to create a one to one video call app with the Video SDK.
  • Go ahead and create advanced features like screen-sharing,chat and others.Browse Our documentation.
  • To see the full implementation of the app, check out this GitHub repository.
  • If you face any problem or have questions, Please join our Discord community.

More Android Resources

--

--