AgoraChatCallKit is an open-source audio and video UI library developed based on Agora's real-time communications and signaling services. With this library, you can implement audio and video calling functionalities with enhanced synchronization between multiple devices. In scenarios where a user ID is logged in to multiple devices, once the user deals with an incoming call that is ringing on one device, all the other devices stop ringing simultaneously.
This page describes how to implement real-time audio and video communications using the AgoraChatCallKit.
Agora provides an open-source AgoraChat-android sample project on GitHub. You can download the sample to try it out or view the source code.
The sample project uses the Agora Chat user ID to join a channel, which enables displaying the user ID in the view of the call. If you use the methods of the Agora RTC SDK to start a call, you can also use the Integer UID to join a channel.
The basic process for implementing real-time audio and video communications with AgoraChatCallKit is as follows:
- Initialize AgoraChatCallKit by calling
init
and add theAgoraChatCallKit
event listener by callingsetCallKitListener
. - Call
startSingleCall
orstartInviteMultipleCall
on the caller's client to send a call invitation for one-to-one or group calls. - On the callee's client, accept or decline the call invitation after receiving
onReceivedCall
. Once a user accepts the invitation, they enter the call. - When the call ends, the SDK triggers the
onEndCallWithReason
callback.
Before proceeding, ensure that your development environment meets the following requirements:
- Java Development Kit 1.8 or later.
- Android Studio 3.5 or later.
targetSdkVersion
33.minSdkVersion
21.- Gradle 4.6 or later.
- An Agora Chat project that has integrated the Chat SDK and implemented the basic real-time chat functionalities, including users logging in and out and sending and receiving messages.
Take the following steps to integrate the AgoraChatCallKit into your project and set up the development environment.
-
Add the dependency
AgoraChatCallKit is developed upon
io.agora.rtc:chat-sdk:x.x.x
(1.2.0 and later) andio.agora.rtc:full-rtc-basic:x.x.x
(4.1.0 and later). Follow the steps to add AgoraChatCallKit using Gradle.In
/Gradle Scripts/build.gradle(Module: <projectname>.app)
, add the following lines to integrate the AgoraChatCallKit into your Android project:implementation 'io.agora.rtc:chat-callkit:1.1.0'
- For the latest callkit version, go to Sonatype.
-
Add project permissions
In
/app/Manifests/AndroidManifest.xml
, add the following permissions after</application>
:<!-- Add alert window --> <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" /> <!-- Access to the internet --> <uses-permission android:name="android.permission.INTERNET" /> <!-- Access to the microphone --> <uses-permission android:name="android.permission.RECORD_AUDIO" /> <!-- Access to the camera --> <uses-permission android:name="android.permission.CAMERA" /> <!-- Access to the tasks --> <uses-permission android:name="android.permission.REORDER_TASKS" />
-
Add the AgoraChatCallKit Activity
In
/app/Manifests/AndroidManifest.xml
, add activities for the one-to-one audio and video call, and the group video call, for example,CallSingleBaseActivity
(inherited fromEaseCallSingleBaseActivity
) andCallMultipleBaseActivity
(inherited fromEaseCallMultipleBaseActivity
).<activity android:name=".av.SingleCallActivity" android:exported="false" android:configChanges="orientation|keyboardHidden|screenSize" android:label="@string/demo_activity_label_video_call" android:taskAffinity=".SingleCallTask" android:launchMode="singleInstance" android:excludeFromRecents="true" android:screenOrientation="portrait" /> <activity android:name=".av.MultipleCallActivity" android:exported="false" android:configChanges="orientation|keyboardHidden|screenSize" android:label="@string/demo_activity_label_multi_call" android:taskAffinity=".MultipleCallTask" android:launchMode="singleInstance" android:excludeFromRecents="true" android:screenOrientation="portrait" />
This section introduces the core steps for implementing audio and video calls in your project.
Call init
to initialize the AgoraChatCallKit after the Chat SDK is initialized. You can also add callback events to listen for and set the configurations. Refer to the following sample code:
// Construct the CallKitConfig class.
EaseCallKitConfig callKitConfig = new EaseCallKitConfig();
// Set the call out time (ms).
callKitConfig.setCallTimeOut(30 * 1000);
// Set the Agora App ID.
callKitConfig.setAgoraAppId("******");
// Set whether to enable token authentication.
callKitConfig.setEnableRTCToken(true);
// Set the default avatar.
callKitConfig.setDefaultHeadImage(getUsersManager().getCurrentUserInfo().getAvatar());
// Set the ringtone file.
String ringFile = EaseFileUtils.getModelFilePath(context,"huahai.mp3");
callKitConfig.setRingFile(ringFile);
// Set the user information.
Map<String, EaseCallUserInfo> userInfoMap = new HashMap<>();
userInfoMap.put("***",new EaseCallUserInfo("****",null));
userInfoMap.put("***",new EaseCallUserInfo("****",null));
callKitConfig.setUserInfoMap(userInfoMap);
// Call init to initialie EaseCallKit.
EaseCallKit.getInstance().init(context, callKitConfig);
// Register the activity added in the Manifest file.
EaseCallKit.getInstance().registerVideoCallClass(SingleCallActivity.class);
EaseCallKit.getInstance().registerMultipleVideoClass(MultipleCallActivity.class);
// Add event listeners to the AgoraChatCallKit.
EaseCallKit.getInstance().setCallKitListener(new DemoCallKitListener(mContext,getUsersManager()));
In this method, you need to set the EaseCallKitConfig
class. Some of the configurations include the following:
/**
* The EaseCallKitConfig class.
* @param defaultHeadImage The default avatar. Set it as the absolute path of a local file or a URL.
* @param userInfoMap The dictionary of the user information. The data format is key-value pairs, where key represents the user ID and value is EaseCallUser.
* @param callTimeOut The timeout duration for the call invitation, in miliseconds. The default value is 30 seconds.
* @param agoraAppId The Agora App ID.
* @param ringFile The ringtone file, represented by the absolute path of a local file.
* @param enableRTCToken Whether to enable token authentication for using the RTC service. If you enabled token authentication in Agora Console, set this parameter as true. The default value is false.
*/
public class EaseCallKitConfig {
private String defaultHeadImage;
private Map<String, EaseCallUserInfo> userInfoMap = new HashMap<>();
private String ringFile;
private String agoraAppId;
private long callTimeOut = 30 * 1000;
private boolean enableRTCToken = false;
public EaseCallKitConfig(){
...
}
From the caller's client, call startSingleCall
or startInviteMultipleCall
to send a call invitation for a one-to-one call or group call. You need to specify the call type when calling the method.
-
One-to-one audio and video call
Call
startSingleCall
to start a one-to-one call. You need to specify the call type as an audio call or video call in this method./** * Starts a one-to-one call. * * @param type The call type: * - SINGLE_VOICE_CALL: A one-to-one voice call. * - SINGLE_VIDEO_CALL: A one-to-one video call. * @param user The user ID of the callee. Ensure that you set this parameter. * @param ext The extension information in the call invitation. Set it as null if you do not need this information. */ public void startSingleCall(final EaseCallType type, final String user, final Map<String, Object> ext){} //for example EaseCallKit.getInstance().startSingleCall(SINGLE_VIDEO_CALL,conversationId,null, SingleCallActivity.class);
The following screenshot gives an example of the user interface after sending a call invitation for one-to-one audio call:
-
Group audio and video call
Call
startInviteMultipleCall
to start a group call. Set the call type as audio call or video call. You can set the users you want to invite from a chat group or the contact list. Refer toConferenceInviteActivity
in the sample project for implementation./** * Starts a group call. * * @param type The call type: * - SINGLE_VOICE_CALL: A one-to-one voice call. * - SINGLE_VIDEO_CALL: A one-to-one video call. * @param user The user ID of the callee. Ensure that you set this parameter. * @param ext The extension information in the call invitation. Set it as null if you do not need this information. */ public void startInviteMultipleCall(final EaseCallType type, final String[] users, final Map<String, Object> ext) {} //for example Map<String, Object> ext = new HashMap<>(); ext.put("groupId", groupId); EaseCallKit.getInstance().startInviteMultipleCall(callType, userIds, ext);
Once a call invitaion is sent, the callee receives the invitation in the onReceivedCall
callback.
/**
* Occurs when a call invitation is received.
* @param callType The call type.
* @param fromUserId The user ID of the caller.
* @param ext The extension information in the call invitation. Set it as null if you do not need this information.
*/
void onReceivedCall(EaseCallType callType, String fromUserId, JSONObject ext);
If the callee is online and available for a call, you can pop out a user interface that allows the callee to accept or decline the invitation. Refer to the following screenshot to implement the interface:
In call sessions with multiple users, these users can also send call invitations to other users. After sending the invitation, the SDK triggers the onInviteUsers
callback in EaseCallKitListener
on the sender's client.
/**
* Occurs when the local user sends a call invitation during a group call.
* @param callType The call type.
* @param existMembers The current members of the group call, excluding the local user.
* @param ext The extension information in the call invitation. Set it as null if you do not need this information.
*/
void onInviteUsers(EaseCallType callType, String[] existMembers, JSONObject ext);
Refer to io.agora.chatdemo.group.fragments.MultiplyVideoSelectMemberChildFragment
in the sample project for the user interface of the call invitation.
When a remote user joins the call, all the other users in the call receive the onRemoteUserJoinChannel
callback. You need to look up the Agora Chat user ID corresponding to the Agora UID in you app server.
- If you find the Agora Chat user ID, construct the user ID to an
EaseUserAccount
object and return it to the app using thecallback
parameter inonRemoteUserJoinChannel
. For thecallback
parameter, implementonUserAccount
inEaseCallGetUserAccountCallback
. - If you fail to find the Agora Chat user ID, report the error code and descriptions using the
onSetUserAccountError
callback in theEaseCallGetYserAccountCallback
class.
/**
* Occurs when the remote user joins the channel.
*
* @param channelName The channel name.
* @param userName The Agora Chat user ID.
* @param uid The Agora UID.
* @param callback The callback object.
*/
void onRemoteUserJoinChannel(String channelName, String userName, int uid, EaseCallGetUserAccountCallback callback);
A one-to-one call ends as soon as one of the two users hangs up, while a group call ends only after the local user hangs up. When the call ends, the SDK triggers the onEndCallWithReason
callback.
/**
* Occurs when a call ends.
* @param callType The call type.
* @param channelName The channel name.
* @param reason The reason why the call ends.
* @param callTime The call duration.
*/
void onEndCallWithReason(EaseCallType callType, String channelName, EaseCallEndReason reason, long callTime);
// The reasons for a call ending.
public enum EaseCallEndReason {
EaseCallEndReasonHangup(0), // One of the call members hangs up.
EaseCallEndReasonCancel(1), // The local user cancels the call.
EaseCallEndReasonRemoteCancel(2), // The remote user cancels the call.
EaseCallEndReasonRefuse(3),// The remote user rejects the call.
EaseCallEndReasonBusy(4), // The remote user is busy.
EaseCallEndReasonNoResponse(5), // The local user did not answer the phone.
EaseCallEndReasonRemoteNoResponse(6), // The remote user did not answer the phone.
EaseCallEndReasonHandleOnOtherDeviceRefused(7),// The call is rejected on another device.
EaseCallEndReasonHandleOnOtherDeviceAgreed; // The call is answered on another device.
....
}
This section contains extra steps you can take for the audio and video call functionalities in your project.
If exceptions or errors occur during a call, the SDK triggers the onCallError
callback in the EaseCallKitListener
class, which reports the detailed information of the exception in AggoraChatCallError
.
/**
* Reports call exceptions.
* @param type The error type.
* @param errorCode The error code.
* @param description The error description.
*/
void onCallError(EaseCallError type, int errorCode, String description);
Types of call errors are as follows:
public enum EaseCallError {
// The process error.
PROCESS_ERROR,
// The RTC service error.
RTC_ERROR,
// The IM service error.
IM_ERROR
}
After initializing the AgoraChatCallKit, you can refer to the following sample code to update the configuration of the call kit:
/**
* Gets the current call kit configuration.
*
* @return The current call kit configuration.
*/
public EaseCallKitConfig getCallKitConfig();
// Sets the default avatar.
EaseCallKitConfig config = EaseCallKit.getInstance().getCallKitConfig();
if(config != null){
String Image = EaseFileUtils.getModelFilePath(context,"bryant.png"……);
callKitConfig.setDefaultHeadImage(Image);
}
When changes to the UI or the channel state occur, for example, when a new user joins the channel, onUserInfoUpdated
is triggered to notify the app to update the UI.
After a user updates the user information, call io.agora.chat.callkit.general.EaseCallKitConfig#setUserInfo
to set the modified user information. Ensure that this method is implemented in a synchronous function so that the UI is updated timely.
/**
* \~chinese
* Occurs when the user information is updated.
* @param userName The Agora Chat user ID.
*/
void onUserInfoUpdate(String userName){
// For example,
/**
EaseUser user = mUsersManager.getUserInfo(userName);
EaseCallUserInfo userInfo = new EaseCallUserInfo();
if (user != null) {
userInfo.setNickName(user.getNickname());
userInfo.setHeadImage(user.getAvatar());
}
EaseCallKit.getInstance().getCallKitConfig().setUserInfo(userName, userInfo);
*/
}
To enhance communication security, Agora recommends that you authenticate app users with the RTC token before they join a call. To do this, you need to make sure that the Primary Certificate of your project is enabled, and setEnableRTCToken
in the AgoraChatCallKit is set to true
.
EaseCallKitConfig callKitConfig = new EaseCallKitConfig();
……
callKitConfig.setEnableRTCToken(true);
……
EaseCallKit.getInstance().init(context, callKitConfig);
Once you enable token authentication, the SDK triggers the onGenerateRTCToken
callback. You need to retrieve an RTC token in this callback following the steps:
- Retrieve the RTC token and Agora UID from your app server.
- Trigger
onSetToken
to pass the token and UID to the callback object. - AgoraChatCallKit uses the token and UID to join the channel.
Tokens are generated on your app server using the token generator provided by Agora. For how to generate a token on the server and retrieve and renew the token on the client, see Authenticate Your Users with Tokens.
/**
* Occurs when RTC token authentication is enabled.
*
* @param userId The Agora Chat user ID of the current user.
* @param channelName The channel name.
* @param callback The callback object.
*/
default void onGenerateRTCToken(String userId, String channelName, EaseCallKitTokenCallback callback) {
// Pass the token and UID to the callback object.
// callback.onSetToken(token, uid);
}
In scenarios where the app runs on the background or goes offline, use push notifications to ensure that the callee receives the call invitation. To enable push notifications, see Set up push notifications.
Once push notifications are enabled, when a call invitation arrives, a notification message pops out on the notification panel. Users can click the message to see the call invitation.
This section provides other reference information that you can refer to when implementing real-time audio and video communications functionalities.
The AgoraChatCallKit provides the following APIs:
Method | Description |
---|---|
init | Initializes AgoraChatCallKit. |
setCallKitListener | Sets the event listener of the call kit. |
startSingleCall | Starts a one-to-one call. |
startInviteMultipleCall | Starts a group call. |
getCallKitConfig | Retrieves the configurations of AgoraChatCallKit. |
registerVideoCallClass | Registers a one-to-one video call class. |
registerMultipleVideoClass | Registers a group video call class. |
EaseCallKitListener
provides the following callback events:
Event | Description |
---|---|
onEndCallWithReason | Occurs when the call ends. |
onInviteUsers | Occurs when a member of the group call invites other users to the call. |
onReceivedCall | Occurs when the call invitation is received and the device rings. |
onGenerateToken | Requests the RTC token. You need to pass the token to AgoraChatCallKit with callbacks. |
onCallError | Reports exceptions and errors during the call. |
onInviteCallMessageSent | Occurs when the call invitation is sent. |
onRemoteUserJoinChannel | Occurs when a remote user joins the call. |
onUserInfoUpdated | Occurs when the user information is updated. This callback is triggered when changes occur to the UI or the channel state in the AgoraChatCallKit. |
EaseCallGetUserAccountCallback
contains the following APIs:
Event | Description |
---|---|
onUserAccount | Occurs when the Agora Chat user ID correspondting to the Agora UID is retrieved. |
onSetUserAccountError | Occurs when the app fails to retrieve the user account. |
EaseCallKitTokenCallback
contains the following APIs:
Event | Description |
---|---|
onSetToken | Occurs when the app passes the retrieved RTC token to the AgoraChatCallKit. |
onGetTokenError | Occurs when the app fails to get the RTC token. |