CEC Android SDK集成(Eclipse)

有些开发者还在用Eclipse或者在用jar的方式,自己写UI,那样就要用到下面的集成文档。

1. 下载SDK

环信官网下载 Android客服访客端SDK

下载后有三个目录:

  • kefu-android-demo 基于客服SDK开发的演示商城demo,可通过Android Studio直接打开
  • libs 为完整版本的客服SDK,内含实时音视频库,使用时把jar包和so都加入自有项目中的libs文件夹中
  • libs.without.audio 为轻量版客服SDK,和完整版的区别为不含有实时音视频库的其他所有功能,使用时把jar包和so都加入自有项目中的libs文件夹中

2. 配置权限

在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>

3. 初始化SDK

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);

4. 登录登出

登录前可检测当前是否为已登录状态:
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
                      

5. 绑定服务号

// 在聊天界面,的onCreate方法中调用绑定IM服务号,让SDK知道你要给发消息的IM服务号
   ChatClient.getInstance().chatManager().bindChat(final String toChatUsername)
   // 在聊天界面,的onDestory方法中调用解绑IM服务号,当SDK知道目前你没有再收发消息
   ChatClient.getInstance().chatManager().unbindChat()

6. 发送消息

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(){}); //发送消息

7. 收消息监听

// 在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();
    }

8. 消息详情

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(); // 远程服务器文件地址

9. 注册实时音视频广播

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);

10. 音视频API

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); 
	}