Build a Zoom clone with native android and WebRTC
without wasting any time let’s start .
Open android studio and create a project .
Select empty activity and select name and all.
Select Java as programming language.
So the plan is to build splash screen , Profile for user , Login and Signup screens.
We will use Firebase for backend .
Let’s start with the splash screen .
xml of splash….
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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:background="@color/custom"
tools:context=".MainActivity">
<ImageView
android:id="@+id/imageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="TODO"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.26"
tools:srcCompat="@tools:sample/avatars" />
<ProgressBar
android:id="@+id/progressBar"
style="?android:attr/progressBarStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="239dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="@+id/imageView"
app:layout_constraintStart_toStartOf="@+id/imageView"
app:layout_constraintTop_toBottomOf="@+id/imageView" />
</androidx.constraintlayout.widget.ConstraintLayout>
In mainactivity.java file copy this..
package com.example.zoomclone;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
startActivity(new Intent(MainActivity.this,SignupActivity.class));
}
},2000);
}
}
Now if you run this you will see a spinner in the splash screen.
Next step is to handle sign in and sign up activities.
Before that let’s handle the firebase and firestore .
Head on to firebase.google.com and click on open console.
Add new project and navigate to authentication . Open docs and add dependencies in the project level gradle and app level gradle respectively.
Refer to ->
https://firebase.google.com/docs/android/setup
By right clicking on the package name (Java->package name) create an empty activity (new ->empty activity) and name it Signup activity .
Signup_activity.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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"
tools:context=".SignupActivity">
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="5dp"
android:layout_marginEnd="5dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="10dp"
android:orientation="vertical">
<EditText
android:id="@+id/editTextTextPersonName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:background="@drawable/buttonstyle"
android:ems="10"
android:hint="Enter username"
android:inputType="textPersonName"
android:padding="10dp" />
<EditText
android:id="@+id/emailBox"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:background="@drawable/buttonstyle"
android:ems="10"
android:hint="Enter your email"
android:inputType="textEmailAddress"
android:padding="10dp" />
<EditText
android:id="@+id/PasswordBox"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:background="@drawable/buttonstyle"
android:ems="10"
android:hint="Password"
android:inputType="textPassword"
android:padding="10dp" />
<Button
android:id="@+id/Create"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:background="@drawable/pressbutton"
android:text="Create Account"
android:textColor="#F1E7E7" />
<Button
android:id="@+id/Login"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:background="@drawable/pressbutton"
android:text="Already an user ? Login"
android:textColor="#FDFCFC" />
</LinearLayout>
</androidx.cardview.widget.CardView>
</androidx.constraintlayout.widget.ConstraintLayout>
SignupActivity.java
package com.example.zoomclone;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.OnSuccessListener;
import com.google.android.gms.tasks.Task;
import com.google.firebase.auth.AuthResult;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.firestore.FirebaseFirestore;
public class SignupActivity extends AppCompatActivity {
EditText emailbox,passwordbox,namebox;
Button loginbutton,signupbutton;
FirebaseAuth firebaseauth;
FirebaseFirestore database;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_signup);
emailbox =findViewById(R.id.emailBox);
passwordbox=findViewById(R.id.PasswordBox);
loginbutton =findViewById(R.id.Login);
signupbutton = findViewById(R.id.Create);
namebox = findViewById(R.id.editTextTextPersonName);
firebaseauth = FirebaseAuth.getInstance();
database = FirebaseFirestore.getInstance();
final User user = new User();
user.setEmail(emailbox.getText().toString());
user.setUsername(namebox.getText().toString());
user.setPassword(passwordbox.getText().toString());
signupbutton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String email,password,usename;
email = emailbox.getText().toString();
password = passwordbox.getText().toString();
usename = namebox.getText().toString();
firebaseauth.createUserWithEmailAndPassword(email,password).addOnCompleteListener(new OnCompleteListener<AuthResult>() {
@Override
public void onComplete(@NonNull Task<AuthResult> task) {
if(task.isSuccessful()){
database.collection("Users").document().set(user).addOnSuccessListener(new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void aVoid) {
Toast.makeText(SignupActivity.this,"Account is created",Toast.LENGTH_SHORT).show();
startActivity(new Intent(SignupActivity.this,LoginActivity.class));
}
});
}else{
Toast.makeText(SignupActivity.this,task.getException().getLocalizedMessage(),Toast.LENGTH_LONG).show();
}
}
});
}
});
loginbutton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
startActivity(new Intent(SignupActivity.this,LoginActivity.class));
}
});
}
}
In similar way create the Login activity.
In xml file of login activity add
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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:background="@color/colorPrimary"
tools:context=".LoginActivity">
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="5dp"
android:layout_marginEnd="5dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="10dp"
android:orientation="vertical">
<EditText
android:id="@+id/emailBox"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:background="@drawable/buttonstyle"
android:ems="10"
android:hint="Enter your email"
android:inputType="textEmailAddress"
android:padding="10dp" />
<EditText
android:id="@+id/PasswordBox"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:background="@drawable/buttonstyle"
android:ems="10"
android:hint="Password"
android:inputType="textPassword"
android:padding="10dp" />
<Button
android:id="@+id/Login"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:background="@drawable/pressbutton"
android:text="Login"
android:textColor="#FDFCFC" />
<Button
android:id="@+id/Create"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:background="@drawable/pressbutton"
android:text="Create Account"
android:textColor="#F1E7E7" />
</LinearLayout>
</androidx.cardview.widget.CardView>
</androidx.constraintlayout.widget.ConstraintLayout>
In LoginActivity.java add
package com.example.zoomclone;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
import com.google.firebase.auth.AuthResult;
import com.google.firebase.auth.FirebaseAuth;
public class LoginActivity extends AppCompatActivity {
EditText email,password;
Button loginbutton,signupbutton;
FirebaseAuth firebase;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
email =findViewById(R.id.emailBox);
password=findViewById(R.id.PasswordBox);
loginbutton =findViewById(R.id.Login);
signupbutton = findViewById(R.id.Create);
firebase=FirebaseAuth.getInstance();
loginbutton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String myemail,mypassword;
myemail = email.getText().toString();
mypassword=password.getText().toString();
firebase.signInWithEmailAndPassword(myemail,mypassword).addOnCompleteListener(new OnCompleteListener<AuthResult>() {
@Override
public void onComplete(@NonNull Task<AuthResult> task) {
if(task.isSuccessful()){
Toast.makeText(LoginActivity.this,"Logged in",Toast.LENGTH_SHORT).show();
startActivity(new Intent(LoginActivity.this,ProfileActivity.class));
}else{
Toast.makeText(LoginActivity.this,task.getException().getLocalizedMessage(),Toast.LENGTH_SHORT).show();
}
}
});
}
});
signupbutton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
startActivity(new Intent(LoginActivity.this,SignupActivity.class));
}
});
}
}
Now we need to add the user profile activity .
First create a new java class and add
package com.example.zoomclone;
public class User {
private String username;
private String email;
private String password;
public User(){
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
This class is a blueprint for every user .
Set up Jitsi Sdk…
//Add this to project level gradlemaven { url "https://github.com/jitsi/jitsi-maven-repository/raw/master/releases" }
// Add this to app gradleimplementation ('org.jitsi.react:jitsi-meet-sdk:2.+') { transitive = true }Hit sync now
In profile activity’s xml file add
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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"
tools:context=".ProfileActivity">
<androidx.cardview.widget.CardView
android:layout_width="342dp"
android:layout_height="255dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="15dp"
android:orientation="vertical"
android:padding="15dp">
<EditText
android:id="@+id/roomid"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="15dp"
android:ems="10"
android:hint="Room id"
android:inputType="textPersonName"
android:padding="10dp" />
<Button
android:id="@+id/joincall"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="15dp"
android:background="@drawable/pressbutton"
android:padding="10dp"
android:text="Join" />
<Button
android:id="@+id/sharebutton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/pressbutton"
android:text="Share" />
</LinearLayout>
</androidx.cardview.widget.CardView>
</androidx.constraintlayout.widget.ConstraintLayout>
In ProfileActivity.Java add
package com.example.zoomclone;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import org.jitsi.meet.sdk.JitsiMeet;
import org.jitsi.meet.sdk.JitsiMeetActivity;
import org.jitsi.meet.sdk.JitsiMeetConferenceOptions;
import java.net.MalformedURLException;
import java.net.URL;
public class ProfileActivity extends AppCompatActivity {
EditText secretcodebox;
Button sharebutton,joinButton ;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_profile);
secretcodebox = findViewById(R.id.roomid);
sharebutton = findViewById(R.id.sharebutton);
joinButton=findViewById(R.id.joincall);
URL serverUrl;
try{
serverUrl = new URL("https://meet.jit.si");
JitsiMeetConferenceOptions defaultoptions = new JitsiMeetConferenceOptions.Builder().setServerURL(serverUrl).setWelcomePageEnabled(false).build();
JitsiMeet.setDefaultConferenceOptions(defaultoptions);
} catch (MalformedURLException e) {
e.printStackTrace();
}
joinButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
JitsiMeetConferenceOptions options = new JitsiMeetConferenceOptions.Builder().setRoom(secretcodebox.getText().toString()).setWelcomePageEnabled(false).build();
JitsiMeetActivity.launch(ProfileActivity.this,options);
}
});
}
}
Now your video calling app is ready .
Reference ->