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:
- Java Development Kit.
- Android Studio 3.0 or later.
- Android SDK API Level 21 or higher.
- A mobile device that runs Android 5.0 or later.
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 setandroid.enableJetifier = true
in thegradle.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 :
- Create Button - Creates a new meeting.
- TextField for Meeting Id - Contains the meeting Id you want to join.
- 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 toMeetingActivity
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 toMeetingActivity
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
andCAMERA
. So, we will implement permission logic onJoinActivity
.
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 createMeetingActivity
.
- 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 ofCustomStreamTrack
. - 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 returnStream
. -
onStreamDisabled
- Whenever a participant disables mic/webcam in meeting, This event will be triggered and returnStream
.
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 intheme.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
- Android One-To-One video calling app with Kotlin
- Android Interactive Live Streaming App with Kotlin
- Android Video Conferencing App with Kotlin example code
- Android Interactive Live Streaming App with Kotlin example code
- Android Interactive Live Streaming App with Java example code
- Android Video Conferencing App with Java example code
Top comments (0)