本文介绍如何实现语聊房。
声网在 agora-ent-scenarios 仓库中提供语聊房(普通版)源代码供你参考。
本节展示语聊房中常见的业务流程。
下图展示创建、进入、退出房间的流程。
下图展示房主邀请听众上麦的流程。在这个流程中,房主发起上麦邀请,如果听众接受邀请,房主会收到通知。听众上麦并修改麦位,然后发布自己的音频流。
下图展示听众向房主申请上麦的流程。在这个流程中,听众主动发起上麦申请,如果房主接受申请,房主修改麦位信息以让听众上麦。听众收到上麦消息后,发布自己的音频流。
声动语聊用到声网 RTC SDK 和即时通讯(IM)SDK。本节介绍如何在 Android Studio 创建项目并集成这两个 SDK:
如需创建新项目,在 Android Studio 里,依次选择 Phone and Tablet > Empty Activity,创建 Android 项目。
使用 Maven Central 将声网 RTC SDK 和 IM SDK 集成到你的项目中。
a. 在 /Gradle Scripts/build.gradle(Project: <projectname>)
文件中添加如下代码,添加 Maven Central 依赖:
buildscript {
repositories {
...
mavenCentral()
}
...
}
allprojects {
repositories {
...
mavenCentral()
}
}
b. 在 /Gradle Scripts/build.gradle(Module: <projectname>.app)
文件中添加如下代码,将声网 RTC SDK 和 IM SDK 集成到你的 Android 项目中:
...
dependencies {
...
// x.y.z,请填写具体的 RTC SDK 版本号,如:4.0.0 或 4.1.0-1
// 通过互动直播产品发版说明获取最新版本号
implementation 'io.agora.rtc:full-sdk:x.y.z'
// x.y.z,请填写具体的 IM SDK 版本号,如:1.1.0。
// 通过即时通讯产品发版说明获取最新版本号
implementation 'io.agora.rtc:chat-sdk:x.y.z'
}
添加网络及设备权限。
在 /app/Manifests/AndroidManifest.xml
文件中,在 </application>
后面添加如下权限:
<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 的代码被混淆:
-keep class io.agora.**{*;}
-dontwarn javax.**
-dontwarn com.google.devtools.build.android.**
如下时序图展示了如何登录即时通讯系统、获取房间列表、创建房间、进入房间、加入 RTC 频道、麦位管理、退出房间、离开 RTC 频道。声网云服务(Service)实现了房间列表的存储和房间生命周期的管理,声网即时通讯(IM)SDK 实现房间内的信令通信,声网 RTC SDK 承担实时音频的业务。本节会详细介绍如何调用声网云服务(voiceServiceProtocol
)、IM SDK API、RTC SDK API 完成这些逻辑。
调用声网云服务中 voiceServiceProtocol
类的 fetchRoomList
方法获取房间列表。获取到房间列表后刷新 UI 并将房间列表展示在界面上。
voiceServiceProtocol.fetchRoomList(page, completion = { error, result ->
...
})
参考如下步骤登录即时通讯(IM)系统:
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);
}
});
}
参考如下步骤初始化 RtcEngine:
// 初始化配置
val config = RtcEngineConfig()
// 设置 App ID
config.mAppId = "YourAppId"
// 创建 RtcEngine 实例
val rtcEngine = RtcEngineEx.create(config) as RtcEngineEx
调用 voiceServiceProtocol
对象中的 createRoom
方法创建一个房间。
val 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
方法进入房间。
voiceServiceProtocol.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
。
// 实现房间内的消息互动
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。你可以参考开始使用声网平台从声网控制台获得临时用途的声网 RTC Token。你也可以参考使用 Token 鉴权获取正式用途的声网 RTC Token。临时 Token 的有效期为 24 小时,建议你仅在测试用途下使用。
你还可以调用 setChannelProfile
、setAudioProfile
、setAudioScenario
、setParameters
来为不同业务场景(语聊社交、KTV、游戏陪玩、专业音频直播场景)设置语聊房的最佳音效。
// 实现房间内的语音互动
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)
具体步骤详见麦位管理。
调用 voiceServiceProtocol
对象的 leaveRoom
方法离开房间。
voiceServiceProtocol.leaveRoom(roomId, isRoomOwnerLeave, completion = { error, result ->
...
})
调用 RtcEngine
类的 leaveChannel
方法离开 RTC 频道。
rtcEngine?.leaveChannel()
调用 leaveChatRoom
离开聊天室,调用 asyncDestroyChatRoom
销毁聊天室。调用 destroy
销毁 RTC 引擎。
ChatroomIMManager.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