本文介绍一对一音视频通话Android SDK集成的代码示例及集成说明。
功能时序图
功能实现
初始化ARTC引擎及回调注册
SDK出现异常时内部会优先进行重试恢复,需要业务处理的异常SDK会通过明确的回调API通知。
异常发生原因 | 回调及参数 | 解决方案 | 备注 |
鉴权失败 | onJoinChannelResult回调result返回AliRtcErrJoinBadToken | 发生错误时需要App检查token是否正确。 | 出现鉴权失败发生在用户主动调用API时发生,所以在API对应的回调中返回。 |
鉴权过期 | onWillAuthInfoExpire | 发生该异常时App需要重新获取最新的鉴权信息后,再调用refreshAuthInfo刷新鉴权信息。 | 出现鉴权过期的情况分为用户主动调用API、程序运行阶段时发生,所以会在API对应的回调及独立的错误回调时发生。 |
鉴权过期 | onAuthInfoExpired | 发生该异常时App需要重新入会。 | 出现鉴权过期的情况分为用户主动调用API、程序运行阶段时发生,所以会在API对应的回调及独立的错误回调时发生。 |
网络链接异常 | onConnectionStatusChange回调返回AliRtcConnectionStatusFailed | 发生该异常时需要重新入会。 | SDK具备一定时间断网自动恢复能力,超过限定的时间后会超时断开;此时需要App检查当前的状态后再次入会。 |
被踢下线 | onBye |
| ARTC服务具备踢人的能力。 |
本地设备异常 | onLocalDeviceException | 本地设备异常,需要App检测权限、设备硬件是否正常。 | ARTC服务具备设备检测、异常诊断的能力;在本地设备异常时那么会通过回调的方式通知客户本地设备异常,此时SDK内部无法恢复,需要App方介入查看设备是否正常。 |
private void createEngine() {
mAliRtcEngine = AliRtcEngine.getInstance(getApplicationContext());
mAliRtcEngine.setRtcEngineEventListener(new AliRtcEngineEventListener() {
/* SDK与服务器的链接状态通知,务必处理链接失败的情况 */
@Override
public void onConnectionStatusChange(AliRtcEngine.AliRtcConnectionStatus aliRtcConnectionStatus, AliRtcEngine.AliRtcConnectionStatusChangeReason aliRtcConnectionStatusChangeReason) {
super.onConnectionStatusChange(aliRtcConnectionStatus, aliRtcConnectionStatusChangeReason);
if (aliRtcConnectionStatus == AliRtcEngine.AliRtcConnectionStatus.AliRtcConnectionStatusFailed) {
/* TODO: 务必处理;建议业务提示客户,此时SDK内部已经尝试了各种恢复策略已经无法继续使用时才会上报 */
} else {
/* TODO: 可选处理;增加业务代码,一般用于数据统计、UI变化 */
}
}
/* SDK尝试控制本地设备异常 */
@Override
public void OnLocalDeviceException(AliRtcEngine.AliRtcEngineLocalDeviceType aliRtcEngineLocalDeviceType, AliRtcEngine.AliRtcEngineLocalDeviceExceptionType aliRtcEngineLocalDeviceExceptionType, String s) {
super.OnLocalDeviceException(aliRtcEngineLocalDeviceType, aliRtcEngineLocalDeviceExceptionType, s);
/* TODO: 务必处理;建议业务提示客户错误,此时SDK内部已经尝试了各种恢复策略已经无法继续使用时才会上报 */
}
@Override
public void onJoinChannelResult(int result, String channel, String userId, int elapsed) {
super.onJoinChannelResult(result, channel, userId, elapsed);
/* TODO: 可选处理;增加业务代码,一般用于数据统计、UI变化 */
Log.i(TAG, "onJoinChannelResult result=" + result + ",channel=" + channel + ",userId=" + userId + ",elapsed=" + elapsed);
}
@Override
public void onLeaveChannelResult(int result, AliRtcEngine.AliRtcStats stats) {
super.onLeaveChannelResult(result, stats);
Log.i(TAG, "onLeaveChannelResult result=" + result);
}
});
mAliRtcEngine.setRtcEngineNotify(new AliRtcEngineNotify() {
/* 鉴权距离过期还有30s时会回调,务必进行鉴权时间刷新 */
@Override
public void onAuthInfoWillExpire() {
super.onAuthInfoWillExpire();
/* TODO: 务必处理;业务触发重新获取当前channel,user的鉴权信息,然后设置refreshAuthInfo即可 */
}
/* 业务可能会触发踢人的动作,所以这个地方也需要处理 */
@Override
public void onBye(int code) {
super.onBye(code);
/* TODO: 建议业务根据自己的场景,进行对应的处理 */
}
@Override
public void onRemoteUserOnLineNotify(String uid, int elapsed) {
super.onRemoteUserOnLineNotify(uid, elapsed);
Log.i(TAG, "onRemoteUserOnLineNotify uid=" + uid + ",elapsed=" + elapsed);
}
@Override
public void onRemoteUserOffLineNotify(String uid, AliRtcEngine.AliRtcUserOfflineReason aliRtcUserOfflineReason) {
super.onRemoteUserOffLineNotify(uid, aliRtcUserOfflineReason);
Log.i(TAG, "onRemoteUserOnLineNotify uid=" + uid + ",aliRtcUserOfflineReason=" + aliRtcUserOfflineReason);
}
@Override
public void onRemoteTrackAvailableNotify(String uid, AliRtcEngine.AliRtcAudioTrack aliRtcAudioTrack, AliRtcEngine.AliRtcVideoTrack aliRtcVideoTrack) {
super.onRemoteTrackAvailableNotify(uid, aliRtcAudioTrack, aliRtcVideoTrack);
Log.i(TAG, "onRemoteUserOnLineNotify uid=" + uid + ",aliRtcAudioTrack=" + aliRtcAudioTrack + ",aliRtcVideoTrack=" + aliRtcVideoTrack);
mMainHandler.post(new Runnable() {
@Override
public void run() {
if (aliRtcVideoTrack == AliRtcEngine.AliRtcVideoTrack.AliRtcVideoTrackCamera
|| aliRtcVideoTrack == AliRtcEngine.AliRtcVideoTrack.AliRtcVideoTrackBoth) {
AliRtcEngine.AliRtcVideoCanvas remote_canvas = new AliRtcEngine.AliRtcVideoCanvas();
SurfaceView remoteView = mAliRtcEngine.createRenderSurfaceView(mContext);
if (remoteView != null) {
remoteView.setZOrderOnTop(true);
remoteView.setZOrderMediaOverlay(true);
}
remote_canvas.view = remoteView;
mLocalSurfaceContainer.addView(remote_canvas.view, new FrameLayout.LayoutParams(
findViewById(R.id.local_surface_container).getWidth()/4,
findViewById(R.id.local_surface_container).getHeight()/4));
mAliRtcEngine.setRemoteViewConfig(remote_canvas,uid,AliRtcEngine.AliRtcVideoTrack.AliRtcVideoTrackCamera);
} else {
mAliRtcEngine.setRemoteViewConfig(null, uid, AliRtcEngine.AliRtcVideoTrack.AliRtcVideoTrackCamera);
}
}
});
}
});
}
设置入会前的参数
SDK在互动模式下、主播角色,默认会推本地的音视频,同时拉其他主播的音视频流。
SDK在互动模式下、观众角色,不会推本地的音视频流,但是会拉取其他主播的音视频流。
SDK默认是按照自动推拉流模式,用户也可以关闭自动推拉流模式。
private void initEngineBeforeJoin() {
/* 可选:入会前的参数设置 */
mAliRtcEngine.setChannelProfile(AliRtcEngine.AliRTCSdkChannelProfile.AliRTCSdkInteractiveLive);
mAliRtcEngine.setClientRole(AliRtcEngine.AliRTCSdkClientRole.AliRTCSdkInteractive);
/* 设置音频的属性 */
mAliRtcEngine.setAudioProfile(AliRtcEngine.AliRtcAudioProfile.AliRtcEngineStereoHighQualityMode, AliRtcEngine.AliRtcAudioScenario.AliRtcSceneMusicMode);
/* 可选:摄像头预览,不设置也会进行推流 */
AliRtcEngine.AliRtcVideoCanvas canvas = new AliRtcEngine.AliRtcVideoCanvas();
canvas.view = mAliRtcEngine.createRenderSurfaceView(mContext);
mLocalSurfaceContainer.removeAllViews();
if (canvas.view != null) {
mLocalSurfaceContainer.addView(canvas.view, new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT));
}
mAliRtcEngine.setLocalViewConfig(canvas, AliRtcEngine.AliRtcVideoTrack.AliRtcVideoTrackCamera);
}
入会
入会后会按照入会前的参数进行对应的推流和拉流。
默认SDK会自动推拉流,减少客户需要调用的API。
initEngineBeforeJoin();
mAliRtcEngine.joinChannel("您的鉴权信息", null, null, "testUserName");
离会
mAliRtcEngine.leaveChannel();
销毁引擎
mAliRtcEngine.destroy();
mAliRtcEngine = null;
效果展示
按照上面的代码集成完毕后,可以得到下面的结果,您可以根据自身业务需求进行调整。
其他API
更多API说明请参见AliRtcEngine接口。