ZEGO Call
  • iOS
  • Android : Java
  • Introduction
  • Sample app
  • Getting started
    • Make your first call with CallUIKit
    • Make your first call with Call SDK
  • Guides
    • Use ZEGO Call with your business server
  • Error codes
  • Documentation
  • ZEGO Call
  • Getting started
  • Make your first call with Call SDK

Make your first call with Call SDK

Last updated:2022-04-29 15:24

This document describes how to make your first voice/video call with the ZEGO Call SDK. To implement the call capability, you will need to While you will need to implement the UI logic on your own when integrating the ZEGO Call SDK to implement the call capability.

To implement the call capability more quickly, we recommend you try our CallUIKit, which already integrated the UI logic and can be integrated easier.




Prerequisites

  • Create a project in ZEGOCLOUD Admin Console.
  • Install Node.js and npm. Node.js versions 10, 12, 14, and 16 are supported.
  • Install Android Studio 2.1 or later.
  • Android SDK Packages: Android SDK 25, Android SDK Build-Tools 25.0.2, Android SDK Platform-Tools 25.x.x or later.

Deploy the Firebase Cloud Functions

ZEGO Call uses the Firebase Cloud Functions as the business server by default, we recommend you activate and deploy it before integrating the Call SDK.

To use your own business server instead of using the Firebase, refer to the Use ZEGO Call with your business server.

  1. Create a Firebase project in the Firebase console. For details, see Firebase Documentation.

  2. Create a new Realtime Database in Firebase.

    /Pics/ZEGOCall/rtd.png

  3. Edit the rules of the Realtime Database by adding the following:

{
  "rules": {
        ".read": "auth.uid != null",
        ".write": "auth.uid != null",
  }
}

/Pics/ZEGOCall/firebase_rules.png

  1. Install the CLI via npm.

    npm install -g firebase-tools
  2. Run the firebase login to log in via the browser and authenticate the firebase tool.

  3. Go to your Firebase project directory.

  4. Run firebase init functions. The tool gives you an option to install dependencies with npm. It is safe to decline if you want to manage dependencies in another way, though if you do decline you'll need to run npm install before emulating or deploying your functions.

  5. Download the Cloud function sample code.

  6. Copy the firebase.json and functions\index.js files in the sample code to your cloud function project, overwrite files with the same name.

  7. Copy the functions\token04 folder from the cloud function project directory, and put it in the same folder together with the index.js.

    /Pics/ZEGOCall/copy_cf.png

  8. Modify the index.js file, fill in the AppID and ServerSecret you get from ZEGOCLOUD Admin Console correctly.

    /Pics/ZEGOCall/index_appid.png

  9. In Firebase CLI, run the firebase deploy --only functions command to deploy the cloud functions.

Integrate the zegocall SDK

To integrate the SDK, do the following:

  1. Download the Sample codes, import the zegocall module to your project root directory (if you have no project, create a new one).

/Pics/ZEGOCall/import.png

  1. Modify the build.gradle file of your application (in the app folder), add the following code :

    ...
    apply plugin: 'com.google.gms.google-services'
    apply plugin: 'com.google.firebase.crashlytics'
    
    android {
        ...
    }
    
    dependencies {
        ...
    
        // Google Sign In SDK (only required for Google Sign In)
        implementation 'com.google.android.gms:play-services-auth:20.1.0'
        implementation project(path: ': zegocall')
    }

    /Pics/ZEGOCall/gradle1.png

    /Pics/ZEGOCall/gradle4.png

  2. Modify the build.gradle file of your project, add the following code :

    If your Android Studio version is higher than "bumblebee 2021.1.1 patch 1", please modify maven configuration in the setting.gradle. For more details, see How to add the Maven repositories in Android Studio version bumblebee?

    buildscript {
        repositories {
            maven { url 'https://www.jitpack.io' }
            ...
        }
        dependencies {
            ...
            classpath 'com.google.gms:google-services:4.3.10'
            classpath 'com.google.firebase:firebase-crashlytics-gradle:2.8.1'
        }
    

    /Pics/ZEGOCall/gradle3.png

  1. Add Firebase to your project by referring to the Add Firebase to your Android project: Step 2-3, and make sure you have downloaded and added the google-services.json file to your app directory.

  2. Click Sync now.

Prevent class name obfuscation

To prevent the ZEGO SDK public class names from being obfuscated, you can add the following code in the file proguard-rules.pro.

-keep class **.zego.**{*;}

Initialize the zegocall SDK

To initialize the zegocall SDK, get the ZegoServiceManager instance, pass the AppID of your project.

// Initialize the SDK. We recommend you call this method when the application starts.
// appID is the AppID you get from ZEGOCLOUD Admin Console.
// The last parameter refers to the Application object of this project.
ZegoServiceManager.getInstance().init(appID, this);

To receive event callbacks, call the setListener to listen for and handle various events as needed.

ZegoCallService callService = ZegoServiceManager.getInstance().callService;
ZegoUserService userService = ZegoServiceManager.getInstance().userService;
userService.setListener(new ZegoUserServiceListener() {
    // Implement the callback handling logic as needed.        
});
callService.setListener(new ZegoCallServiceListener() {
    // Implement the callback handling logic as needed.        
});

User login

ZEGO Call does not provide user management capabilities yet. You will need to have users log in to Firebase and then call the setLocalUser method to set user information to Call SDK based on the login result.

Firebase provides multiple login authentication modes. The following uses Google login as an example. For more modes, refer to the Firebase official.

// init google sign in 
GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
        .requestIdToken(CLIENT_ID)
        .requestEmail()
        .build();
GoogleSignInClient mGoogleSignInClient = GoogleSignIn.getClient(this, gso);

// when button is clicked,invoke this
private void signIn() {
    Intent signInIntent = mGoogleSignInClient.getSignInIntent();
    startActivityForResult(signInIntent, RC_SIGN_IN);
}

// overwrite onActivityResult to get google sign in result.
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

    // Result returned from launching the Intent from GoogleSignInApi.getSignInIntent(...);
    if (requestCode == RC_SIGN_IN) {
        Task<GoogleSignInAccount> task = GoogleSignIn.getSignedInAccountFromIntent(data);
        try {
            // Google Sign In was successful, authenticate with Firebase
            GoogleSignInAccount account = task.getResult(ApiException.class);
            AuthCredential credential = GoogleAuthProvider.getCredential(account.getIdToken(), null);
            FirebaseAuth.getInstance().signInWithCredential(credential)
                .addOnCompleteListener(new OnCompleteListener<AuthResult>() {
                    @Override
                    public void onComplete(@NonNull Task<AuthResult> task) {
                    if (task.isSuccessful()) {
                        // Sign in success, update UI with the signed-in user's information
                        Log.d(TAG, "signInWithCredential:success");
                        FirebaseUser currentUser = FirebaseAuth.getInstance().getCurrentUser();
                       ZegoServiceManager.getInstance().userService.setLocalUser(currentUser.getUid(), currentUser.getDisplayName());
                    } else {
                        // If sign in fails, display a message to the user.
                        Log.w(TAG, "signInWithCredential:failure", task.getException()); 
                    }
                }
            });
        } catch (ApiException e) {
            // Google Sign In failed, update UI appropriately
            Log.w(TAG, "Google sign in failed", e);
        }
    }
}

Make outbound calls

ZEGOCLOUD Call implements the voice and video call feature using the RTC SDK. The caller and called user join the same room and the stream publishing and stream playing start upon the call gets connected. Therefore, to make an outbound call, you will need to provide a token for the RTC SDK for validation. For details, see Control user privileges.

Before making or accepting an outbound call, you will need to get a Token from the Firebase Cloud Functions.

private void getTokenFromCloudFunction(String userID, long effectiveTime) {
    Map<String, Object> data = new HashMap<>();
    data.put("id", userID);
    data.put("effective_time", effectiveTime);

    FirebaseFunctions.getInstance().getHttpsCallable("getToken")
        .call(data)
        .continueWith(new Continuation<HttpsCallableResult, Object>() {
            @Override
            public Object then(@NonNull Task<HttpsCallableResult> task) throws Exception {
                return task.getResult().getData();
            }
        })
        .addOnCompleteListener(new OnCompleteListener<Object>() {
            @Override
            public void onComplete(@NonNull Task<Object> task) {
                if (!task.isSuccessful()) {
                    Exception e = task.getException();
                    if (e instanceof FirebaseFunctionsException) {
                        FirebaseFunctionsException ffe = (FirebaseFunctionsException) e;
                        FirebaseFunctionsException.Code code = ffe.getCode();
                        Object details = ffe.getDetails();
                    }
                    return;
                }
                HashMap<String, String> result = (HashMap<String, String>) task.getResult();
                String token = result.get("token");
            }
        });
}

To make an outbound voice call, call the callUser method and set the callType parameter to ZegoCallType.Voice.

For Android 6.0 or later, some important permissions must be requested both at runtime and declared statically in the file AndroidMainfest.xml, you can add the following code to do so (requestPermissions is a method of an Android Activity). For more information, refer to Request app permissions.

// shows how to request camera and audio permission at run time
String[] permissionNeeded = {
        "android.permission.CAMERA",
        "android.permission.RECORD_AUDIO"};

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
    if (ContextCompat.checkSelfPermission(this, "android.permission.CAMERA") != PackageManager.PERMISSION_GRANTED ||
        ContextCompat.checkSelfPermission(this, "android.permission.RECORD_AUDIO") != PackageManager.PERMISSION_GRANTED) {
        requestPermissions(permissionNeeded, 101);
    }
}

You can make a call after getting the access permission of the camera and microphone.

// userInfo refers to the user info(ID and name) of the user you want call. 
// ZegoCallType.Voice indicates that you make a voice call.
// token refers to the token you provide to the RTC SDK for validation.
ZegoServiceManager.getInstance().userService.callUser(userInfo, ZegoCallType.Voice, token, errorCode -> {
    // Callback for the result of make a call. 
});

To make an outbound video call, call the callUser method and set the callType parameter to ZegoCallType.Video.

// userInfo refers to the user info(ID and name) of the user you want call. 
// ZegoCallType.Video indicates that you make a video call.
// token refers to the token you provide to the RTC SDK for validation.
ZegoServiceManager.getInstance().userService.callUser(userInfo, ZegoCallType.Video, token, errorCode -> {
    // Callback for the result of make a call. 
});

To start the local video preview (using the front-facing camera) when initiating an outbound video call, call the startPreview method.

ZegoServiceManager.getInstance().streamService.startPreview(textureView);

To cancel the call you just initiated, call the cancelCall method before the call gets answered.

ZegoServiceManager.getInstance().callService.cancelCall(errorCode -> {
    // Callback for the result of cancel a call
});

Respond to incoming calls

After a call is made, the called user receives a notification through the callback onReceiveCallInvite.

ZegoServiceManager.getInstance().callService.setListener(new ZegoCallServiceListener() {
    public void onReceiveCallInvite(ZegoUserInfo userInfo, String callID, ZegoCallType type) {
        // Implement the callback handling logic when receiving an incoming call. For example, you can set a ringing and a UI for call notification. 
    }       
});

If the call has been canceled before it gets answered, the called user receives a notification through the callback onReceiveCallCanceled.

ZegoServiceManager.getInstance().callService.setListener(new ZegoCallServiceListener() {
    public void onReceiveCallCanceled(ZegoUserInfo userInfo) {
        // Implement the callback handling logic when receiving a notification that the incoming call has been canceled. For example, you can set the ringing to stop and the UI to stop notifying.
    }       
});

To respond to an incoming call, call the acceptCall method to accept it or call the declineCall method to decline it.

// Accept an incoming call. 
// token refers to the token you provide to the RTC SDK for validation.
ZegoServiceManager.getInstance().callService.acceptCall(token, errorCode -> {
    // Callback for the result of accept a call
});

// Decline an incoming call. 
ZegoServiceManager.getInstance().callService.declineCall(errorCode -> {
    // Callback for the result of decline a call
});

After the call gets answered, the caller receives a notification through the callback onReceiveCallAccepted or onReceiveCallDeclined.

When you receive an incoming call, the ZEGO Call SDK will automatically determine that you are in the busy state. In this case, the ZEGO Call SDK will automatically reject other call invitations until you decline or end the current call.

ZegoServiceManager.getInstance().callService.setListener(new ZegoCallServiceListener() {
    // Callback: the call has been accepted. 
    public void onReceiveCallAccept(ZegoUserInfo userInfo){
        // Implement the callback handling logic as needed.
    }

    // Callback: the call has been declined. 
    // It indicates the callee declines the call actively when the [DeclineType] is [decline]. 
    // It indicates the callee is busy when the [DeclineType] is [busy], and the SDK automatically declines the call. 
    public void onReceiveCallDecline(ZegoUserInfo userInfo, ZegoDeclineType declineType){
        // Implement the callback handling logic as needed.
    }
});

After the called user accepts the call, both the caller and called user will need to call the startPlaying method to start playing the audio and video streams to begin a call.

// userID refers to the ID of the user that you are on the line with. 
// In a voice call, the textureView is null.
// In a video call, the textureView will be the view to be previewed during the video call. 
// To preview your local video preview during a video call, call this method again. And pass in your user ID to the userID, pass in the view to be previewed to textureView. 
ZegoServiceManager.getInstance().streamService.startPlaying(userID, textureView);

Control the devices during a call

To enable or disable the camera during a video call, call the enableCamera method.

// To enable the camera, set it to [true]. To disable the camera, set it to [false].
ZegoServiceManager.getInstance().deviceService.enableCamera(true);

To change the camera during a call, call the useFrontCamera method.

// To use the front-facing camera, set it to [true]. To use the rear camera, set it to [false].
ZegoServiceManager.getInstance().deviceService.useFrontCamera(true);

To enable or disable the microphone during a voice or video call, call the enableMic method.

// To enable the mircophone, set it to [true]. To disable the microphone, set it to [false].
ZegoServiceManager.getInstance().deviceService.enableMic(true);

To enable or disable the speaker during a voice or video call, call the enableSpeaker method.

// To enable the speaker, set it to [true]. To disable the speaker, set it to [false].
ZegoServiceManager.getInstance().deviceService.enableSpeaker(true);

End a call

For the caller or called user to end a call, call the endCall method.

ZegoServiceManager.getInstance().callService.endCall(errorCode -> {
    // Callback for the result of end a call 
});

Once the call ended, the other user receives a notification through the callback onReceiveCallEnded.

ZegoServiceManager.getInstance().callService.setListener(new ZegoCallServiceListener() {
    public void onReceiveCallEnded(){
        // Implement the callback handling logic as needed. For example, you can disable the UI that shows a call is ongoing.
    }       
});

Upload logs

When you encounter problems when using your app, call the uploadLog method to upload logs for us to locate and help you faster.

ZegoServiceManager.getInstance().uploadLog(errorCode -> {
    // Callback for the result of upload SDK logs. 
});

Deinitialize the zegocall SDK

After finishing using the ZEGO Call, call the unInit method to deinitialize the SDK.

ZegoServiceManager.getInstance().unInit();

FAQ

Question: The error Lambda expressions are not supported at language level '7' occurs after importing the zegocall module.

Answer: Lambda expressions are only supported in Java 8 or later. You will need to add the following code into the build.gradle file of your project first:

android {
    ...
    // Configure only for each module that uses Java 8
    // language features (either in its source code or
    // through dependencies).
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
}
Page Directory