====== Android 访客端demo集成(含UI库) ======
* 为了方便您快速了解我们的访客端SDK所提供的各种能力,我们对外开放了访客端集成Demo的全部源码,里面包含了对话过程中的业务处理及上层UI库;
* 通过这个Demo源码,可以帮助产品人员快速了解我们的访客端功能,可以帮助研发人员快速了解集成技术逻辑,帮助测试人员通过对比demo和您自己的app,更快定位问题;
* 我们的访客端Demo里提供了一整套UI,您可以直接使用这套UI,当然我们更建议您用作参考,根据您的APP风格和实际业务场景,设计您自己的一套UI和业务使用流程,减少访客在使用您app过程中所产生的割裂感;
* 在SDK集成过程中,针对您遇到的问题我们建议您先对比下Demo里的处理逻辑,帮助您快速解决您遇到的问题,如果Demo仍无法解答您心中的疑惑,请直接联系我们商务或技术支持,我们会全力为您提供所需要的帮助!
==== Demo源码下载 ====
您可以通过如下方式获取到源代码:
* 下载代码压缩包:客服云sdk 及 Demo 下载 http://www.easemob.com/download/cs
{{:cs:300visitoraccess:客服云-安卓端demo下载.png?nolink|}}
==== 访客端Demo使用 ====
当您在手机上安装完访客端demo应用后,首次使用需先经过简单的扫码配置,然后就可以开始发起正常对话了,详细说明如下:
{{:cs:300visitoraccess:客服云-安卓端demo下载后使用配置.png?nolink|}}
==== 访客端Demo与您自己APP的区别 ====
访客端Demo与客户的APP以及SDK之间的关系说明如下:
* 对象不同:我们的demo主要供产品、研发、测试等内部使用,便于了解功能的,您的APP是面对终端用户的;
* 使用不同:我们访客端Demo是不上架应用商店,您的App是需要上架到各大应用商店提供给访客下载的;
* 功能不同:我们访客端Demo仅提供的是对话的功能,您的APP里一般都是实现各种例如零售、维修、娱乐等各种功能,对话功能只是对于您的app里的一项补充能力;
{{:cs:300visitoraccess:客服云-安卓端demo与sdk的区别.png?nolink|}}
==== 项目集成:详细内容参考demo ====
**app模块主体类介绍:**
* LoginActivity:处理登录相关的逻辑,必须先登录环信服务器获取相关信息
* SettingFragment:通过扫码配置appkey相关信息
* CallReceiver:用于接收视频邀请相关的信令
* DemoApplication:继承Application类,需要在AndroidManifest.xml内指定
* DemoHelper:初始化相关信息配置和注册
* HMSPushHelper:配置华为HMS推送相关的工具类
**kefu-easeui模块主体类介绍:**
* ChatFragment:聊天界面,app也可继承此fragment续写,参数传入示例可查看demo里的ChatActivity
**VideoKit模块主体类介绍(在线视频):**
* Calling:视频通话页面唤起类
* CallActivity:视频通话页面(没有赋予悬浮权限),普通效果
* VideoCallWindowService:视频通话页面(已赋予悬浮权限),画中画效果
* AgoraRtcEngine:音视频通话相关(基于声网sdk)
**VECKit模块主体类介绍(VEC视频):**
* VECKitCalling:视频通话页面唤起类
* CallVideoActivity:视频通话页面(没有赋予悬浮权限),普通效果
* VideoCallWindowService:视频通话页面(已赋予悬浮权限),画中画效果
* AgoraRtcEngine:音视频通话相关(基于声网sdk)
==== 初始化注意事项 ====
在项目Application类的onCreate方法里调用如下方法:
// VEC视频用到
AppStateVecCallback.init(this);
// CEC视频用到
AppStateCecCallback.init(this);
// UI库里用到
EaseUiStateUtils.getEaseUiStateUtils().init(this);
==== 其它注意事项 ====
如果使用到询前引导发起视频功能,需要到Demo里拷贝GuideMenuUtils类文件到自己项目里,在对应聊天页面里调用如下方法:
// 聊天页面创建时,需要注册
GuideMenuUtils.getGuideMenuUtils().registerReceiver(getContext());
// 聊天页面关闭时,需要取消注册
GuideMenuUtils.getGuideMenuUtils().unregisterReceiver(getContext());
如果用户自己实现聊天页面,需要在打开聊天页面和关闭聊天页面时调用如下两个方法(如下两个方法目前已经集成在kefu-easeui模块ChatFragment类里面,自行修改)
进入到聊天页面时调用:开启在线上报
EaseUiReportUtils.getEaseUiReportUtils().startReport(im服务号); // ChatFragment类onStart()方法里
关闭聊天页面时调用:停止在线上报
EaseUiReportUtils.getEaseUiReportUtils().closeReport(); // ChatFragment类onDestroyView()方法里
注意:根据自己业务场景是否需要在自己聊天页面里上报,UI库里已经调用此方法,如果自己实现的聊天页面需要用户到kefu-easeui模块ChatFragment类里面注释掉上报代码,在自己聊天页面里进行调用
==== kefu-easeui模块说明 ====
注意:当使用到环信kefu-easeui模块时,在ChatFragment类里已经添加如下功能,不需要用户自己调用
// 自定义表情通知
ChatClient.getInstance().emojiconManager().addDelegate(this);
ChatClient.getInstance().emojiconManager().removeDelegate(this);
// 进入到聊天页面时调用
ChatClient.getInstance().chatManager().bindChat(toChatUsername);
ChatClient.getInstance().chatManager().unbindChat();
// 添加座席端输入状态
ChatClient.getInstance().chatManager().addAgentInputListener(agentInputListener);
ChatClient.getInstance().chatManager().removeAgentInputListener(agentInputListener);
// 待接入时获取等待数
ChatClient.getInstance().chatManager().addVisitorWaitListener(visitorWaitListener);
ChatClient.getInstance().chatManager().removeVisitorWaitListener(visitorWaitListener);
// 获取机器人欢迎语,默认在ChatFragment类里requestRobotWelcome()方法里对数据进行处理刷新页面显示
ChatFragment类 requestRobotWelcome()方法,方法默认被注释掉,需要用户自行调用。如果自己调用获取机器人欢迎语接口时需要参考requestRobotWelcome()方法处理结果以及更新屏幕显示
==== VideoKit在线音视频模块主要功能介绍 ====
音视频(基于声网音视频服务,使用环信 IM 作为信令通道的开源音视频模块)
**注册视频信令广播(demo里CallReceiver广播类)**
IntentFilter callFilter = new IntentFilter(ChatClient.getInstance().callManager().getIncomingCallBroadcastAction());
callFilter.addAction("calling.state");
CallReceiver callReceiver = new CallReceiver();
// register incoming call receiver
context.registerReceiver(callReceiver, callFilter);
=====主动发送视频邀请:=====
// 只是唤起视图页面,需要单独发送视频邀请信令
Calling.callingRequest(context(), toChatUsername);
// 发送视频邀请信令
ChatClient.getInstance().callManager().callVideo(msg, toChatUsername);
=====被动收到访客视频邀请信令,唤起视频页面:=====
/**
* V1.3.1版本之后才可以使用此方法,需要悬浮权限,授予权限将会实现悬浮效果
* 被动唤起视频页面(座席端发起会话到访客端)
* @param context
* @param intent
*/
Calling.callingResponse(Context context, Intent intent);
=====相关音视频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);
发送视频通话信令
/**
* 发送视频通话信令
* @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);
音视频(基于声网音视频服务,使用环信 IM 作为信令通道的开源音视频模块)相关详细方法及参数说明参考声网api地址:https://docs.agora.io/cn/Interactive%20Broadcast/API%20Reference/java/index.html
===== VECKit 模块音视频主要方法介绍 =====
VECKit 模块(新版VEC)音视频(基于声网音视频服务,使用环信 IM 作为信令通道的开源音视频模块)
**相关音视频api介绍及使用如下:**
==== 注册视频信令广播(demo里CallReceiver广播类) ====
IntentFilter callFilter = new IntentFilter(ChatClient.getInstance().callManager().getIncomingCallBroadcastAction());
callFilter.addAction("calling.state");
CallReceiver callReceiver = new CallReceiver();
// register incoming call receiver
context.registerReceiver(callReceiver, callFilter);
==== 主动发送视频邀请信令同时唤起视频视图 ====
// 主动向坐席发送信令(发送信令并且唤起视频视图)
VECKitCalling.callingRequest(Context context, String toChatUserName);
==== 被动接收到视频邀请信令同时唤起视图页面 ====
// 接收到坐席发来的信令(发送信令并且唤起视图)
VECKitCalling.callingResponse(Context context, Intent intent);
==== 唤起满意度评价视图 ====
// 接收到坐席发来的信令,唤起满意度评价视图
VECKitCalling.callingRetry(Context context, String content);
==== 初始化相关操作 ====
/**
* 注册Vec视频通知
* @param classKey 当前类名。当调用unRegisterVecMessageNotify方法释放时传入相同类名
* @param message IVecMessageNotify接口,通知回调:
* zuoXiSendThreeUserRequest(ZuoXiSendRequestObj obj)当座席端邀请第三方用户加入时,回调此方法
* createFlatRoom(ZuoXiSendRequestObj obj) 创建电子白板房间时,回调此方法
*/
AgoraMessage.newAgoraMessage().registerVecMessageNotify(String classKey, IVecMessageNotify message);
/**
* 注销通知
* @param classKey 当前类名。registerVecMessageNotify方法传入相同类名
*/
AgoraMessage.newAgoraMessage().unRegisterVecMessageNotify(String classKey);
// 创建引擎
AgoraRtcEngine agoraRtcEngine = AgoraRtcEngine.builder().build(Context context, String appId, IRtcEngineEventHandler handler)
// 设置自己窗口视图
agoraRtcEngine.setupLocalVideo(surfaceView, AgoraRtcEngine.RENDER_MODE_HIDDEN, obj.getUid());
// 加入房间
agoraRtcEngine.joinChannel(obj.getToken(), obj.getChannel(), obj.getUid());
*注:详情参数设置参考demo
==== 主动发送视频邀请信令 ====
// 主动向坐席发送信令(只发送信令)
ChatClient.getInstance().callManager().callVecVideo(String content, String toChatUsername)
==== 挂断视频信令 ====
/**
* 主动发起视频邀请,坐席未接通状态。主动发送挂断信令
*/
VECKitCalling.endCallFromOff();
/**
* 视频已接通。发送挂断信令
* @param callBack 回调函数
*/
VECKitCalling.endCallFromOn(ValueCallBack callBack);
/**
* 坐席发起视频邀请,访客未接通状态。访客发送挂断信令
* @param content 显示内容
*/
VECKitCalling.endCallFromZuoXi(String content);
==== 发送接通视频信令(只发送信令) ====
// 发送接通视频信令(只发送信令)
/**
* 坐席发起视频邀请。访客发送接通信令
* @param content 显示内容
*/
VECKitCalling.acceptCallFromZuoXi(String content);
==== 智能辅助相关信令 ====
// 注册接口,接收vec相关信令
AgoraMessage.newAgoraMessage().registerVecPushMessage(String classKey, IPushMessage callback);
// 释放接口
AgoraMessage.newAgoraMessage().unRegisterVecPushMessage(String classKey);
/**
* 智能辅助(手电筒):通知坐席端开启手电筒的状态
* @param isOk 是否开启成功:true开启成功,false开启失败
* @param msg 内容(通知坐席端开启失败的原因,如果isOK指定为true,msg传入"")
*/
AgoraMessage.sendFlashLight(boolean isOk, String msg);
/**
* 智能辅助(闪光灯):通知坐席端开启光灯的状态
* @param isOk 是否开启成功:true开启成功,false开启失败
* @param msg 内容(通知坐席端开启失败的原因,如果isOK指定为true,msg传入"")
*/
AgoraMessage.sendCameraTorch(boolean isOk, String msg);
/**
* 智能辅助(聚焦):通知坐席端开启的状态
* @param msg 内容(通知坐席端聚焦失败的原因,聚焦成功msg传入"")
*/
AgoraMessage.sendCameraFocus(String msg);
/**
* 智能辅助(麦克风):通知坐席端开启的状态
* @param msg 内容(通知坐席端开启失败的原因,麦克风开启成功msg传入"")
*/
AgoraMessage.sendMicrophone(String msg);
/**
* 智能辅助(相机):通知坐席端开启的状态
* @param msg 内容(通知坐席端开启失败的原因,相机开启成功msg传入"")
*/
AgoraMessage.sendCamera(String msg);
/**
* 智能辅助(切换相机):通知坐席端切换的状态
* @param msg 内容(通知坐席端切换相机失败的原因,切换相机成功msg传入"")
*/
AgoraMessage.sendChangeCamera(String msg);
详情使用请参考demo
音视频(基于声网音视频服务,使用环信 IM 作为信令通道的开源音视频模块)相关详细方法及参数说明参考声网api地址:https://docs.agora.io/cn/Interactive%20Broadcast/API%20Reference/java/index.html