语音房养成记 5 - 根据我们的 "语音房" 需求, 对 [声网] 客户端API做功能划分整理


前言

前期调研结束, 结合我们的 "语音房” 的需求, 对 [声网] 客户端API做功能划分整理.

主要分类有 :  创建声网SDK对象 /  加入频道前设置参数 /  声网角色设置&更新token /  加入频道&离开频道 /  打开&关闭 本地扬声器 “静音”   /  在onActivityResumed时,需要做音频路由校正 /  本地麦克风静音 /  实现背景音乐功能 /  跨房PK功能 /  IRtcEngineEventHandler(重要的声网异步回调)


文档地址

声网 : https://docs.agora.io/cn/live-streaming-premium-legacy/API%20Reference/java/classio_1_1agora_1_1rtc_1_1_rtc_engine.html#a8bbeb8a8b07e4e7b1a0a493f1c66998d


所使用的SDK版本(以写文档时使用的SDK版本为准) :

声网 : 3.7.2.1


声网核心API


// ————————— 创建声网SDK对象 ——————————

// 设置初始化方法,没有设置logconfig 默认log地址:
// /storage/emulated/0/Android/data/<package name>/files/agorasdk.log
// TODO : 目前 Agora RTC Native SDK 只支持每个 app 创建一个 RtcEngine 实例。
/**
 * context    : 安卓活动 (Android Activity) 的上下文。
 * appId    : Agora 为 app 开发者签发的 App ID,详见获取 App ID。
 *            使用同一个 App ID 的 app 才能进入同一个频道进行通话或直播。
 *            一个 App ID 只能用于创建一个 RtcEngine。如需更换 App ID,
 *            必须先调用 destroy 销毁当前 RtcEngine,并在 destroy 成功返回后,
 *            再调用 create 重新创建 RtcEngine。
 * handler    : io.agora.rtc.IRtcEngineEventHandler 是一个提供了缺省实现的抽象类,
 *            SDK 通过该抽象类向 app 报告 SDK 运行时的各种事件
 */
// Java

RtcEngineConfig.LogConfig logConfig = new RtcEngineConfig.LogConfig();
// TODO : 不要修改声网日志路径和名字, 否则声网无法在用户在频道期间在线拉取了...
logConfig.level = Constants.LogLevel.getValue(Constants.LogLevel.LOG_LEVEL_INFO);
logConfig.fileSize = 1024 * 4;// TODO : 单位 : K

RtcEngineConfig config = new RtcEngineConfig();
config.mAppId = agoraRtcAppKey;
config.mEventHandler = new MyRtcEngineEventHandler(vcrSdk, handler);
config.mContext = context.getApplicationContext();
config.mLogConfig = logConfig;
rtcEngine = RtcEngine.create(config);



// ————————— 加入频道前设置参数 ——————————

 /**
 * 关闭视频模块。
 *
 * 该方法用于关闭视频。可以在加入频道前或者通话中调用,在加入频道前调用,则自动开启纯音频模式,
 * 在通话中调用则由视频模式切换为纯音频频模式。调用 enableVideo 方法可开启视频模式。
 *
 * 成功调用该方法后,远端会触发 onUserEnableVideo(false) 回调。
 *
 * 注解
 * 该方法设置的是内部引擎为禁用状态,在频道内和频道外均可调用,且在 leaveChannel 后仍然有效。
 * 该方法重置整个引擎,响应速度较慢,因此 Agora 建议使用如下方法来控制视频模块:
 * enableLocalVideo:是否启动摄像头采集并创建本地视频流
 * muteLocalVideoStream:是否发布本地视频流
 * muteRemoteVideoStream:是否接收并播放远端视频流
 * muteAllRemoteVideoStreams:是否接收并播放所有远端视频流
 * 返回
 * 0: 方法调用成功。
 * < 0: 方法调用失败。
 */
rtcEngine.disableVideo();

/**
 * 初始化结束后,调用 setChannelProfile 方法,将频道场景设为直播。
 * 注意 : 一个 RtcEngine 只能使用一种频道场景。如果想切换为其他场景,需要先调用 destroy 方法
 * 释放当前的 RtcEngine 实例,然后使用 create 方法创建一个新实例,再调用 setChannelProfile
 * 设置新的频道场景。
 */
/**
 * 设置频道场景。
 *
 * SDK 初始化后默认的频道场景为通信场景,你可以调用该方法设置 Agora 频道的使用场景。
 * Agora SDK 会针对不同的使用场景采用不同的优化策略,如通信场景偏好流畅,直播场景偏好画质。
 *
 * 注解
 * 为保证实时音视频质量,我们建议相同频道内的用户必须使用同一种频道场景。
 * 该方法必须在加入频道前调用,进入频道后无法再设置频道模式。
 * 不同的频道场景下,SDK 的默认音频路由和默认视频编码码率是不同的,
 * 详见 setDefaultAudioRoutetoSpeakerphone 和 setVideoEncoderConfiguration 中的说明。
 * 参数
 * profile    频道使用场景:
 * CHANNEL_PROFILE_COMMUNICATION(0):通信场景。该场景下,频道内所有用户都可以发布和接收音、视频流。适用于语音通话、视频群聊等应用场景。
 * CHANNEL_PROFILE_LIVE_BROADCASTING(1):直播场景。该场景有主播和观众两种用户角色,可以通过 setClientRole 设置。主播可以发布和接收音视频流,观众直接接收流。适用于语聊房、视频直播、互动大班课等应用场景。
 * CHANNEL_PROFILE_GAME(2):Agora 不推荐使用。setParameters("{\"che.audio.opensl\":false }");
 * 返回
 * 0(ERR_OK): 方法调用成功。
 * < 0: 方法调用失败。
 * -2(ERR_INVALID_ARGUMENT): 参数无效。
 * -7(ERR_NOT_INITIALIZED): SDK 尚未初始化。
 */
rtcEngine.setChannelProfile(Constants.CHANNEL_PROFILE_LIVE_BROADCASTING);


/**
 * 3.1.3. 组合3:极简主义,适用于不频繁上下麦的纯音频场景
 *
 * Default模式:观众/单主播使用媒体音量(软件3A),主播连麦使用通话音量(硬件3A)。
 * ● 优点:音频码率低、最大程度降低主播客户端网络对音质、流畅度的影响;
 * ● 缺点:上下麦有卡顿(适合不频繁上下麦的纯音频场景),唱歌的话对伴奏有抑制
 * MusicStandard模式:48kHz采样率,单声道语音编码,编码码率最大值为56Kbps。
 */
/**
 * 设置音频编码配置。
 *
 * 注解
 * 该方法需要在 joinChannel 之前设置好,joinChannel 后设置不生效。
 * 通信和直播场景下,音质(码率)会有网络自适应的调整,通过该方法设置的是一个最高码率。
 * 在有高音质需求的场景(例如音乐教学场景)中,建议将 profile 设置为 MUSIC_HIGH_QUALITY (4),Scenario 设置为 GAME_STREAMING (3)。
 * 参数
 * profile    设置采样率,码率,编码模式和声道数,详见 AudioProfile。
 * scenario    设置音频应用场景,详见 AudioScenario。不同的音频场景下,设备的音量类型不同。详见如何区分媒体音量和通话音量。
 */
rtcEngine.setAudioProfile(Constants.AUDIO_PROFILE_MUSIC_HIGH_QUALITY, Constants.AUDIO_SCENARIO_GAME_STREAMING);


/**
 * 启用用户音量提示。
 *
 * 该方法允许 SDK 定期向 app 报告本地发流用户和瞬时音量最高的远端用户(最多 3 位)的音量相关信息。
 * 启用该方法后,只要频道内有发流用户,SDK 会在加入频道后按设置的时间间隔触发 onAudioVolumeIndication 回调。
 *
 * 参数
 * interval    指定音量提示的时间间隔:
 *      ≤ 0:禁用音量提示功能。
 *      > 0:返回音量提示的间隔,单位为毫秒。建议设置到大于 200 毫秒。最小不得少于 10 毫秒,否则会收不到 onAudioVolumeIndication 回调。
 * smooth    平滑系数,指定音量提示的灵敏度。取值范围为 [0, 10],建议值为 3,数字越大,波动越灵敏;数字越小,波动越平滑。
 * report_vad    是否开启人声检测
 *      true: 开启本地人声检测功能。开启后,onAudioVolumeIndication 回调的 vad 参数会报告是否在本地检测到人声。
 *      false: (默认)关闭本地人声检测功能。除引擎自动进行本地人声检测的场景外,onAudioVolumeIndication 回调的 vad 参数不会报告是否在本地检测到人声。
 * 返回
 *      0: 方法调用成功。
 *      < 0: 方法调用失败。
 *
 *
 * 实测发现enableAudioVolumeIndication   interval设置的间隔时间。
 * 我们在间隔时间开始内说话。是没有给我们回调的。
 * 比如说:设置回调是10s,如果我们在3s的时间节点说一句话,在10s前说话结束,那我们是没有收到onAudioVolumeIndication 回调的。
 */
rtcEngine.enableAudioVolumeIndication(500, 3, false);


// ————————— 声网角色设置/更新token ——————————

/**
 * 设置用户角色。
 *
 * 详情
 * 在加入频道前和加入频道后均可调用该方法设置用户角色。
 *
 * 如果你在加入频道前调用该方法设置用户角色为主播、并且通过 setupLocalVideo 方法设置了本地视频属性,则用户加入频道时会自动开启本地视频预览。
 *
 * 如果你在加入频道后调用该方法切换用户角色,调用成功后:
 * 本地会触发 onClientRoleChanged 回调。
 * 远端会触发 onUserJoined 或 onUserOffline(USER_OFFLINE_BECOME_AUDIENCE) 回调。
 * 参数
 * role
 * 用户的角色:
 * CLIENT_ROLE_BROADCASTER (1):主播。
 * CLIENT_ROLE_AUDIENCE (2):观众。
 * 返回值
 * 0: 方法调用成功。
 * < 0: 方法调用失败。
 * -1: 一般性的错误(未明确归类)。
 * -2: 参数无效。
 * -7: SDK 尚未初始化。
 */
rtcEngine.setClientRole();

/**
 * 更新 Token。
 *
 * 详情该方法用于更新 Token。Token 会在一定时间后失效。在以下两种情况下,app 应重新获取 Token,
 * 然后调用该方法传入新的 Token,否则 SDK 无法和服务器建立连接:
 * 发生 onTokenPrivilegeWillExpire 回调时。
 * onConnectionStateChanged 回调报告 CONNECTION_CHANGED_TOKEN_EXPIRED(9) 时。
 * 参数
 * token
 * 新的 Token。
 * 返回值
 * 0: 方法调用成功。
 * < 0: 方法调用失败。
 * -2:传入的参数无效。例如,使用了不合法的 Token。你需要填入有效的参数。
 * -7:RtcEngine 对象尚未初始化。你需要在调用该方法前成功初始化 RtcEngine 对象。
 */
int renewToken(String token);

// ————————— 加入频道/离开频道 ——————————

/**
 * 加入频道。
 *
 * 详情
 * 该方法让用户加入通话频道,在同一个频道内的用户可以互相通话,多个用户加入同一个频道,可以群聊。 使用不同 App ID 的 app 不能互通。
 *
 * 成功调用该方法加入频道后会触发以下回调:
 * 本地会触发 onJoinChannelSuccess 和 onConnectionStateChanged 回调。
 * 通信场景下的用户和直播场景下的主播加入频道后,远端会触发 onUserJoined 回调。
 * 在网络状况不理想的情况下,客户端可能会与声网服务器失去连接;SDK 会自动尝试重连,重连成功后,本地会触发 onRejoinChannelSuccess 回调。
 *
 * 注意:用户成功加入频道后,默认订阅频道内所有其他用户的音频流和视频流,因此产生用量并影响计费。如果想取消订阅,可以通过调用相应的 mute 方法实现。
 * 参数
 * token
 * 在服务端生成的用于鉴权的动态密钥。详见使用 Token 鉴权。
 * channelId
 * 频道名。该参数标识用户进行实时音视频互动的频道。App ID 一致的前提下,填入相同频道名的用户会进入同一个频道进行音视频互动。该参数为长度在 64 字节以内的字符串。以下为支持的字符集范围(共 89 个字符):
 * 26 个小写英文字母 a~z
 * 26 个大写英文字母 A~Z
 * 10 个数字 0~9
 * 空格
 * "!"、"#"、"$"、"%"、"&"、"("、")"、"+"、"-"、":"、";"、"<"、"="、"."、">"、"?"、"@"、"["、"]"、"^"、"_"、"{"、"}"、"|"、"~"、","
 * optionalInfo
 * (非必选项) 预留参数。
 * optionalUid
 * 用户 ID。该参数用于标识在实时音视频互动频道中的用户。你需要自行设置和管理用户 ID,
 * 并确保同一频道内的每个用户 ID 是唯一的。该参数为 32 位无符号整数。
 * 建议设置范围:1 到 232-1。如果不指定(即设为 0),SDK 会自动分配一个,并在 onJoinChannelSuccess 回调中返回, 
 * 应用层必须记住该返回值并维护,SDK 不对该返回值进行维护。
 */
int joinChannel(String token, String channelName, String optionalInfo, int optionalUid);

/**
 * 离开频道。
 *
 * 详情
 * 该方法会把会话相关的所有资源释放掉。
 *
 * 该方法是异步操作,调用返回时并没有真正退出频道。
 *
 * 成功加入频道后,必须调用本方法或者 leaveChannel [2/2] 结束通话,否则无法开始下一次通话。
 *
 * 成功调用该方法、并且离开频道后会触发以下回调:
 * 本地:onLeaveChannel 回调。
 * 远端:通信场景下的用户和直播场景下的主播离开频道后,远端会触发 onUserOffline 回调。
 * 注意:
 * 如果你调用了本方法后立即调用 destroy 方法,SDK 将无法触发 onLeaveChannel 回调。
 * 如果你已调用 joinChannelEx 加入多频道,调用本方法后会同时离开 joinChannel [2/2] 和 joinChannelEx 加入的频道。
 * 返回值
 * 0(ERR_OK): 方法调用成功。
 * < 0: 方法调用失败。
 * -1: 一般性的错误(未明确归类)。
 * -2: 参数无效。
 * -7: SDK 尚未初始化。
 */
int leaveChannel();

// ————————— 打开/关闭 本地扬声器 “静音” ——————————

/**
 * 取消或恢复订阅所有远端用户的音频流。
 *
 * 成功调用该方法后,本地用户会取消或恢复订阅所有远端用户的音频流,包括在调用该方法后加入频道的用户的音频流。
 *
 * 注解
 * 该方法需要在加入频道后调用。
 * 自 v3.3.0 起,该方法包含了 setDefaultMuteAllRemoteAudioStreams 的功能。 声网建议不要一起调用 muteAllRemoteAudioStreams 和 setDefaultMuteAllRemoteAudioStreams,否则设置可能会不生效。详见《设置订阅状态》。
 * 参数
 * muted    是否取消订阅所有远端用户的音频流。
 * true: 取消订阅。
 * false:(默认)订阅。
 * 返回
 * 0: 方法调用成功。
 * < 0: 方法调用失败。
 */
int muteAllRemoteAudioStreams(boolean muted);

/**
 * 调节本地播放的所有远端用户信号音量。
 *
 * 注解
 * 该方法调节的是本地播放的所有远端用户混音后的音量。
 * 从 v2.3.2 开始,静音本地音频需同时调用该方法和 adjustAudioMixingPlayoutVolume 方法,并将 volume 参数设置为 0。
 * 参数
 * volume    播放音量。取值范围为 [0,400],其中:
 * 0: 静音
 * 100:(默认)原始音量
 * 400: 原始音量的 4 倍(自带溢出保护)
 * 返回
 * 0:方法调用成功
 * < 0:方法调用失败
 */
int adjustPlaybackSignalVolume(int volume);


/**
 * 调节音乐文件的本地播放音量。
 *
 * 自从
 * v2.3.2。
 * 该方法调节混音里音乐文件在本端播放的音量大小。
 *
 * 你需要在调用 startAudioMixing 并收到 onAudioMixingStateChanged(MEDIA_ENGINE_AUDIO_EVENT_MIXING_PLAY) 回调后调用该方法。
 *
 * 参数
 * volume    伴奏音量范围为 0~100。默认 100 为原始文件音量。
 * 返回
 * 0: 方法调用成功。
 * < 0: 方法调用失败。
 */
int adjustAudioMixingPlayoutVolume(int volume);

// ————————— 在onActivityResumed时,需要做音频路由校正 ——————————

 /**
 * 开启/关闭扬声器播放。
 * enabled    设置是否开启扬声器播放
 * true:开启。音频路由为扬声器。
 * false:关闭。音频路由为听筒。
 *
 * 如果 SDK 默认的音频路由(见《设置音频路由》)或 setDefaultAudioRoutetoSpeakerphone 的设置无法满足你的需求,
 * 你可以调用 setEnableSpeakerphone 切换当前的音频路由。 成功切换音频路由后,SDK 会触发 onAudioRouteChanged 回调提示音频路由已更改。
 *
 * 该方法只设置用户在当前频道内使用的音频路由,不会影响 SDK 默认的音频路由。 如果用户离开当前频道并加入新的频道,则用户还是会使用 SDK 默认的音频路由。
 *
 * 注解
 * 该方法需要在 joinChannel 后调用。
 * 如果用户使用了蓝牙耳机、有线耳机等外接音频播放设备,则该方法的设置无效,音频只会通过外接设备播放。当有多个外接设备时,音频会通过最后一个接入的设备播放。
 */
int setEnableSpeakerphone(boolean enabled);

注意 :  为什么需要在 onActivityResumed 中调用 setEnableSpeakerphone, 下面简单讲解了下, 会在后续专门讲解如何实现代码.
/**
 * 为什么在 Android 设备上切换到其他 app 会改变音频路由?
 * <p>
 * 问题描述
 * 在 Android 设备上使用集成了 Agora RTC SDK 的 app (以下简称 SDK app)进行实时音视频互动,
 * 切换到其他有音频输入或输出的 app,再切换回 SDK app 之后 SDK 的音频路由发生改变。
 * <p>
 * 例如,用户在 SDK app 中通话并启用扬声器,通话过程中用听筒模式接听了 QQ 语音电话,
 * 结束 QQ 语音电话后返回 SDK app 通话,音频仍然通过听筒播放。
 * <p>
 * 问题原因
 * 在 Android 设备上从 SDK app 切换到其他 app 时,其他 app 可能会修改 SDK 的音频路由。
 * 由于 SDK 没有权限检测其他 app 对音频路由的修改,也无法判断是否已从其他 app 切换回来,
 * 因此切换回 SDK app 后仍然使用其他 app 的音频路由设置。
 * <p>
 * 解决方案
 * 在安卓原生方法 onResume 中检测当前的音频路由,然后调用 setEnableSpeakerphone 方法重新设置音频路由。可参考以下示例代码。
 */


// ————————— 本地麦克风静音 ——————————

/**
 * 取消或恢复发布本地音频流。
 *
 * 自 v3.4.5 起,该方法仅设置用户在 RtcEngine 频道中的音频发布状态。
 *
 * 成功调用该方法后,远端会触发 onUserMuteAudio 回调。
 *
 * 同一时间,本地的音视频流只能发布到一个频道。如果你创建了多个频道,请确保你只在一个频道中调用 muteLocalVideoStream(false),否则方法会调用失败并返回 -5 (ERR_REFUSED)。
 *
 * 注解
 * 该方法不会改变音频采集设备的使用状态。
 * 该方法的调用是否生效受 joinChannel 和 setClientRole 方法的影响,详见《设置发布状态》。
 * 参数
 * muted    是否取消发布本地音频流。
 * true:取消发布。
 * false:发布。
 * 返回
 * 0: 方法调用成功。
 * < 0: 方法调用失败。
 * -5 (ERR_REFUSED): 调用被拒绝。
 */
int muteLocalAudioStream(boolean muted);


// ————————— 实现背景音乐功能 ——————————

// 开始播放音乐文件及混音。

int startAudioMixing(String filePath, boolean loopback, boolean replace, int cycle, int startPos);

//停止播放音乐文件及混音。

int stopAudioMixing();

// 暂停播放音乐文件及混音。

int pauseAudioMixing();

// 恢复播放音乐文件及混音。

int resumeAudioMixing();

// 调节音乐文件的播放音量。

int adjustAudioMixingVolume(int volume);

// 获取音乐文件的远端播放音量。

int getAudioMixingPublishVolume();

// 获取音乐文件的播放进度。

int getAudioMixingCurrentPosition();

// 获取音乐文件的时长。注意 : 该方法自 v3.5.1 起废弃,请改用 getAudioFileInfo。

int getAudioMixingDuration();


// ————————— 跨房PK功能 ——————————

// 开始跨频道媒体流转发。

int startChannelMediaRelay(ChannelMediaRelayConfiguration channelMediaRelayConfiguration);

// 停止跨频道媒体流转发。

int stopChannelMediaRelay();

// 更新媒体流转发的频道。

int updateChannelMediaRelay(ChannelMediaRelayConfiguration channelMediaRelayConfiguration);

// 暂停向所有目标频道转发媒体流。

int pauseAllChannelMediaRelay();

// 恢复向所有目标频道转发媒体流。

int resumeAllChannelMediaRelay();


// ————————— IRtcEngineEventHandler ——————————


这里只罗列我们会编写额外逻辑的回调函数


/**
 * 发生错误回调。
 * <p>
 * 表示 SDK 运行时出现了(网络或媒体相关的)错误。通常情况下,
 * SDK 上报的错误意味着 SDK 无法自动恢复,需要 App 干预或提示用户。
 * 例如启动通话失败时,SDK 会上报 ERR_START_CALL 错误。
 * App 可以提示用户启动通话失败,并调用 leaveChannel 退出频道。
 *
 * @param errorCode 错误代码,详细定义见 Error Code
 */
@Override
public void onError(int errorCode) {
    if (errorCode == Constants.ERR_NOT_READY 
        || errorCode == Constants.ERR_NOT_INITIALIZED 
        || errorCode == Constants.ERR_ALREADY_IN_USE 
        || errorCode == Constants.ERR_INVALID_APP_ID 
        || errorCode == Constants.ERR_INVALID_CHANNEL_NAME 
        || errorCode == Constants.ERR_INVALID_TOKEN 
        || errorCode == Constants.ERR_LOAD_MEDIA_ENGINE 
        || errorCode == Constants.ERR_START_CALL) {
                // TODO : 发生了致命错误, 此时客户端可以结束声网SDK的使用了, 直接退出语聊房
    }
}



/**
 * 加入频道回调。(TODO : 本回调用于本地用户调用 joinChannel 成功时执行)
 * <p>
 * 表示客户端已经登入服务器,且分配了频道 ID 和用户 ID。
 * 频道 ID 的分配是根据 joinChannel 方法中指定的频道名称。
 * 如果调用 joinChannel 时并未指定用户 ID,服务器就会分配一个。
 *
 * @param channel 频道名
 * @param uid     用户 ID 。如果 joinChannel 中指定了 uid,则此处返回该 ID;否则使用 Agora 服务器自动分配的 ID
 * @param elapsed 从 joinChannel 开始到发生此事件过去的时间(毫秒)
 */
@Override
public void onJoinChannelSuccess(String channel, int uid, int elapsed) {
    // TODO : 本地用户成功加入频道时,会触发该回调。
    // TODO : 在这里编写加入频道之后的后续代码

}

/**
 * Token 服务即将过期回调。
 * <p>
 * 在调用 joinChannel 时如果指定了 Token,由于 Token 具有一定的时效,在通话过程中如果 Token 即将失效,SDK 会提前 30 秒触发该回调,提醒 App 更新 Token。
 * 当收到该回调时,你需要重新在服务端生成新的 Token,然后调用 renewToken 将新生成的 Token 传给 SDK。
 *
 * @param token 即将服务失效的 Token
 */
@Override
public void onTokenPrivilegeWillExpire(String token) {
    // TODO : 在这里请求我们服务器接口, 刷新当前登录用户的 声网token
}
/**
 * Token 过期回调。
 * <p>
 * 在调用 joinChannel 时如果指定了 Token,
 * <p>
 * 由于 Token 具有一定的时效,在通话过程中 SDK 可能由于网络原因和服务器失去连接,重连时可能需要新的 Token。
 * <p>
 * 该回调通知 App 需要生成新的 Token,并调用 renewToken 更新 Token。
 */
@Override
public void onRequestToken() {
    // TODO : 在这里请求我们服务器接口, 刷新当前登录用户的 声网token

}


/**
 * 用户音量提示回调
 * 该回调默认禁用。可以通过 enableAudioVolumeIndication 方法开启。
 * 开启后,只要频道内有发流用户,SDK 会在加入频道后按 enableAudioVolumeIndication 中设置的时间间隔触发 onAudioVolumeIndication 回调。
 * 每次会触发两个 onAudioVolumeIndication 回调,一个报告本地发流用户的音量相关信息,另一个报告瞬时音量最高的远端用户(最多 3 位)的音量相关信息。
 * <p>
 * 注解
 * 启用该功能后,如果有用户将自己静音(调用了 muteLocalAudioStream),SDK 行为会受如下影响:
 * 1] 本地用户静音后,SDK 立即停止报告本地用户的音量提示回调。
 * 2] 瞬时音量最高的远端用户静音后 20 秒,远端的音量提示回调中将不再包含该用户;如果远端所有用户都将自己静音,20 秒后 SDK 停止报告远端用户的音量提示回调。
 * <p>
 * 参数
 *
 * @param speakerArray 用户音量信息,详见 AudioVolumeInfo 数组。如果 speakers 为空,则表示远端用户不发流或没有远端用户。
 * @param totalVolume  混音后的总音量,取值范围为 [0,255]。
 *                     1] 在本地用户的回调中,totalVolume 为本地发流用户的音量。
 *                     2] 在远端用户的回调中,totalVolume 为瞬时音量最高的远端用户(最多 3 位)混音后的总音量。
 *                     如果用户调用了 startAudioMixing,则 totalVolume 为音乐文件和用户声音的总音量。
 */
@Override
public void onAudioVolumeIndication(final AudioVolumeInfo[] speakerArray, final int totalVolume) {
    // 1] 本房 主播和嘉宾 说话时的水波纹效果, 在这里实现.
     // 2] 跨房PK时, 对方主播 说话时的水波纹效果, 在这里实现.
}


/**
 * 跨频道媒体流转发状态发生改变回调。
 * <p>
 * 自从
 * v2.9.0。
 * 当跨频道媒体流转发状态发生改变时,SDK 会触发该回调,并报告当前的转发状态以及相关的错误信息。
 *
 * @param state 跨频道媒体流转发状态:
 *              RELAY_STATE_IDLE(0):SDK 正在初始化
 *              RELAY_STATE_CONNECTING(1):SDK 尝试跨频道
 *              RELAY_STATE_RUNNING(2):源频道主播成功加入目标频道
 *              RELAY_STATE_FAILURE(3):发生异常,详见 code 中提示的错误信息
 * @param code  跨频道媒体流转发出错的错误码:
 *              RELAY_OK(0):一切正常
 *              RELAY_ERROR_SERVER_ERROR_RESPONSE(1):服务器回应出错
 *              RELAY_ERROR_SERVER_NO_RESPONSE(2):服务器无回应。可能是由于当前的 App ID 未开启连麦鉴权导致的。你可以提交工单申请开通连麦鉴权服务。
 *              RELAY_ERROR_NO_RESOURCE_AVAILABLE(3):SDK 无法获取服务,可能是因为服务器资源有限导致
 *              RELAY_ERROR_FAILED_JOIN_SRC(4):发起跨频道转发媒体流请求失败
 *              RELAY_ERROR_FAILED_JOIN_DEST(5):接受跨频道转发媒体流请求失败
 *              RELAY_ERROR_FAILED_PACKET_RECEIVED_FROM_SRC(6):服务器接收跨频道转发媒体流失败
 *              RELAY_ERROR_FAILED_PACKET_SENT_TO_DEST(7):服务器发送跨频道转发媒体流失败
 *              RELAY_ERROR_SERVER_CONNECTION_LOST(8):SDK 因网络质量不佳与服务器断开。你可以调用 leaveChannel 方法离开当前频道
 *              RELAY_ERROR_INTERNAL_ERROR(9):服务器内部出错
 *              RELAY_ERROR_SRC_TOKEN_EXPIRED(10):源频道的 Token 已过期
 *              RELAY_ERROR_DEST_TOKEN_EXPIRED(11):目标频道的 Token 已过期
 */
@Override
public void onChannelMediaRelayStateChanged(int state, int code) {
    // 在这里实现, 跨房PK功能 , 频道转发过程中的兜底策略 (常规重试策略 or  深度规避策略)

}
/**
 * 本地用户的音乐文件播放状态已改变回调。
 * <p>
 * 自从
 * v3.4.0
 * 该回调在音乐文件播放状态发生改变时触发,并报告当前的播放状态和播放状态改变的原因。
 *
 * @param state  当前音乐文件播放状态:
 *               MEDIA_ENGINE_AUDIO_EVENT_MIXING_PLAY(710):音乐文件正常播放。该状态可能由以下原因导致:
 *               AUDIO_MIXING_REASON_STARTED_BY_USER(720)
 *               AUDIO_MIXING_REASON_ONE_LOOP_COMPLETED(721)
 *               AUDIO_MIXING_REASON_START_NEW_LOOP(722)
 *               AUDIO_MIXING_REASON_RESUMED_BY_USER(726)
 *               MEDIA_ENGINE_AUDIO_EVENT_MIXING_PAUSED(711):音乐文件暂停播放。该状态由 AUDIO_MIXING_REASON_PAUSED_BY_USER(725) 原因导致。
 *               MEDIA_ENGINE_AUDIO_EVENT_MIXING_STOPPED(713):音乐文件停止播放。该状态可能由以下原因导致:
 *               AUDIO_MIXING_REASON_ALL_LOOPS_COMPLETED(723)
 *               AUDIO_MIXING_REASON_STOPPED_BY_USER(724)
 *               MEDIA_ENGINE_AUDIO_EVENT_MIXING_ERROR(714):音乐文件播放失败。该状态可能由以下原因导致:
 *               AUDIO_MIXING_REASON_CAN_NOT_OPEN(701)
 *               AUDIO_MIXING_REASON_TOO_FREQUENT_CALL(702)
 *               AUDIO_MIXING_REASON_INTERRUPTED_EOF(703)
 * @param reason 音乐文件播放状态改变的原因:
 *               AUDIO_MIXING_REASON_CAN_NOT_OPEN(701):音乐文件打开出错。例如,本地音乐文件不存在、文件格式不支持或无法访问在线音乐文件 URL。
 *               AUDIO_MIXING_REASON_TOO_FREQUENT_CALL(702):音乐文件打开太频繁。如需多次调用 startAudioMixing,请确保调用间隔大于 500 ms。
 *               AUDIO_MIXING_REASON_INTERRUPTED_EOF(703):音乐文件播放中断。
 *               AUDIO_MIXING_REASON_STARTED_BY_USER(720):成功调用 startAudioMixing 播放音乐文件。
 *               AUDIO_MIXING_REASON_ONE_LOOP_COMPLETED(721):音乐文件完成一次循环播放。
 *               AUDIO_MIXING_REASON_START_NEW_LOOP(722):音乐文件开始新的一次循环播放。
 *               AUDIO_MIXING_REASON_ALL_LOOPS_COMPLETED(723):音乐文件完成所有循环播放。
 *               AUDIO_MIXING_REASON_STOPPED_BY_USER(724):成功调用 stopAudioMixing 停止播放音乐文件。
 *               AUDIO_MIXING_REASON_PAUSED_BY_USER(725):成功调用 pauseAudioMixing 暂停播放音乐文件。
 *               AUDIO_MIXING_REASON_RESUMED_BY_USER(726):成功调用 resumeAudioMixing 恢复音乐文件播放。
 */
@Override
public void onAudioMixingStateChanged(int state, int reason) {

    // TODO : 在这里实现背景音乐播放控制功能(播放 / 暂停 / 停止 / 失败 / 本手播放完成,播放下一曲 / 异常)
}


推荐阅读
相关专栏
开发者实践
186 文章
本专栏仅用于分享音视频相关的技术文章,与其他开发者和声网 研发团队交流、分享行业前沿技术、资讯。发帖前,请参考「社区发帖指南」,方便您更好的展示所发表的文章和内容。