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.
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.
Create a Firebase project in the Firebase console. For details, see Firebase Documentation.
Create a new Realtime Database in Firebase.
Edit the rules of the Realtime Database by adding the following:
{
"rules": {
".read": "auth.uid != null",
".write": "auth.uid != null",
}
}
Install the CLI via npm.
npm install -g firebase-tools
Run the firebase login
to log in via the browser and authenticate the firebase tool.
Go to your Firebase project directory.
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.
Download the Cloud function sample code.
Copy the firebase.json
and functions\index.js
files in the sample code to your cloud function project, overwrite files with the same name.
Copy the functions\token04
folder from the cloud function project directory, and put it in the same folder together with the index.js
.
Modify the index.js
file, fill in the AppID and ServerSecret you get from ZEGOCLOUD Admin Console correctly.
In Firebase CLI, run the firebase deploy --only functions
command to deploy the cloud functions.
To integrate the SDK, do the following:
zegocall
module to your project root directory (if you have no project, create a new one).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')
}
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'
}
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.
Click Sync now.
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.**{*;}
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.
});
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);
}
}
}
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
});
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);
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);
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.
}
});
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.
});
After finishing using the ZEGO Call, call the unInit
method to deinitialize the SDK.
ZegoServiceManager.getInstance().unInit();
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
}
}