有些开发者还在用Eclipse或者在用jar的方式,自己写UI,那样就要用到下面的集成文档。
从环信官网下载 Android客服访客端SDK。
下载后有三个目录:
在AndroidManifest.xml中配置需要的权限:
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" />
<uses-feature android:glEsVersion="0x00020000" android:required="true" />
<uses-permission android:name="com.android.launcher.permission.READ_SETTINGS" />
<!-- 这个权限用于进行网络定位 -->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<!-- 这个权限用于访问GPS定位 -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<!-- 用于访问wifi网络信息,wifi信息会用于进行网络定位 -->
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<!-- 获取运营商信息,用于支持提供运营商信息相关的接口 -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<!-- 用于读取手机当前的状态 -->
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<!-- 写入扩展存储,向扩展卡写入数据,用于写入离线定位数据 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<!-- 访问网络,网络定位需要上网 -->
<uses-permission android:name="android.permission.INTERNET" />
<!-- 听筒和扬声器模式切换 -->
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>
<!-- 震动 -->
<uses-permission android:name="android.permission.VIBRATE" />
<!-- 录制语音 -->
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<!-- 拍照 -->
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
<uses-permission android:name="android.permission.GET_TASKS" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.BROADCAST_STICKY" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
<!-- 音视频 -->
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<!-- 声明sdk所需的service -->
<service
android:name="com.hyphenate.chat.EMChatService"
android:exported="true"
tools:ignore="ExportedService" />
<service android:name="com.hyphenate.chat.EMJobService"
android:permission="android.permission.BIND_JOB_SERVICE"
android:exported="true"
/>
<!-- 声明sdk所需的receiver -->
<receiver android:name="com.hyphenate.chat.EMMonitorReceiver">
<intent-filter>
<action android:name="android.intent.action.PACKAGE_REMOVED" />
<data android:scheme="package" />
</intent-filter>
<!-- 可选filter -->
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.USER_PRESENT" />
</intent-filter>
</receiver>
ChatClient.Options options = new ChatClient.Options();
options.setAppkey("app渠道的appkey"); // 可以在管理员模式的APP渠道中找到自己的关联
options.setTenantId("自己的tenantid"); // 租户ID可以在管理员模式的企业信息里面查看
options.showAgentInputState().showVisitorWaitCount();// 打开排队人数和坐席输入状态提示功能(可选)
//增加GCM推送,对于国外的APP可能比较需要
// options.setGCMNumber("****");
//在小米手机上当app被kill时使用小米推送进行消息提示,SDK已支持,可选
options.setMipushConfig(String mipushAppid, String mipushAppKey);
//设为调试模式,打成正式包时,最好设为false,以免消耗额外的资源
options.setConsoleLog(boolean enable);
登录前可检测当前是否为已登录状态:
ChatClient.getInstance().isLoggedInBefore() // 如果已经是登录状态则不需要再次登录,
ChatClient.getInstance().currentUserName() //获取当前登录的用户名,例如当前已经登录非自己的用户,可以先调用退出然后再调用登录操作
ChatClient.getInstance().login(final String userName, String password,
final Callback callback) //异步登录方法
ChatClient.getInstance().logout(boolean unbindToken, final Callback callback) //退出方法,unBindToken是解绑设备推送的token,需要网络,如果true无网络会返回失败,如果也希望能够退出则可以把unbindToken设置false
// 在聊天界面,的onCreate方法中调用绑定IM服务号,让SDK知道你要给发消息的IM服务号
ChatClient.getInstance().chatManager().bindChat(final String toChatUsername)
// 在聊天界面,的onDestory方法中调用解绑IM服务号,当SDK知道目前你没有再收发消息
ChatClient.getInstance().chatManager().unbindChat()
Message message = Message.createTxtSendMessage(String content, String toUserName) //发送文本消息 toUserName为IM服务号,content为具体内容,
message = Message.createVoiceSendMessage(String filePath, int timeLength, String toUserName) //发送语音消息
message = Message.createImageSendMessage(String filePath, boolean sendOriginalImage, String toUserName) // 发送图片消息
message = Message.createVideoSendMessage(String filePath, String thumbImagePath, int fileLength, String toUserName) // 发送视频消息
message = Message.createLocationSendMessage(double latitude, double longitude, String locAddress, String toUserName) // 发送位置消息
message = Message.createFileSendMessage(String filePath, String toUserName) //发送文件消息
message = Message.createTranferToKefuMessage(String toUserName, ToCustomServiceInfo info) //发送转人工消息
message = Message.createVideoInviteSendMessage(String content, String toUserName) // 发送实时视频邀请消息
ChatClient.getInstance().chatManager().sendMessage(message, new Callback(){}); //发送消息
// 在onResume中调用 ChatClient.getInstance().chatManager().addMessageListener(this);
// 在onStop中调用 ChatClient.getInstance().chatManager().removeMessageListener(this);
// 并实现MessageListener监听
public interface MessageListener {
void onMessage(List<Message> msgs); // 收到普通的消息 (会存储数据库)
void onCmdMessage(List<Message> msgs); // 收到命令消息 (不存储数据库)
void onMessageStatusUpdate();
void onMessageSent();
}
Message msg = ChatClient.getInstance().chatManager().getMessage(msgId);//获取某个消息,
msg.getType() == Message.Type.CMD // 命令消息
EMCmdMessageBody body = (EMCmdMessageBody)msg.body();
String action = body.action();
msg.getType() == Message.Type.TXT // 文本消息
EMTextMessageBody body = (EMTextMessageBody)msg.body();
String message = body.getMessage(); // 具体消息内容
msg.getType() == Message.Type.IMAGE //图片消息
EMImageMessageBody body = (EMImageMessageBody)msg.body();
String fileName = body.getFileName(); // 图片名称
String remoteUrl = body.getRemoteUrl(); //图片服务器URL
String thumbnailUrl = body.getThumbnailUrl(); //缩略图服务器URL
String localPath = body.getLocalUrl();//图片本地URL
String thumbnailPath = body.thumbnailLocalPath(); // 缩略图本地URL
int height = body.getHeight();//图片高度
int width = body.getWidth();//图片宽度
msg.getType() == Message.Type.VOICE // 语音消息
EMVoiceMessageBody body = (EMVoiceMessageBody)msg.body();
int duration = body.getLength(); //录制的语音长度
String fileName = body.getFileName(); //文件名
String localPath = body.getLocalUrl();//本地语音地址
String remoteUrl = body.getRemoteUrl();// 服务器语音地址
msg.getType() == Message.Type.FILE // 文件消息
EMFileMessageBody body = (EMFileMessageBody)msg.body();
String fileName = body.getFileName(); // 文件名称
String localPath = body.getLocalUrl(); // 本地文件路径
String remoteUrl = body.getRemoteUrl(); // 远程服务器文件地址
IntentFilter callFilter = new IntentFilter(ChatClient.getInstance().callManager().getIncomingCallBroadcastAction());
if (callReceiver == null){
callReceiver = new CallReceiver(); //自己新建一个Receiever extends BroadcastReceiver 当接收到实时视频邀请时,会回调这里,
}
// register incoming call receiver
appContext.registerReceiver(callReceiver, callFilter);
ChatClient.getInstance().callManager().acceptCall(String nickName, final Callback callback) // 接受呼叫
ChatClient.getInstance().callManager().endCall(); // 挂断或者拒绝接听
ChatClient.getInstance().callManager().setLocalView(CallSurfaceView localSurface) //设置自己的视频View,
ChatClient.getInstance().callManager().setRemoteView(String streamId, CallSurfaceView callSurfaceView) //设置非自己的视频View
ChatClient.getInstance().callManager().pauseVideo() //关闭视频流
ChatClient.getInstance().callManager().resumeVideo(); // 打开视频流
ChatClient.getInstance().callManager().resumeVoice(); // 打开音频流
ChatClient.getInstance().callManager().pauseVoice(); // 关闭音频流
ChatClient.getInstance().callManager().subscribe(final EMediaStream stream, final CallSurfaceView videoView, final Callback callback) // 订阅某个流到对应视频View上
ChatClient.getInstance().callManager().unSubscribe(final EMediaStream stream, final Callback callback) // 取消订阅某个流
ChatClient.getInstance().callManager().addDelegate(this); // 添加视频监听, 需要在onCreate中调用
ChatClient.getInstance().callManager().removeDelegate(this); //取消视频监听, 需要在onDestory中调用
public interface CallManagerDelegate {
void onAddStream(MediaStream stream); // 当有流进来时回调,例如会议增加一个人
void onRemoveStream(MediaStream stream); // 当有流离开时回调,例如视频会议离开一个人
void onUpdateStream(MediaStream stream); // 当流的某个状态更改的回调,例如某个流关闭了视频或者音频流
void onCallEnd(int reason, String desc); // 当视频会议被关闭回调, 由于某种原因,需要关闭视频
void onNotice(HMediaNoticeCode code, String arg1, String arg2, Object arg3);
}