Android 访客端demo集成(含UI库)

代码下载

您可以通过以下两种方式获取到源代码:

项目集成:详细内容参考demo

app模块主体类介绍:

  • LoginActivity:处理登录相关的逻辑,必须先登录环信服务器获取相关信息
  • SettingFragment:通过扫码配置appkey相关信息
  • CallActivity:视频通话页面(注意:V1.3.0版本采用此类进行唤起视屏通话页面)
  • Calling:视频通话页面,兼容画中画模式(注意:V1.3.1版本之后采用此类进行唤起视屏通话页面)
  • CallReceiver:用于接收视频邀请相关的信令
  • DemoApplication:继承Application类,需要在AndroidManifest.xml内指定
  • DemoHelper:初始化相关信息配置和注册
  • HMSPushHelper:配置华为HMS推送相关的工具类

kefu-easeui模块主体类介绍:

  • ChatFragment:聊天界面,app也可继承此fragment续写,参数传入示例可查看demo里的ChatActivity
  • AgoraRtcEngine:音视频通话相关(基于声网sdk)

VECKit模块主体类介绍:

  • VECKitCalling:视频通话页面唤起类
  • CallVideoActivity:视频通话页面(没有赋予悬浮权限),普通效果
  • VideoCallWindowService:视频通话页面(已赋予悬浮权限),画中画效果
  • AgoraRtcEngine:音视频通话相关(基于声网sdk)

主要功能介绍

kefu-easeui模块:包含聊天、图片、表情、音视频相关内容的输入选择,可以实现自定义 音视频(基于声网音视频服务,使用环信 IM 作为信令通道的开源音视频模块)

相关音视频api介绍及使用如下:

创建视频引擎AgoraRtcEngine
/**
 * 创建视频数据
 * @param context Context
 * @param appId String
 * @param handler IAgoraRtcEngineEventHandler
 */
AgoraRtcEngine engine = AgoraRtcEngine.builder()
		.addVideoWatermark() // 该方法将一张 PNG 图片作为水印添加到本地发布的直播视频流上
		.setVideoEncodingDimension() // 视频编码像素。参数使用查看SDK里方法注解
		.setVideoEncoderConfiguration() // 视频编码属性的定义。参数使用查看SDK里方法注解
		.setRenderMode() // 设置视频渲染模式。参数使用查看SDK里方法注解
		.setMirrorMode() // 设置视频镜像模式。参数使用查看SDK里方法注解
		.setClientRole() // 设置直播场景下的用户角色。参数使用查看SDK里方法注解
		.setChannelProfile() // 设置频道场景。参数使用查看SDK里方法注解
		.build(getApplication(), "appid", new IAgoraRtcEngineEventHandler() {
	@Override
	public void onUserJoined(int uid, int elapsed) {
		// 有人员加入时回调
	}

@Override
	public void onJoinChannelSuccess(String channel, int uid, int elapsed) {
		// 自己加入成功时回调
	}

	@Override
	public void onLeaveChannel(RtcStats stats) {
		// 离开channel时回调
	}

	@Override
	public void onUserOffline(int uid, int reason) {
		// 人员离开时回调
	}
});


/**
 * 创建 RendererView视图
 *
 * 请在主线程调用该方法
 * @return SurfaceView
 */
engine.createRendererView();
engine.createRendererView(Context context);
/**
 * 初始化远端用户视图
 *
 * 如果 App 不能事先知道对方的用户 ID,可以在 APP 收到 onUserJoined 事件时设置。
 * 如果启用了视频录制功能,视频录制服务会做为一个哑客户端加入频道,因此其他客户端也会收到它的 onUserJoined 事件,
 * App 不应给它绑定视图(因为它不会发送视频流),如果 App 不能识别哑客户端,可以在 onFirstRemoteVideoDecoded 事件时再绑定视图。
 * 解除某个用户的绑定视图可以把 view 设置为空。退出频道后,SDK 会把远程用户的绑定关系清除掉。
 * 注意:请在主线程调用该方法。如果你希望在通话中更新远端用户的渲染或镜像模式,请使用 setRemoteRenderMode 方法
 * 如果你希望在通话中更新远端用户的渲染或镜像模式,请使用 setRemoteRenderMode 方法
 * @param videoCanvas VideoCanvas
 * @return 0: 方法调用成功。小于 0: 方法调用失败。
 */
engine.setupRemoteVideo(VideoCanvas videoCanvas);
engine.setupRemoteVideo(View surfaceView, int uid)
/**
 * 更新远端视图显示模式
 *
 * @param uid uid
 * @param renderMode 详细说明查看setRenderMode()方法注解
 * @param mirrorMode 详细说明查看setMirrorMode()方法
 * @return 0: 方法调用成功。小于 0: 方法调用失败。
 */
engine.setRemoteRenderMode(int uid, int renderMode, int mirrorMode);
/**
 * 启用视频模块
 *
 * 该方法用于打开视频模式。可以在加入频道前或者通话中调用,在加入频道前调用,则自动开启视频模式,在通话中调用则由音频模式切换为视频模式。调用 disableVideo 方法可关闭视频模式。
 * 成功调用该方法后,远端会触发 onUserEnableVideo(true) 回调
 * 该方法设置的是内部引擎为开启状态,在频道内和频道外均可调用,且在 leaveChannel 后仍然有效。
 * 该方法重置整个引擎,响应速度较慢,因此 Agora 建议使用如下方法来控制视频模块:
 * enableLocalVideo:是否启动摄像头采集并创建本地视频流
 * muteLocalVideoStream:是否发布本地视频流
 * muteRemoteVideoStream:是否接收并播放远端视频流
 * muteAllRemoteVideoStreams:是否接收并播放所有远端视频流
 * @return 0: 方法调用成功。小于 0: 方法调用失败
 */
engine.enableVideo();
/**
 * 关闭视频模块
 *
 * 该方法用于关闭视频。可以在加入频道前或者通话中调用,在加入频道前调用,则自动开启纯音频模式,在通话中调用则由视频模式切换为纯音频频模式。调用 enableVideo 方法可开启视频模式。
 * 成功调用该方法后,远端会触发 onUserEnableVideo(false) 回调。
 * 该方法设置的是内部引擎为禁用状态,在频道内和频道外均可调用,且在 leaveChannel 后仍然有效。
 * 该方法重置整个引擎,响应速度较慢,因此 建议使用如下方法来控制视频模块:
 * enableLocalVideo:是否启动摄像头采集并创建本地视频流
 * muteLocalVideoStream:是否发布本地视频流
 * muteRemoteVideoStream:是否接收并播放远端视频流
 * muteAllRemoteVideoStreams:是否接收并播放所有远端视频流
 * @return 0: 方法调用成功。小于 0: 方法调用失败
 */
engine.disableVideo();
/**
 * 启用音频模块(默认为开启状态)
 *
 * 该方法设置的是音频模块为开启状态,在频道内和频道外均可调用,且在 leaveChannel 后仍然有效
 * 该方法开启整个音频模块,响应速度较慢,因此建议使用如下方法来控制音频模块:
 * enableLocalAudio:是否启动麦克风采集并创建本地音频流。
 * muteLocalAudioStream:是否发布本地音频流。
 * muteRemoteAudioStream:是否接收并播放远端音频流。
 * muteAllRemoteAudioStreams:是否接收并播放所有远端音频流。
 * @return 0: 方法调用成功。小于 0: 方法调用失败
 */
engine.enableAudio();
/**
 * 关闭音频模块
 *
 * 该方法设置的是音频模块为禁用状态,在频道内和频道外均可调用,且在 leaveChannel 后仍然有效
 * 该方法关闭整个音频模块,响应速度较慢,因此建议使用如下方法来控制音频模块
 * enableLocalAudio:是否启动麦克风采集并创建本地音频流。
 * muteLocalAudioStream:是否发布本地音频流。
 * muteRemoteAudioStream:是否接收并播放远端音频流。
 * muteAllRemoteAudioStreams:是否接收并播放所有远端音频流。
 * @return 0: 方法调用成功。小于 0: 方法调用失败
 */
engine.disableAudio();
/**
 * 开启/关闭本地音频采集。
 *
 * 当 app 加入频道时,它的语音功能默认是开启的。该方法可以关闭或重新开启本地语音,即停止或重新开始本地音频采集
 * 该方法不影响接收远端音频流,enableLocalAudio(false) 适用于只听不发的用户场景。
 * 语音功能关闭或重新开启后,会收到回调 onLocalAudioStateChanged ,并报告 LOCAL_AUDIO_STREAM_STATE_STOPPED(0) 或 LOCAL_AUDIO_STREAM_STATE_CAPTURING(1)
 * 该方法与 muteLocalAudioStream 的区别在于:
 * enableLocalAudio 开启或关闭本地语音采集及处理。使用 enableLocalAudio 关闭或开启本地采集后,本地听远端播放会有短暂中断。
 * muteLocalAudioStream 停止或继续发送本地音频流。
 * @param enabled 是否开启
 * @return 0: 方法调用成功。小于 0: 方法调用失败。
 */
engine.enableLocalAudio(boolean enabled);
/**
 * 取消或恢复订阅指定远端用户的音频流
 *
 * 该方法需要在加入频道后调用
 * @param uid 指定用户的用户 ID
 * @param muted 是否取消订阅指定远端用户的音频流,true:取消订阅。false:(默认)订阅
 * @return 0: 方法调用成功。小于 0: 方法调用失败
 */
engine.muteRemoteAudioStream(int uid, boolean muted);
/**
 * 取消或恢复订阅所有远端用户的音频流
 *
 * 成功调用该方法后,本地用户会取消或恢复订阅所有远端用户的音频流,包括在调用该方法后加入频道的用户的音频流
 * @param muted 是否取消订阅所有远端用户的音频流。true: 取消订阅。false:(默认)订阅
 * @return 0: 方法调用成功。小于 0: 方法调用失败
 */
engine.muteAllRemoteAudioStreams(boolean muted);
/** 
 * 取消或恢复发布本地音频流
 *
 * 该方法仅设置用户在 RtcChannel 频道中的音频发布状态。
 * 成功调用该方法后,远端会触发 onRemoteAudioStateChanged 回调。
 * 同一时间,本地的音视频流只能发布到一个频道。如果你创建了多个频道,请确保你只在一个频道中调用 muteLocalAudioStream(false),否则方法会调用失败并返回 -5 (ERR_REFUSED)。
 * @param muted 是否取消发布本地音频流,true:取消发布,false:发布
 * @return 0: 方法调用成功。小于 0: 方法调用失败。-5 (ERR_REFUSED):调用被拒绝
 */
engine.muteLocalAudioStream(boolean muted);
/**
 * 开启/关闭扬声器播放
 *
 * 你可以调用 setEnableSpeakerphone 切换当前的音频路由。 成功切换音频路由后,SDK 会触发 onAudioRouteChanged 回调提示音频路由已更改。
 * 该方法只设置用户在当前频道内使用的音频路由,不会影响 SDK 默认的音频路由。 如果用户离开当前频道并加入新的频道,则用户还是会使用 SDK 默认的音频路由
 * 该方法需要在 joinChannel 后调用。
 * 如果用户使用了蓝牙耳机、有线耳机等外接音频播放设备,则该方法的设置无效,音频只会通过外接设备播放。当有多个外接设备时,音频会通过最后一个接入的设备播放。
 * @param enabled 设置是否开启扬声器播放,true:开启。音频路由为扬声器。false:关闭。音频路由为听筒。
 * @return 0:方法调用成功。小于 0:方法调用失败
 */
engine.setEnableSpeakerphone(boolean enabled);
/**
 * 取消或恢复发布本地视频流。
 *
 * 成功调用该方法后,远端会触发 onUserMuteVideo 回调。
 * 同一时间,本地的音视频流只能发布到一个频道。如果你创建了多个频道,请确保你只在一个频道中调用 muteLocalVideoStream(false), 否则方法会调用失败并返回 -5 (ERR_REFUSED)。
 * 该方法不会改变视频采集设备的使用状态。该方法的调用是否生效受 joinChannel 和 setClientRole 方法的影响
 * @param muted 是否取消发布本地视频流。true:取消发布。false:发布。
 * @return 0:方法调用成功。小于 0:方法调用失败。-5 (ERR_REFUSED):调用被拒绝
 */
engine.muteLocalVideoStream(boolean muted);
/**
 * 切换前置/后置摄像头。
 *
 * 该方法需要在相机启动(如通过调用 startPreview 或 joinChannel 实现)后调用。
 * @return 0: 方法调用成功。小于 0: 方法调用失败。
 */
engine.switchCamera();
/**
 * 使用 uid 加入频道
 *
 * 该方法不支持相同的用户重复加入同一个频道,如果想要从不同的设备同时接入同一个频道,请确保每个设备上使用的 UID 是不同的
 * 请确保用于生成 Token 的 App ID 和创建 IRtcEngine 对象时用的 App ID 一致
 * @param token 在 app 服务端生成的用于鉴权的 Token
 * @param channelName 要加入的渠道名
 * @param optionalUid 用户 ID,32 位无符号整数。建议设置范围:1 到 (232-1),并保证唯一性。如果不指定(即设为 0),SDK 会自动分配一个, 并在 onJoinChannelSuccess 回调方法中返回,App 层必须记住该返回值并维护,SDK 不对该返回值进行维护
 * @return 0:调用成功,小于 0:方法调用失败
 * 调用失败将返回如下:
 * ERR_INVALID_ARGUMENT(-2)
 * ERR_NOT_READY(-3)
 * ERR_REFUSED(-5)
 * ERR_NOT_INITIALIZED(-7)
 * ERR_JOIN_CHANNEL_REJECTED(-17):加入频道被拒绝。由于 SDK 不支持用户重复加入同一个 RtcChannel 频道, 当已经加入某个 RtcChannel 频道的用户再次调用该 RtcChannel 对象的加入频道方法时,会返回此错误码
 */
engine.joinChannel(String token, String channelName, int optionalUid);
/**
 *  使用 uid 加入频道
 *
 * 该方法不支持相同的用户重复加入同一个频道,如果想要从不同的设备同时接入同一个频道,请确保每个设备上使用的 UID 是不同的
 * 请确保用于生成 Token 的 App ID 和创建 IRtcEngine 对象时用的 App ID 一致
 * @param token 在 app 服务端生成的用于鉴权的 Token
 * @param channelName 要加入的渠道名
 * @param optionalInfo 开发者需加入的任何附加信息。一般可设置为空字符串,或频道相关信息。该信息不会传递给频道内的其他用户。
 * @param optionalUid 用户 ID,32 位无符号整数。建议设置范围:1 到 (232-1),并保证唯一性。如果不指定(即设为 0),SDK 会自动分配一个, 并在 onJoinChannelSuccess 回调方法中返回,App 层必须记住该返回值并维护,SDK 不对该返回值进行维护
 * @param options 频道媒体设置选项:ChannelMediaOptions
 * @return 0:调用成功,小于 0:方法调用失败
 * 调用失败将返回如下:
 * ERR_INVALID_ARGUMENT(-2)
 * ERR_NOT_READY(-3)
 * ERR_REFUSED(-5)
 * ERR_NOT_INITIALIZED(-7)
 * ERR_JOIN_CHANNEL_REJECTED(-17):加入频道被拒绝。由于 SDK 不支持用户重复加入同一个 RtcChannel 频道, 当已经加入某个 RtcChannel 频道的用户再次调用该 RtcChannel 对象的加入频道方法时,会返回此错误码
 */
engine.joinChannel(String token, String channelName, String optionalInfo, int optionalUid, ChannelMediaOptions options);
/**
 * 离开当前频道
 *
 * 成功调用该方法离开频道后,会触发如下回调:
 * 本地:onLeaveChannel.
 * 远端:通信场景下的用户和直播场景下的主播离开频道后,触发 onUserOffline。
 * @return 0:方法调用成功。小于 0:方法调用失败
 */
engine.leaveChannel();
接听通话
/**
 * 接听通话
 */
engine.joinChannel(String token, String channelName, int uid)
发起视频通话
/**
 * 发起视频通话
 * @param chatInviteShoe msg内容
 * @param toChatUsername IM服务号
 */
ChatClient.getInstance().callManager().callVideo(String chatInviteShoe, String toChatUsername);
拒绝接听
/**
 * 拒接视频
 * @param callId callId
 * @param isConnected 是否已接通,false未接通
 */
ChatClient.getInstance().callManager().endCall(int callId, boolean isConnected);
拒绝接听
/**
 * 挂断视频
 * @param callId callId
 * @param isConnected 是否已接通,true接通
 */
ChatClient.getInstance().callManager().endCall(int callId, boolean isConnected);
/**
 * V1.3.1版本之后才可以使用此方法,需要悬浮权限,授予权限将会实现悬浮效果
 * 主动唤起视频页面(访客端发起会话到座席端)
 * @param context
 */
Calling.callingRequest(Context context);
/**
 * V1.3.1版本之后才可以使用此方法,需要悬浮权限,授予权限将会实现悬浮效果
 * 被动唤起视频页面(座席端发起会话到访客端)
 * @param context
 * @param intent
 */
Calling.callingResponse(Context context, Intent intent);

音视频(基于声网音视频服务,使用环信 IM 作为信令通道的开源音视频模块)相关详细方法及参数说明参考声网api地址:https://docs.agora.io/cn/Interactive%20Broadcast/API%20Reference/java/index.html

VECKit 模块音视频主要方法介绍

VECKit 模块(新版VEC)音视频(基于声网音视频服务,使用环信 IM 作为信令通道的开源音视频模块)

相关音视频api介绍及使用如下:

主动发送视频邀请信令(唤起视图页面)

// 主动向坐席发送信令(发送信令并且唤起视频视图)
VECKitCalling.callingRequest(Context context, String toChatUserName);
// 主动向坐席发送信令(只发送信令)
ChatClient.getInstance().callManager().callVecVideo(String content, String toChatUsername)

挂断视频信令

/**
 * 主动发起视频邀请,坐席未接通状态。主动发送挂断信令
 */
VECKitCalling.endCallFromOff();

/**
  * 视频已接通。发送挂断信令
  * @param callBack 回调函数
  */
VECKitCalling.endCallFromOn(ValueCallBack<String> callBack);

/**
 * 坐席发起视频邀请,访客未接通状态。访客发送挂断信令
 * @param content 显示内容
 */
VECKitCalling.endCallFromZuoXi(String content);

被动接收到信令(唤起视图页面)

// 接收到坐席发来的信令(发送信令并且唤起视图)
VECKitCalling.callingResponse(Context context, Intent intent);
// 接收到坐席发来的信令(只发送信令)
/**
  * 坐席发起视频邀请。访客发送接通信令
  * @param content 显示内容
  */
VECKitCalling.acceptCallFromZuoXi(String content);
// 接收到坐席发来的信令,唤起满意度评价视图
VECKitCalling.callingRetry(Context context, String content);

详情使用请参考demo

音视频(基于声网音视频服务,使用环信 IM 作为信令通道的开源音视频模块)相关详细方法及参数说明参考声网api地址:https://docs.agora.io/cn/Interactive%20Broadcast/API%20Reference/java/index.html