Android 常见问题
本文搜集并整理了 Android 通话过程中的常见问题
若您遇到的问题本文未提及,请提交工单或者联系七牛技术支持同学协助解决
获取 RoomToken
在正式的业务场景中,RoomToken 需要您的业务服务器根据 AppID、RoomName 以及 UserID 根据一定规则签算生成,签算规则可参考 RoomToken 签发服务。
若您的服务端还没有实现相关代码,可参考房间的创建和管理文档在 portal 上生成临时的 RoomToken,需要注意 UserID 不可重复。
SDK 重连机制
当前 SDK 内部会尝试无限次数的重连,但是,如果 30s 内无法完成一次有效的重连过程,则超时后的有效的重连请求在到达 RTC 服务后会抛出 ERROR_RECONNECT_FAILED
错误。
断网重连的处理
监控房间连接状态的用法,可以参考文档 房间管理。这里需要注意的点是,断网重连的处理。
默认情况下,当发生网络异常等情况,SDK 会进入自动重连状态,此时房间连接状态会变为 RECONNECTING
,表示重连中。之后就会两种可能:
- SDK 自动重连成功,房间状态变为
RECONNECTED
。重连成功后,SDK 会自动恢复原有的发布和订阅状态。也就是说,如果在重连之前有发布过 tracks 或者订阅过 tracks,重连成功后,SDK 会自动重新发布/订阅这些 tracks。 - SDK 自动重连失败,此时 SDK 将自动退出房间,房间状态变为
DISCONNECTED
。在断开连接状态时,回调函数中会带有第二个参数 QNConnectionDisconnectedInfo,用来表示断开的原因。此时应当根据断开原因不同,做不同的逻辑处理。
具体处理见如下代码:
public void onConnectionStateChanged(QNConnectionState state, QNConnectionDisconnectedInfo disconnectedInfo) {
if (QNConnectionState.CONNECTING.equals(state)) {
// 连接中
} else if (QNConnectionState.CONNECTED.equals(state)) {
// 连接成功,可以进行发布 track 等行为
} else if (QNConnectionState.RECONNECTING.equals(state)) {
// 重连中
} else if (QNConnectionState.RECONNECTED.equals(state)) {
// 重连成功,可以进行发布 track 等行为;自动恢复原来的发布订阅状态
} else if (QNConnectionState.DISCONNECTED.equals(state)) {
// 监控断开原因
switch(disconnectedInfo.reason) {
// 当连接失败时
case QNConnectionDisconnectedReason.ERROR:
if (disconnectedInfo.errorCode == QNErrorCode.ERROR_RECONNECT_FAILED) {
// 重连失败
}
break;
}
}
}
此时,最需要关注的是异常断开的情况。一般处理模式有两种:
- 通知用户:展示 UI,通知用户网络异常,用户可选择调整网络后重试
- 自动重连:可以在收到异常断开的通知后,主动调用加入房间的方法尝试重新加入房间,此时需注意 token 的实效性,若 token 过期,需要重新获取再加入房间
断网重连场景下的 CDN 转推处理
若您使用客户端提供的接口进行 CDN 转推,那么,若出现断网重连,建议的处理方式如下:
单路转推
- 若重连成功,则需要判断是否收到 QNLiveStreamingListener.onError 回调:
- 未收到回调,则无需重新创建转推任务,转推流将正常进行
- 收到回调,且 QNLiveStreamingErrorInfo.type 为 STOP,QNLiveStreamingErrorInfo.code 为 ERROR_LIVE_STREAMING_CLOSED,则代表转推流已经断开,需要重新创建转推任务
- 若重连失败,则需要在重新加入房间后,再次创建转推任务
合流转推
- 若重连成功,则不需要重新配置合流布局,服务端会默认将重连后的 Track 重新加入到合流中
- 若重连失败,则需要在重新加入房间后,再次创建合流任务,并配置合流布局,否则,转推流将会断开
是否支持后台连麦
基于 Android 行为变更的相关声明,我们了解到,从 Android 9 开始,设备将无法后台进行音视频的采集。
解决方案:
- 若您有后台连麦的需求,可参考 Android 官网相关说明在退后台后使用前台服务让应用正常工作。
- 若您不需要后台连麦,可以在 Android
onResume
、onPause
等生命周期函数中分别调用 QNCameraVideoTrack.startCapture 和 QNCameraVideoTrack.stopCapture 方法进行 Camera 采集的开启和关闭操作。
集成三方美颜厂商
SDK 提供了 QNLocalVideoTrack.setVideoFrameListener 接口进行视频帧数据的回调,具体回调方法如下:
public interface QNVideoFrameListener {
/**
* YUV 视频数据回调
*/
void onYUVFrameAvailable(byte[] data, QNVideoFrameType type, int width, int height, int rotation, long timestampNs);
/**
* 纹理视频数据回调
*/
int onTextureFrameAvailable(int textureID, QNVideoFrameType type, int width, int height, int rotation, long timestampNs, float[] transformMatrix);
}
在对接三方美颜厂商时,将 onTextureFrameAvailable
回调返回的纹理数据送入三方美颜 SDK,并将其处理后的纹理返回给 RTC SDK 即可。
感知用户是否讲话
可通过定时获取音频 Track 的音量大小来判断用户是否在讲话。
SDK 提供获取音频 Track 音量的接口如下:
- 本地音频 Track:QNLocalAudioTrack.getVolumeLevel
- 远端音频 Track:QNRemoteAudioTrack.getVolumeLevel
其中,在安静的环境下,获取到 0.0x 大小的音量值为环境音的大小,属于预期现象,您可根据您的需求自行决定判断的阈值。
接口的调用方式也可参考麦克风采集纯音频通话场景示例
实际采集分辨率与设置不符
这是因为不同的设备所支持的采集能力是不同的,当前设备的 Camera 可能不支持配置中的分辨率,导致 SDK 基于内部策略选择了一个相近的采集分辨率,若 SDK 内部策略选择的分辨率不符合您的需求,您可以通过监听 QNCameraEventListener.onCameraOpened 回调并返回指定的索引来选择符合您需求的采集分辨率
实际编码分辨率与设置不符
实际分辨率与设置不符有如下两种原因:
编码分辨率对齐
硬编场景下,考虑到硬件平台的兼容性,避免出现花屏等问题,SDK 内部将会对编码分辨率做对齐处理,对齐规则如下:
- 华为机型 32 对齐
- 其他机型 16 对齐
实际编码分辨率会根据对齐的参数进行整数倍调整
和采集宽高比不一致
若编码宽高比和采集宽高比不一致,SDK 会根据采集宽高比对编码分辨率做等比例的处理,此时就会出现编码分辨率与设置不符的情况。
若想确保编码分辨率与设置相符,需保证在创建 QNCameraVideoTrackConfig 时,setVideoCaptureConfig 和 setVideoEncoderConfig 接口设置的分辨率具有相同的宽高比。
回声问题的处理
回声现象是指在通话过程中,可以听到自己的声音通过扬声器回放出来,该现象是远端设备的回声消除处理失效导致的,需要在远端设备上检查并修改如下配置项,再观察通话体验是否有所改善:
- 使用单声道音频采集参数,建议使用 QNAudioQualityPreset.STANDARD 和 QNAudioQualityPreset.LOW 的音频编码预设
- 使用
VOICE_CHAT
清晰语聊模式,可通过 QNRTCSetting.setAudioScene 接口进行配置。
混音格式支持
Android 12 以上设备蓝牙连接失败
如果您的应用适配了 API 31 及以上的版本, 为了在通话过程中使用蓝牙耳机设备,需要添加并动态获取 BLUETOOTH_CONNECT
权限。详情可参考 Android 12 中的新蓝牙权限。