实现语聊房
本文介绍如何实现语聊房,包含登录系统、初始化引擎、创建房间、麦位管理、退出房间。
示例项目
声网在 agora-ent-scenarios
仓库中提供实现语聊房的源代码供你参考。
业务流程
本节展示语聊房中常见的业务流程。
进出房间
下图展示创建、进入、退出房间的流程。
房主邀请听众上麦
下图展示房主邀请听众上麦的流程。在这个流程中,房主发起上麦邀请,如果听众接受邀请,房主会收到通知。听众上麦并修改麦位,然后发布自己的音频流。
听众申请上麦
下图展示听众向房主申请上麦的流程。在这个流程中,听众主动发起上麦申请,如果房主接受申请,房主修改麦位信息以让听众上麦。听众收到上麦消息后,发布自己的音频流。
准备开发环境
前提条件
开始前,请确保你的开发环境满足如下要求:
- Android Studio 3.5 及以上。
- Android 手机,版本 Android 5.0(API Level 21)及以上。
- 可以访问互联网的计算机。确保你的网络环境没有部署防火墙,否则无法正常使用声网服务。
- 参考开通服务创建声网开发者账号和声网项目,并获取项目的 App ID 和临时 Token,以及登录即时通讯系统所需的用户名 (ID) 和 Token。
集成 SDK
声动语聊用到声网实时互动 (RTC) SDK 和即时通讯 (IM) SDK。本节介绍如何在 Android Studio 创建项目并集成这两个 SDK:
-
如需创建新项目,在 Android Studio 里,依次选择 Phone and Tablet > Empty Activity,创建 Android 项目。
信息创建项目后,Android Studio 会自动开始同步 gradle,稍等片刻至同步成功后再进行下一步操作。
-
使用 Maven Central 将声网 RTC SDK 和 IM SDK 集成到你的项目中。
-
在
/Gradle Scripts/build.gradle(Project: <projectname>)
文件中添加如下代码,添加 Maven Central 依赖:Groovybuildscript {
repositories {
...
mavenCentral()
}
...
}
allprojects {
repositories {
...
mavenCentral()
}
}信息如果你的 Android 项目设置了 dependencyResolutionManagement,添加 Maven Central 依赖的方式可能存在差异。
-
在
/Gradle Scripts/build.gradle(Module: <projectname>.app)
文件中添加如下代码,将声网 RTC SDK 和 IM SDK 集成到你的 Android 项目中:Groovy...
dependencies {
...
// x.y.z,请填写具体的 SDK 版本号,如:4.0.0 或 4.1.0-1
// 通过实时互动产品发版说明获取最新版本号
implementation 'io.agora.rtc:full-sdk:x.y.z'
// 指定 IM SDK 1.1.0 版
implementation 'io.agora.rtc:chat-sdk:1.1.0'
}
-
-
添加网络及设备权限。
在
/app/Manifests/AndroidManifest.xml
文件中,在</application>
后面添加如下权限:XML<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.BLUETOOTH"/>
<!-- 对于 Android 12.0 及以上且集成 v4.1.0 以下声网 RTC SDK 的设备,还需要添加以下权限 -->
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT"/>
<!-- 对于 Android 12.0 及以上设备,还需要添加以下权限 -->
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="android.permission.BLUETOOTH_SCAN"/> -
在
/Gradle Scripts/proguard-rules.pro
文件中添加如下行,以防止声网 SDK 的代码被混淆:Kotlin-keep class io.agora.**{*;}
-dontwarn javax.**
-dontwarn com.google.devtools.build.android.**
实现语聊房
你需要声网 RTC SDK、IM SDK 和云服务 (Service) 共同搭建语聊房场景。其中:
- 实时互动 RTC SDK 承担实时音频的业务。
- 即时通讯 IM SDK 实现房间内的信令通信。
- 云服务 (Service) 实现了房间列表的存储和房间生命周期的管理。
本节会详细介绍如何调用声网云服务(voiceServiceProtocol
)、IM SDK 和 RTC SDK 的 API 完成登录即时通讯系统、获取房间列表、创建房间、进入房间、加入 RTC 房间、离开 RTC 房间等关键逻辑。完整的调用时序可以参考 API 时序图。
声网云服务为内部自研服务,暂不对外提供。你可以调用声网云服务的 API 用于测试,但是对于正式环境,声网建议你参考文档自行实现相似的一套服务。如需协助,请联系技术支持。
1. 获取房间列表
调用声网云服务中 voiceServiceProtocol
类的 fetchRoomList
方法获取房间列表。获取到房间列表后刷新 UI 并将房间列表展示在界面上。
voiceServiceProtocol.fetchRoomList(page, completion = { error, result ->
...
})
2. 登录即时通讯系统
参考如下步骤登录即时通讯 (IM) 系统:
- 根据前提条件开启声网即时通讯服务,并获取登录即时通讯系统所需的用户名 (ID) 和 Token。
- 调用声网即时通讯 (IM) SDK 中
ChatClient
类的loginWithToken
方法并传入即时通讯服务的用户名和 Token 以登录即时通讯系统。
public void login(String uid,String token,CallBack callBack){
ChatClient.getInstance().loginWithToken(uid, token, new CallBack() {
@Override
public void onSuccess() {
ThreadManager.getInstance().runOnMainThread(new Runnable() {
@Override
public void run() {
callBack.onSuccess();
}
});
LogTools.d("ChatroomConfigManager","Login success");
}
@Override
public void onError(int code, String msg) {
ThreadManager.getInstance().runOnMainThread(new Runnable() {
@Override
public void run() {
callBack.onError(code,msg);
}
});
LogTools.e("ChatroomConfigManager", "Login onError code:" + code + " desc: " + msg);
}
});
}
3. 初始化 RtcEngine
参考如下步骤初始化 RtcEngine
:
// 初始化配置
val config = RtcEngineConfig()
// 设置 App ID
config.mAppId = "YourAppId"
// 创建 RtcEngine 实例
val rtcEngine = RtcEngineEx.create(config) as RtcEngineEx
4. 创建并进入房间
参考如下步骤创建并进入房间:
-
调用
voiceServiceProtocol
对象中的createRoom
方法创建一个房间。Kotlinval voiceCreateRoomModel = VoiceCreateRoomModel(
roomName = roomName,
soundEffect = soundEffect,
isPrivate = !TextUtils.isEmpty(password),
password = password ?: "",
roomType = roomType
)
voiceServiceProtocol.createRoom(voiceCreateRoomModel, completion = { error, result ->
when (error) {
VoiceServiceProtocol.ERR_OK -> {
callBack.onSuccess(createLiveData(result))
}
VoiceServiceProtocol.ERR_ROOM_NAME_INCORRECT -> {
callBack.onError(error, "")
}
else -> {
callBack.onError(error, "")
}
}
}) -
调用
voiceServiceProtocol
对象的joinRoom
方法进入房间。KotlinvoiceServiceProtocol.joinRoom(roomId, completion = { error, result ->
when (error) {
VoiceServiceProtocol.ERR_OK -> {
callBack.onSuccess(createLiveData(result))
}
VoiceServiceProtocol.ERR_ROOM_UNAVAILABLE -> {
callBack.onError(error, "room is not existent")
}
else -> {
callBack.onError(error, "")
}
}
}) -
语聊房里需要有消息聊天和语音聊天,因此你还需进行如下操作:
-
调用声网 IM SDK 中
joinChatRoom
实现房间内的消息互动。方法中的参数含义和取值请参考joinChatRoom
。Kotlin// 实现房间内的消息互动
public void joinRoom(String chatroomId, ValueCallBack<ChatRoom> callBack){
ChatClient.getInstance().chatroomManager()
.joinChatRoom(chatroomId, new ValueCallBack<ChatRoom>() {
@Override
public void onSuccess(ChatRoom value) {
ThreadManager.getInstance().runOnMainThreadDelay(new Runnable() {
@Override
public void run() {
callBack.onSuccess(value);
}
},200);
}
@Override
public void onError(int error, String errorMsg) {
ThreadManager.getInstance().runOnMainThread(new Runnable() {
@Override
public void run() {
callBack.onError(error,errorMsg);
}
});
}
});
} -
调用声网 RTC SDK 中
RtcEngine
类的joinChannel
加入 RTC 频道以实现房间内的实时音频通话。方法中的参数含义和支持取值请参考joinChannel
。在这一步里需要填写声网 RTC Token。你可以使用开通服务中获取的临时 Token,也可以参考使用 Token 鉴权获取正式用途的声网 RTC Token。临时 Token 的有效期为 24 小时,建议你仅在测试用途下使用。你还可以调用
setChannelProfile
、setAudioProfile
、setAudioScenario
、setParameters
来为不同业务场景(语聊社交、KTV、游戏陪玩、专业音频直播场景)设置语聊房的最佳音效。Kotlin// 实现房间内的语音互动
rtcEngine?.apply {
when (soundEffect) {
// 在线 K 歌房和泛娱乐社交场景下推荐设置
ConfigConstants.SoundSelection.Social_Chat,
ConfigConstants.SoundSelection.Karaoke -> {
// 设置频道属性为直播
setChannelProfile(Constants.CHANNEL_PROFILE_LIVE_BROADCASTING)
// 设置 48 kHz 采样率,音乐编码,单声道,编码码率最大值为 96 Kbps
setAudioProfile(Constants.AUDIO_PROFILE_MUSIC_HIGH_QUALITY)
// 设置为高音质场景
setAudioScenario(Constants.AUDIO_SCENARIO_GAME_STREAMING)
}
// 1 对 1 游戏陪玩通话场景下推荐
ConfigConstants.SoundSelection.Gaming_Buddy -> {
// 设置频道属性为通信
setChannelProfile(Constants.CHANNEL_PROFILE_COMMUNICATION)
}
else -> {
// 专业音频直播场景下推荐设置
// 设置频道属性为直播
setChannelProfile(Constants.CHANNEL_PROFILE_LIVE_BROADCASTING)
// 指定 48 kHz 采样率,音乐编码,双声道,编码码率最大值为 128 Kbps
setAudioProfile(Constants.AUDIO_PROFILE_MUSIC_HIGH_QUALITY)
// 设置为高音质场景
setAudioScenario(Constants.AUDIO_SCENARIO_GAME_STREAMING)
// 设置私有参数以获得好的实时音频互动体验
setParameters("{\"che.audio.custom_payload_type\":73}")
setParameters("{\"che.audio.custom_bitrate\":128000}")
setParameters("{\"che.audio.input_channels\":2}")
}
}
}
// 加入 RTC 频道
// 此处的 Token 为声网 RTC Token
val status = rtcEngine?.joinChannel(VoiceBuddyFactory.get().getVoiceBuddy().rtcToken(), channelId, "", rtcUid)
-
5. 麦位管理
具体步骤详见麦位管理。
6. 退出房间
参考如下步骤退出并销毁语聊房。
-
调用
voiceServiceProtocol
对象的leaveRoom
方法离开房间。KotlinvoiceServiceProtocol.leaveRoom(roomId, isRoomOwnerLeave, completion = { error, result ->
...
}) -
调用
RtcEngine
类的leaveChannel
方法离开 RTC 频道。KotlinrtcEngine?.leaveChannel()
-
调用
leaveChatRoom
离开聊天室,调用asyncDestroyChatRoom
销毁聊天室。调用destroy
销毁 RTC 引擎。KotlinChatroomIMManager.getInstance().leaveChatRoom(roomKitBean.chatroomId)
ChatroomIMManager.getInstance().asyncDestroyChatRoom(roomKitBean.chatroomId, object :
CallBack {
override fun onSuccess() {}
override fun onError(code: Int, error: String?) {}
})
RtcEngineEx.destroy()
rtcEngine = null
API 时序图
如下时序图展示了如何登录即时通讯系统、获取房间列表、创建房间、进入房间、加入 RTC 频道、麦位管理、退出房间、离开 RTC 频道。