Real-time voice chatting immerses people in the sights and sounds of human connections, keeping them engaged in your app longer.
This page shows the minimum code you need to integrate high-quality, low-latency Voice Call function into your app using the SDK.
The following figure shows the workflow you need to integrate into your app in order to achieve Voice Call functionality.
To start voice call, implement the following steps in your app:
1. Set the role
Set both app clients as the host.
2. Join a channel
Call joinChannel
to create and join a channel. When using the same App ID, users who pass in the same channel name enter the same channel.
3 and 4. Publish and subscribe to audio in the channel
After joining a channel, both hosts can publish audio stream to the channel and subscribe to each other.
In order to create the environment necessary to integrate Voice Call into your app, do the following:
See Create a C++ console app project to create a C++ console app on Visual Studio.
Follow these steps to integrate the Agora SDK into your project.
Right-click the project name in the Solution Explorer window, click Properties to configure the following project properties, and click OK.
Go to the C/C++ > General > Additional Include Directories menu, click Edit, and input $(SolutionDir)include in the pop-up window.
Go to the Linker > General > Additional Library Directories menu, click Edit, and input $(SolutionDir) in the pop-up window.
Go to the Linker > Input > Additional Dependencies menu, click Edit, and input agora_rtc_sdk.dll.lib in the pop-up window.
The following figure shows the API call sequence of the voice call.
Create the UI
Create the user interface (UI) for the voice call in your project. Skip to Initialize IRtcEngine if you already have an UI in your project.
If you are implementing the voice call, we recommend adding the following element into the UI:
Refer to the following interface:
Initialize IRtcEngine
Create and initialize the IRtcEngine
object before calling any other Agora APIs.
Call the createAgoraRtcEngine
method and the initialize
method, and pass in the App ID to initialize the IRtcEngine
object.
You can also listen for callback events, such as when the local user joins or leaves the channel.
// Create Rtc engine.
m_lpAgoraEngine = createAgoraRtcEngine();
RtcEngineContext ctx;
// Add the register events and callbacks.
ctx.eventHandler = &m_engineEventHandler;
// Input your App ID.Fill the App ID of your project generated on Agora Console.
ctx.appId = "Your App ID";
// Initialize the IRtcEngine object.
m_lpAgoraEngine->initialize(ctx);
// Inherit the events and callbacks of IRtcEngineEventHandler.
class CAGEngineEventHandler :
public IRtcEngineEventHandler
{
public:
CAGEngineEventHandler();
~CAGEngineEventHandler();
void setMainWnd(HWND wnd);
HWND GetMsgReceiver() {return m_hMainWnd;};
// Listen for the onJoinChannelSuccess callback.
// This callback occurs when the local user successfully joins the channel.
virtual void onJoinChannelSuccess(const char* channel, uid_t uid, int elapsed);
// Listen for the onLeaveChannel callback.
// This callback occurs when the local user successfully leaves the channel.
virtual void onLeaveChannel(const RtcStats& stat);
// Listen for the onUserJoined callback.
// This callback occurs when the remote host successfully joins the channel.
// After receiving this callback, immediately call setupRemoteVideo to set the remote video view.
virtual void onUserJoined(uid_t uid, int elapsed) override;
// Listen for the onUserOffline callback.
// This callback occurs when the remote host leaves the channel or drops offline.
virtual void onUserOffline(uid_t uid, USER_OFFLINE_REASON_TYPE reason);
private:
HWND m_hMainWnd;
};
Join the channel
Set channel profile and client role and join the channel by a temp token.
ChannelMediaOptions options;
// For a voice call scenario, set the channel profile as BROADCASTING.
options.channelProfile = CHANNEL_PROFILE_LIVE_BROADCASTING;
// Shut down the camera
options.publishCameraTrack = false;
// Set both clients as the BROADCASTER.
options.clientRoleType = CLIENT_ROLE_BROADCASTER;
// Join channel with a temp token that you generate on Agora Console.
BOOL CAgoraObject::JoinChannel("Your token", LPCTSTR lpChannelName, 0, options)
{
int nRet = 0;
LPCSTR lpStreamInfo = "{\"owner\":true,\"width\":640,\"height\":480,\"bitrate\":500}";
#ifdef UNICODE
CHAR szChannelName[128];
::WideCharToMultiByte(CP_ACP, 0, lpChannelName, -1, szChannelName, 128, NULL, NULL);
if (nRet == 0)
m_strChannelName = lpChannelName;
return nRet == 0 ? TRUE : FALSE;
}
void CLiveBroadcastingDlg::OnBnClickedButtonJoinchannel()
{
if (!m_rtcEngine || !m_initialize)
return;
CString strInfo;
if (!m_joinChannel) {
CString strChannelName;
m_edtChannelName.GetWindowText(strChannelName);
if (strChannelName.IsEmpty()) {
AfxMessageBox(_T("Fill channel name first"));
return;
}
ChannelMediaOptions options;
// Set the channel profile as BROADCASTING.
options.channelProfile = CHANNEL_PROFILE_LIVE_BROADCASTING;
// Set the client role as BROADCASTER.
options.clientRoleType = CLIENT_ROLE_TYPE(m_cmbRole.GetCurSel() + 1);
options.autoSubscribeAudio = true;
// Join channel with a temp token that you generate on Agora Console.
if (0 == m_rtcEngine->joinChannel(APP_TOKEN, szChannelId.c_str(), 0, options)) {
strInfo.Format(_T("join channel %s, use ChannelMediaOptions"), getCurrentTime());
m_btnJoinChannel.EnableWindow(FALSE);
}
}
else {
if (0 == m_rtcEngine->leaveChannel()) {
strInfo.Format(_T("leave channel %s"), getCurrentTime());
m_btnJoinChannel.EnableWindow(FALSE);
}
}
m_lstInfo.InsertString(m_lstInfo.GetCount(), strInfo);
}
Leave the channel
Call the leaveChannel
method to leave the current channel according to your scenario, for example, when the voice call ends, when you need to close the app, or when your app runs in the background.
void CLiveBroadcastingDlg::UnInitAgora()
{
if (m_rtcEngine) {
if(m_joinChannel)
// Leave the current channel.
m_rtcEngine->leaveChannel();
m_lstInfo.InsertString(m_lstInfo.GetCount(), _T("leaveChannel"));
// Release the IRtcEngine object.
m_rtcEngine->release(true);
m_lstInfo.InsertString(m_lstInfo.GetCount(), _T("release rtc engine"));
m_rtcEngine = NULL;
}
}
In a test or production environment, use a token server to generate token is recommended to ensure communication security, see Authenticate Your Users with Tokens for details.