DEV Community

Sandy Pradana
Sandy Pradana

Posted on

Building an Android Video Call Application with ZEGOCLOUD CallKit (Kotlin)

Introduction to ZEGOCLOUD CallKit

ZEGOCLOUD is a real-time communication platform that provides APIs and SDKs for building various digital communication features, such as video calls, voice calls, live streaming, and other real-time interactions. This platform is designed to help developers easily integrate real-time communication technology into their applications.
One of ZEGOCLOUD’s flagship solutions is CallKit, a ready-to-use package that simplifies the process of building calling features. With CallKit, we do not need to build everything from scratch because:

  1. The video call UI is already available and ready to use.
  2. The incoming and outgoing call system is automatically integrated.
  3. User management, camera, microphone, mute, and network handling are managed by the system.
  4. It supports both one-on-one (1-on-1) calls and group calls.

By simply preparing the App ID and App Sign and performing a few simple configurations, we can directly implement video call features into our application without developing them from the ground up.

Introduction to Kotlin

Kotlin is a modern programming language developed by JetBrains and runs on the Java Virtual Machine (JVM). Its popularity surged after Google officially designated Kotlin as the primary language for Android development in Android Studio. Supported by an active global community and a continuously growing ecosystem of libraries, Kotlin has become the preferred choice for developers to build Android applications faster, cleaner, and with fewer errors compared to the conventional approach using Java.

In this article, I will share a step-by-step guide on building an Android video call application using ZEGOCLOUD CallKit with the Kotlin programming language, based on the demonstration presented on the Sandy Pradana YouTube channel. The steps are as follows:

Creating a ZEGOCLOUD Account

Visit https://www.zegocloud.com, then click Sign Up. Choose one of the available registration methods, either using a Google account or filling out the registration form manually.
After successfully registering, complete your profile data according to the requested information. Once registered and logged in, on the dashboard page you will receive 10,000 minutes of free streaming/video call credits using ZEGOCLOUD.

Obtaining the App ID & App Sign

The next step is to create a new project in ZEGOCLOUD to obtain the App ID and App Sign. These two items are required to integrate the application we build with our ZEGOCLOUD account. Therefore, never share your App ID and App Sign for security reasons.

Steps:

  1. On the Dashboard menu, select Create Project.
  2. From the available feature options, choose Voice & Video Call, then click Next.
  3. Fill in the project name form, for example ZegoVcall.
  4. Select Start with UI Kits.
  5. Wait until the project creation process is complete, then click Start building your app.
  6. In the framework selection form, choose For Android.
  7. In the feature configuration, select the features you want to enable. Available options include 1-on-1 call or Group Call, as well as enabling call invitations, standard face beautification, screen sharing, virtual avatars, and others. For this tutorial, we only need to enable 1-on-1 call.
  8. Click Save and start integrate.
  9. You will then receive your App ID and App Sign (Never share your App ID and App Sign).

Creating a New Project in Android Studio Using Kotlin

The steps to create a new project in Android Studio are as follows:

  1. Open Android Studio.
  2. Select New Project, then choose the template Empty Views Activity.
  3. Fill in the application details:
    Application name: for example Zego Vcall
    Package name and project storage location as needed
    Choose Kotlin as the language
    Set Minimum SDK to API 26 (lower versions do not support ZEGOCLOUD integration).

  4. Click Finish, then wait until the project creation process is complete.

Adding the ZEGOCLOUD CallKit dependency to the project

After finishing creating the project, the next step is to add the ZEGOCLOUD CallKit dependency to the project. The setup instructions can be easily followed through the documentation provided in the ZEGOCLOUD project that we created earlier, or the documentation can be accessed via the following link: https://www.zegocloud.com/docs/uikit/callkit-android/quick-start
. The steps are as follows:

Go to the project root folder, then open the settings.gradle file.

Add two lines of code as shown below inside the repositories tag.

maven { url = uri("https://maven.zego.im") } // <- Add this line.
maven { url = uri("https://www.jitpack.io") } // <- Add this line.

settings.gradle.kts

pluginManagement {
    repositories {
        google {
            content {
                includeGroupByRegex("com\\.android.*")
                includeGroupByRegex("com\\.google.*")
                includeGroupByRegex("androidx.*")
            }
        }
        mavenCentral()
        maven { url = uri("https://maven.zego.im") }   // <- Add this line.
        maven { url = uri("https://www.jitpack.io") } // <- Add this line.
        gradlePluginPortal()
    }
}
dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {
        google()
        mavenCentral()
        maven { url = uri("https://maven.zego.im") }   // <- Add this line.
        maven { url = uri("https://www.jitpack.io") } // <- Add this line.
    }
}

rootProject.name = "Zego Vcall"
include(":app")

Enter fullscreen mode Exit fullscreen mode

Selanjutnya adalah menambahkan depedency pada build.gradle.kts (module)

dependencies {
    ...
    implementation("com.github.ZEGOCLOUD:zego_uikit_prebuilt_call_android:+")    // add this line in your module-level build.gradle file's dependencies, usually named [app].
}
Enter fullscreen mode Exit fullscreen mode

After all dependencies have been added, click Sync Now.

Adding application permissions in AndroidManifest.xml

After the synchronization completes without errors, we proceed by adding important permissions in the AndroidManifest.xml file, such as access to the internet, camera, microphone (audio recording), network state, and Wi-Fi.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.RECORD_AUDIO" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.CAMERA" />
    <uses-permission android:name="android.permission.BLUETOOTH" />
    <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" /> <!-- Permissions required by the App -->
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
    <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />

    <uses-feature
        android:glEsVersion="0x00020000"
        android:required="true" />
    <uses-feature android:name="android.hardware.camera" />
    <uses-feature android:name="android.hardware.camera.autofocus" />

    <application
        android:allowBackup="true"
        android:dataExtractionRules="@xml/data_extraction_rules"
        android:fullBackupContent="@xml/backup_rules"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.ZegoVcall">
        <activity
            android:name=".CallActivity"
            android:exported="false" />
        <activity
            android:name=".MainActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>
Enter fullscreen mode Exit fullscreen mode

Creating the UI for Join Room/Call ID and Logic for Start Video Call

After completing the basic configuration, we start by creating the main application interface using a simple vertical LinearLayout. The layout contains an EditText for entering the Call ID or Room Code and a “Join Call” button to enter the video call room. This concept allows two or more users to join the same room simply by entering the identical Call ID on each device.

activity_main.xml :

<?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/main"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="24dp"
    android:gravity="center"
    tools:context=".MainActivity">

    <EditText
        android:id="@+id/edtCallID"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="Enter Call ID/ Room Code"
        android:padding="16dp"
        android:background="@android:drawable/edit_text"
        android:textSize="16sp"/>

    <Button
        android:id="@+id/btnJoin"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Join Call"
        android:layout_marginTop="20dp"
        android:textSize="18sp"/>

</LinearLayout>
Enter fullscreen mode Exit fullscreen mode

In MainActivity, each UI component is linked using findViewById. When the Join button is pressed, the application validates the input to ensure that the Call ID is not empty. If it is empty, the user will receive an error message. If a Call ID is provided, the application navigates to CallActivity while passing the Call ID parameter through an Intent.

MainActivity.kt

package com.mstech.zegovcall

import android.annotation.SuppressLint
import android.content.Intent
import android.os.Bundle
import android.widget.Button
import android.widget.EditText
import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat

class MainActivity : AppCompatActivity() {
    @SuppressLint("MissingInflatedId")
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        setContentView(R.layout.activity_main)

        val edtCallID = findViewById<EditText>(R.id.edtCallID)
        val btnJoin = findViewById<Button>(R.id.btnJoin)

        btnJoin.setOnClickListener {
            val callID = edtCallID.text.toString().trim()

            if (callID.isEmpty()) {
                edtCallID.error = "Call ID tidak boleh kosong!"
                return@setOnClickListener
            }

            val intent = Intent(this, CallActivity::class.java)
            intent.putExtra("CALL_ID", callID)
            startActivity(intent)
        }

    }
}
Enter fullscreen mode Exit fullscreen mode

Next, create a new activity using the Empty Views Activity template and name it CallActivity.
In CallActivity, we implement the ZEGOCLOUD CallKit by adding the App ID and App Sign obtained from the ZEGOCLOUD dashboard. Since this tutorial does not yet use a login system, we create a simple function to generate a random unique User ID and Username as the user identity when joining the room. Additionally, we prepare a container layout that will be used to display the ZEGOCLOUD video call fragment.

CallActivity.kt

package com.mstech.zegovcall

import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import com.zegocloud.uikit.prebuilt.call.ZegoUIKitPrebuiltCallConfig
import com.zegocloud.uikit.prebuilt.call.ZegoUIKitPrebuiltCallFragment
import java.util.UUID

class CallActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_call)

        val callID = intent.getStringExtra("CALL_ID") ?: "defaultRoom"
        addCallFragment(callID)
    }

    private fun addCallFragment(callID: String) {
        val appID: Long = **YOUR APPID**
        val appSign: String = "**YOUR APPSIGN**"
        val callID: String = callID
        //val userID: String = userID
        //val userName: String = userName

        val (userID, userName) = getUniqueUser()

        // You can also use GroupVideo/GroupVoice/OneOnOneVoice to make more types of calls.
        val config = ZegoUIKitPrebuiltCallConfig.oneOnOneVideoCall()
        val fragment = ZegoUIKitPrebuiltCallFragment.newInstance(
            appID, appSign, userID, userName, callID, config
        )
        supportFragmentManager.beginTransaction()
            .replace(R.id.fragment_container, fragment)
            .commitNow()
    }

    private fun getUniqueUser(): Pair<String, String> {
        val prefs = getSharedPreferences("userData", MODE_PRIVATE)

        var id = prefs.getString("uid", null)
        var name = prefs.getString("uname", null)

        if (id == null || name == null) {
            id = UUID.randomUUID().toString()
            name = "User-$id"
            prefs.edit()
                .putString("uid", id)
                .putString("uname", name)
                .apply()
        }

        return id!! to name!!
    }
}
Enter fullscreen mode Exit fullscreen mode

activity_call.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/fragment_container"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

</androidx.constraintlayout.widget.ConstraintLayout>
Enter fullscreen mode Exit fullscreen mode

After all configurations are ready, the application can be tested directly on an emulator or a physical device. When two devices enter the same Call ID, the video call will automatically connect. Inside the room, various standard features are available, such as switching cameras, muting/unmuting the microphone, turning the speaker on/off, and disabling video.

As the final step, the application is compiled into an APK file using the Generate Signed APK feature in Android Studio. After the signing process is completed, the APK can be installed and run directly on a smartphone. With these simple steps, we have successfully built a Kotlin-based Android video call application in a short time using the ZEGOCLOUD CallKit.

Top comments (0)