CEC Android SDK集成

环信客服云(Customer Engagement Cloud, CEC)现已推出专属 Android SDK!您只需在客服云创建 APP 关联,并按照本文档的步骤集成 Android SDK,即可轻松实现 Android 版 APP 接入。

SDK介绍

Android SDK 支持以下功能:

  • 发送文本消息、语音消息、图片消息、文件消息。
  • 接收文本消息、语音消息、图片消息、文件消息、机器人菜单消息。
  • 显示客服头像和昵称、显示机器人转人工按钮。
  • 显示访客信息,指定客服,指定技能组(参考第4步:集成更多业务功能)。
  • 支持留言功能,包括文字、图片和语音留言(参考第5步:集成更多扩展功能)。

客户端与服务端连接方式:

客户端与服务端的连接方式包含长连接(永久)和长连接(24小时)。长连接(永久)包含Socket通道,能够保证客户端无论是否在线,都能够收到消息和通知;长连接(24小时)是仅有24小时时效的长连接,同样包含Socket通道,在时效内与长连接拥有相同的通信能力。

环信客服云默认采用“长连接(24小时)”方式与Android/iOS客户端对接。“长连接(永久)”方式为增值服务,如需开通,请联系环信商务经理。

集成方式

CEC Android SDK 已集成双通道功能,确保不丢消息;并提供会话相关内置 UI,集成客服云通用功能,只需5分钟。本文档介绍如何使用Android Studio集成Android SDK。如果您还在使用Eclipse,请参考:CEC Android SDK集成(Eclipse)

关于如何同时集成IM和客服云功能,请参考:IM-SDK和客服SDK并存开发指南—Android篇

第1步:创建APP关联

环信客服云的“APP关联”对应即时通讯云(IM)后台的应用。在客服云创建关联后,可直接登录IM后台管理该关联对应的应用。

  • 如果您还没有环信即时通讯云的账号,可以打开环信客服云,进入“管理员模式 > 渠道管理 > 手机APP”,快速创建一个“APP关联”;
  • 如果您已有环信即时通讯云的账号并创建了应用,可以打开环信客服云(并使用客服云账号登录),进入“管理员模式 > 渠道管理 > 手机APP”,关联您的IM账号。

关于创建APP关联的分步骤演示,请参考:创建APP关联

第2步:环境准备

开发工具:Android Studio。

集成客服云Android SDK时,可参考“商城”demo源码和EaseUI源码。下载地址:https://github.com/easemob/kefu-android-demo

KefuSDK基于IMSDK3.x,如同时使用环信IM功能(非音视频),需使用此文档中的初始化、登录、登出操作,不需要添加IM的SDK,其IM SDK-API正常使用。

第3步:集成基础功能

客服云Android SDK已包含EaseUI,完成该步骤可以实现用户注册、登录、退出,向客服云发送文本、语音、图片、文件消息功能。

注意事项

  1. 自定义的Application需要在Androidmanifest.xml中注册;
  2. 切记,先判断登录状态再进入会话界面,否则会出问题,检测登录状态的方法:ChatClient.getInstance().isLoggedInBefore()

build.gradle 配置

添加客服云SDK及其他依赖。

在app的 build.gradle 文件的defaultConfig和dependencies中加入如下(添加后需同步gradle):

android{
   ......
   defaultConfig {
     ndk {
        //选择要添加的对应cpu类型的.so库
        abiFilters 'armeabi-v7a', 'arm64-v8a'
        //还可以添加 'armeabi', 'x86'
     }
   }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    //环信客服SDK,此版本过低,官网demo里为最新版本,详细查看新版集成方式
    compile 'com.hyphenate:kefu-easeui-android:latest.release' //或者 compile 'com.hyphenate:kefu-easeui-android:1.1.9r2'
    //EaseUI中 头像获取用到了glide,请添加glide库
    compile 'com.github.bumptech.glide:glide:4.7.1' //新版本会有异常,建议使用这个版本号
    //EaseUI中,fragment用到了android-support-v4包
    compile 'com.android.support:support-v4:23.1.1' 
}

注意:如果在添加以上abiFilter配置后AndroidStudio有如下提示:

NDK integration is deprecated in the current plugin. Consider trying the new experimental plugin.

则需要在Project根目录的gradle.properties文件中添加:

android.useDeprecatedNdk=true

另:如不用任何easeui的页面,自己写页面,也可以用纯SDK

lite版本(不含实时音视频):compile 'com.easemob:kefu-sdk-lite:1.1.9r2'
  av版本(含有实时音视频):compile 'com.easemob:kefu-sdk:1.1.9r2'

初始化

客服云Android SDK包含EaseUI,需要在Application中调用初始化的方法(本示例中Application的文件名为MyApplication.java):

  • 使用ChatClient方法对SDK进行初始化
  • 使用UIProvider方法对EaseUI进行初始化

ChatClient的其他方法也都需要在它后面调用。例如:本文档中的DebugMode(日志),以及Demo中的自定义通知栏、消息通知等。

public class MyApplication extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        ChatClient.Options options = new ChatClient.Options();
        options.setAppkey("Your appkey");//必填项,appkey获取地址:kefu.sh.easemob.com,“管理员模式 > 渠道管理 > 手机APP”页面的关联的“AppKey”
        options.setTenantId("Your tenantId");//必填项,tenantId获取地址:kefu.sh.easemob.com,“管理员模式 > 账户 > 账户信息 > 租户ID一栏的数据”
        
        // Kefu SDK 初始化
        if (!ChatClient.getInstance().init(this, options)){
            return;
        }
        // Kefu EaseUI的初始化
        UIProvider.getInstance().init(this);
        //后面可以设置其他属性
    }
}
//Kefu sdk 初始化简写方式:
  ChatClient.getInstance().init(this, new ChatClient.Options().setAppkey("zdxd#ksf").setTenantId("35"));

注:私有部署场景下,需要在初始化方法中额外配置服务器IP地址和端口,请参考:访客端SDK私有部署集成

自定义的Application需要在Androidmanifest.xml中注册。

<application
    ...
    android:name=".MyApplication"
    ...
</application>

注册

注册模式分两种,开放注册和授权注册。只有开放注册时,才可以客户端注册。

  • 开放注册是为了测试使用,正式环境中不推荐使用该方式注册环信账号;
  • 授权注册的流程应该是您服务器通过环信提供的 REST API 注册,之后保存到您的服务器或返回给客户端。

建议使用授权模式,即在服务端注册,而不要放到APP中,可以在登录自己APP时从返回的结果中获取环信账号再登录环信服务器。

ChatClient.getInstance().register("username", "password", new Callback(){});

//ErrorCode:
Error.NETWORK_ERROR 网络不可用
Error.USER_ALREADY_EXIST  用户已存在
Error.USER_AUTHENTICATION_FAILED 无开放注册权限(后台管理界面设置[开放|授权])
Error.USER_ILLEGAL_ARGUMENT 用户名非法

登录

用户需要登录后才能进入会话界面,与客服聊天。 可以采用账号密码登录,或 账号token登录。

ChatClient.getInstance().login("username", "password", new Callback(){});

ChatClient.getInstance().loginWithToken("username", "token", new Callback(){});

获取用户Token:根据username和password获取access_token。

Request body:

{
    "grant_type":"password",
    "username":"user",
    "password":"pwd"
}

Response示例

{
    "access_token": "YWMtI5JsbKhHEem57CF4KOxCxnljbbBGLhHpjpSjqzuD_CB4YttqkNER6YIJEZ8gpOpaAwMAAAFr_hTkLQBPGgB7xNZ6-mjCRkn_nivCNcB01uiyS9Yt9pdiU_6LH579zA",
    "expires_in": 5184000,
    "user": {
        "uuid": "7862db6a-90d1-11e9-8209-119f20a4ea5a",
        "type": "user",
        "created": 1560756495382,
        "modified": 1560765534117,
        "username": "test1",
        "activated": true,
        "device_token": "Getg6CgqFanQ4dwAvn9/qxoa5crWpNSkiVFcVt3eDr1S6xqz5X2sm0dbi1yNAQsl",
        "notifier_name": "2882303761517507836"
    }
}

登录状态

需要先判断登录状态再进入会话界面,否则会出问题。

if(ChatClient.getInstance().isLoggedInBefore()){
    //已经登录,可以直接进入会话界面
}else{
    //未登录,需要登录后,再进入会话界面
}

退出

登出后则无法收到客服发来的消息。

//第一个参数为是否解绑推送的devicetoken
ChatClient.getInstance().logout(true, new Callback(){});

日志

设置调试模式。

// 在ChatClient初始化的时候设置Option
// 设置为true后,将打印日志到logcat, 发布APP时应关闭该选项
ChatClient.getInstance().init(this, new ChatClient.Options().setConsoleLog(true|false));

会话

新建“联系客服”按钮,并调用以下方法打开会话界面。

注意:该方法中设置的“IM服务号”需要与初始化时设置的appkey对应。

注意: ServiceIMNumber(IM服务号)由于服务器忽略大小写,IM服务号必须是小写,在配置界面的IM服务号请使用小写

Intent intent = new IntentBuilder({Activity}.this)
    .setServiceIMNumber("客服关联的IM服务号") //获取地址:kefu.sh.easemob.com,“管理员模式 > 渠道管理 > 手机APP”页面的关联的“IM服务号”
    .build();
startActivity(intent);

界面引用了环信IM的EaseUI,您可以对界面进行修改,使用指南见EaseUI 使用指南

网络监听

添加网络监听,可以显示当前是否连接服务器。

ChatClient.getInstance().addConnectionListener(new ChatClient.ConnectionListener() {
    @Override
    public void onConnected() {
        //成功连接到服务器
    }

    @Override
    public void onDisconnected(int errorcode) {
        //errorcode的值
        //Error.USER_REMOVED 账号移除
        //Error.USER_LOGIN_ANOTHER_DEVICE 账号在其他地方登录
        //Error.USER_AUTHENTICATION_FAILED 账号密码错误
        //Error.USER_NOT_FOUND  账号找不到

    }
});

消息监听

添加消息监听。

ChatClient.getInstance().getChat().addMessageListener(new ChatManager.MessageListener() {
    @Override
    public void onMessage(List<Message> list) {
        //收到普通消息
    }

    @Override
    public void onCmdMessage(List<Message> list) {
        //收到命令消息,命令消息不存数据库,一般用来作为系统通知,例如留言评论更新,
        //会话被客服接入,被转接,被关闭提醒
    }

    @Override
    public void onMessageStatusUpdate() {
        //消息的状态修改,一般可以用来刷新列表,显示最新的状态
    }

    @Override
    public void onMessageSent() {
        //发送消息后,会调用,可以在此刷新列表,显示最新的消息
    }
});

添加Google FCM推送

- 服务端

1.登录Firebase管理后台

2.在Firebase欢迎界面点击 Add Project,输入相应内容并点击 Create Project

3.在Firebase欢迎界面选择 Add Firebase to your Android App

4.选择应用类型后需要输入包名、项目昵称、SHA-1,然后点击 Register App

5.进入引导页,如下图,点击按钮下载google-services.json文件到本地。注意该json文件在Android项目中的放置位置。

6.跳过引导页,点击Cloud Messaging tab页,复制Server Key和Sender ID。

7.登录环信管理后台,选择你的应用—选择推送证书—新增证书,证书的名称要求填上方复制Sender ID,证书秘钥填写上方复制的Server Key。

- 移动端

1.添加Google Play Service相关依赖库

用于检查设备是否支持Google Play Service,只有支持的设备才支持Google推送服务。

compile 'com.google.android.gms:play-services-base:11.4.2'该行配置添加到项目相应的build.gradle文件中,SDK demo中的配置在app/build.gradle中.

2. 在project-level的build.gradle中添加FCM相关库文件配置:

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        // 添加此行
        classpath 'com.google.gms:google-services:3.1.1'
    }
}

allprojects {
    repositories {
        // 添加此行
        maven { url 'https://maven.google.com' }
    }
}

3.在app-level的build.gradle中添加FCM相关库文件配置

dependencies {
// 添加此行,Google Firebase cloud messaging
    compile 'com.google.firebase:firebase-messaging:11.4.2'
    compile 'com.google.android.gms:play-services-base:11.4.2'
}

// 此行添加在文件末尾
apply plugin: 'com.google.gms.google-services'

注意:Google推送相关依赖库版本必须对应(该文档中均为:11.4.2),否则可能会出现类冲突的错误。

4.放置下载的google-services.json在app-level的根目录下

5.实现一个继承自FirebaseMessagingService的自定义service,该类用于FCM在后台进行接收应用推送消息的处理。并把该service注册到AndroidManifest.xml中。 自定义FirebaseMessagingService:

public class EMFCMMSGService extends FirebaseMessagingService {
    private static final String TAG = "EMFCMMSGService";

    @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {
        super.onMessageReceived(remoteMessage);
        if (remoteMessage.getData().size() > 0) {
            String message = remoteMessage.getData().get("alert");
            Log.i(TAG, "onMessageReceived: " + message);
        }
    }
}

AndroidManifest.xml:

<service android:name=".fcm.EMFCMMSGService">
    <intent-filter>
        <action android:name="com.google.firebase.MESSAGING_EVENT" />
    </intent-filter>
</service>

6.实现一个继承自FirebaseInstanceIdService的自定义service,该类用于监听FCM token的创建和更新。一个设备对应一个FCM token,该token用于服务端向该设备推送消息,所以该token创建或更新后需及时上传至环信服务器。

自定义FirebaseInstanceIdService:

public class EMFCMTokenRefreshService extends FirebaseInstanceIdService {
    private static final String TAG = "FCMTokenRefreshService";

    @Override
    public void onTokenRefresh() {
        super.onTokenRefresh();
        String token = FirebaseInstanceId.getInstance().getToken();
        Log.i(TAG, "onTokenRefresh: " + token);
        // Important, send the fcm token to the server
        ChatClient.getInstance().sendFCMTokenToServer(token);
    }
}

AndroidManifest.xml:

<service android:name=".fcm.EMFCMTokenRefreshService">
    <intent-filter>
        <action android:name="com.google.firebase.INSTANCE_ID_EVENT" />
    </intent-filter>
</service>

7.将Sender ID(即创建Google推送证书时填写的证书名称)在SDK初始化前通过options.setFCMNumber(string)接口设置到options里options.setFCMNumber(senderId)

8.使用 FCM 时需要在退出登录时解绑设备 token,调用ChatClient.getInstance().logout(true)或者ChatClient.getInstance().logout(true,callback)方法,如果是被踢的情况下,则要求设置为 false。

添加华为推送SDK1.1.6版本

为了方便用户自己升级华为推送相关sdk,客服 SDK 在1.1.6之后的版本中将华为推送相关从 SDK 中移除,同时提供对应的上传推送token接口供开发者调用,以后的版本就需要开发者自己去集成华为推送相关功能,然后调用下边的方法将 token 发送到环信服务器:

// 上传 token 方法
ChatClient.getInstance().sendHMSPushTokenToServer("华为appId", "注册华为的 token");

这是华为官方集成文档,开发者可以自己根据华为官方文档进行集成华为推送 华为消息推送服务集成官方文档

商城Demo也已经集成了华为最新推送 SDK,开发者也可以参考 demo 进行集成。

Demo 中将华为的 HMSAgent 做成了一个 module 进行引用(这里没有对华为 HMSAgent 进行任何封装和修改),开发者可以直接进行使用,也可以直接下载华为官方最新的HMSAgent自己进行集成。

Demo在集成华为推送时将调用华为推送的几个方法都放在了HMSPushHelper类中,开发者可以进行参考使用。

添加华为推送SDK1.1.5及之前版本

按照下面的说明集成 HMS 推送服务;

PS:集成时需要删除之前的华为jar包和推送代码,并下载新版HMS SDK引用到自己的项目中,其中BasePush两个库是必须的,其他的可以参考华为官方介绍自己决定是否添加。

创建华为应用

首先就是去华为开发者后台创建应用,并开启 push 服务,并上传对应的证书指纹,具体可以看下华为官方介绍: 华为HMS消息推送服务集成

上传推送证书

注册完整后,需要在环信开发者后台上传推送证书,选择你的应用—>推送证书—>Huawei—>新增证书,然后输入你在华为开发者后台创建的应用的APPIDAPP SECRET

注意: 一定要传包名,如不传包名,则无法推送到APP。

客户端配置 HMS

然后SDK 这里对 HMS 注册华为推送 token 进行了封装,集成时还是比较简单的,只需要在 AndroidManifest.xml 配置文件配置相关广播接收器和服务等: 记得设置自己的在华为开发者后台创建的应用的APP ID

PS:在自己实现广播接收器的时候必须继承自环信封装的那个广播接收器com.hyphenate.chat.EMHWPushReceiver,否则收不到环信的离线推送

<!--华为 HMS Config-->
        <!--华为开发者后台创建的应用的 APP ID-->
        <meta-data
            android:name="com.huawei.hms.client.appid"
            android:value="华为应用 APP ID" />
        <!--华为推送广播接收器,可以直接使用环信 sdk 封装好的,也可以继承自环信重写,如果继承自环信,实现 onToken 方法时必须要调用 super 方法-->
        <receiver android:name="com.hyphenate.chat.EMHWPushReceiver">
            <intent-filter>
                <!-- 必须,用于接收 TOKEN -->
                <action android:name="com.huawei.android.push.intent.REGISTRATION"/>
                <!-- 必须,用于接收消息 -->
                <action android:name="com.huawei.android.push.intent.RECEIVE"/>
                <!-- 可选,用于点击通知栏或通知栏上的按钮后触发 onEvent 回调 -->
                <action android:name="com.huawei.android.push.intent.CLICK"/>
                <!-- 可选,查看 PUSH 通道是否连接,不查看则不需要 -->
                <action android:name="com.huawei.intent.action.PUSH_STATE"/>
            </intent-filter>
        </receiver>

        <receiver android:name="com.huawei.hms.support.api.push.PushEventReceiver">
            <intent-filter>
                <!-- 接收通道发来的通知栏消息,兼容老版本 PUSH -->
                <action android:name="com.huawei.intent.action.PUSH"/>
            </intent-filter>
        </receiver>
        <!-- huawei push end -->

配置完这些之后,在满足条件的华为设备上就可以使用华为推送接收离线推送通知了。

故障排查

当开发者做完这些之后如果在华为设备上还是收不到推送,可以看下控制台的输出,或者环信 sdcard 上保存的日志,是否有一下日志输出:

// 当设备的华为移动服务版本比较低的时候,无法启用华为推送,会有以下输出
D/ONE SDK: [EMPushHelper] huawei mobile services is not available. please upgrade
// 当注册 token 时,华为开发者后台证书不对应,或者没有开通 Push 服务,当所有的都确认没问题后,如果还是有这样的问题,这个需要联系华为技术支持查看下是否生效
D/ONE SDK: hms service connection suspended. error: 6xxx 或 9xxxxxxxx

后边的 error 为华为官方错误码,更多错误码请参考华为官方错误表:表3-1 HMS 通用错误码及处理方式


更多厂家推送通道集成

可以参考IM部分的集成文档 第三方推送集成,使用下面的方式开启各厂商的推送:

ChatClient.Options options = new ChatClient.Options();

 // 你需要设置自己申请的账号来使用三方推送功能,详见集成文档
 EMPushConfig.Builder builder = new EMPushConfig.Builder(context);
 builder.enableVivoPush() // 需要在AndroidManifest.xml中配置appId和appKey
        .enableMeiZuPush("119943", "91163267c8784687804af6dd8e8fcf37")
        .enableMiPush("2882303761517507836", "5631750729836")
        .enableOppoPush("b08eb4a4b43f49799f45d136a5e2eabe", "52d5f8b887c14987bd306f6ffcd33044")
        .enableHWPush() // 需要在AndroidManifest.xml中配置appId
        .enableFCM("570662061026");      
        
 options.setPushConfig(builder.build());

打包混淆

混淆添加到proguard-rules.pro中。

#环信客服
-keep class com.hyphenate.** {*;}
-dontwarn  com.hyphenate.**

//如果使用了实时音视频功能
-keep class com.superrtc.** {*;}
-dontwarn  com.superrtc.**

#如添加华为push
# Huawei push
-keep class com.huawei.android.pushagent.** {*;}
-keep class com.huawei.android.pushselfshow.** {*;}
-keep class com.huawei.android.microkernel.** {*;}
-keep class com.baidu.mapapi.** {*;}
-keep class com.hianalytics.android.** {*;}
-dontwarn com.huawei.android.pushagent.**
-dontwarn com.huawei.android.pushselfshow.**
-dontwarn com.huawei.android.microkernel.**
-dontwarn com.github.mikephil.charting.data.**

恭喜您!您已完成 CEC Android SDK 基础功能的集成,用户可以使用您的 APP 给客服云发送文本、语音、图片、文件消息。

第4步:集成更多业务功能

完成该步骤可以实现将用户资料传递到客服云,将用户发起的会话直接分配给客服或技能组。

访客属性

传访客属性到客服云,将展示在“会话”面板的“资料”tab页。

管理员模式 >设置 > 功能设置 >允许访客端修改客户信息 要打开,nickName不能为空。

Intent intent = new IntentBuilder(this)
    .setServiceIMNumber("ceshia")
    .setVisitorInfo(ContentFactory.createVisitorInfo(null)
    .companyName("huanxin")
    .email("abc@123.com")
    .qq("12345")
    .name("visitor_" + userName)
    .nickName("nick_" + userName))//不可为空
    .build();
startActivity(intent);

指定客服

当用户点击“联系客服”按钮时,发起的会话直接分配给指定的客服。

Intent intent = new IntentBuilder(this)
    .setServiceIMNumber("ceshia")
    .setScheduleAgent(ContentFactory.createAgentIdentityInfo("zhangsan@qq.com")) //需填写正确的客服的邮箱地址
    .build();
startActivity(intent)

指定技能组

当用户点击“联系客服”按钮时,发起的会话直接分配给指定的技能组。

技能组名称须和客服系统设置的技能组名称完全一致,中英文均可。

Intent intent = new IntentBuilder(this)
    .setServiceIMNumber("ceshia")
    .setScheduleQueue(ContentFactory.createQueueIdentityInfo("售前")) //需填写正确的技能组名称
    .build();
startActivity(intent);

实时通话(实时视频)

实时通话分为视频通话和音频通话,与普通电话不同,它是基于网络的。

  • 监听呼入通话

通过注册相应 action 的 BroadcastReceiver 来监听呼叫过来的通话,接到广播后开发者可以调起 APP 里的通话 Activity。

IntentFilter callFilter = new IntentFilter(ChatClient.getInstance().callManager().getIncomingCallBroadcastAction());
registerReceiver(new CallReceiver(), callFilter);
private class CallReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        // 拨打方username
        String from = intent.getStringExtra("from");
        // call type
        String type = intent.getStringExtra("type");
                //跳转到通话页面
    }
}

更多实时音视频API请参考客服云Android SDK API

第5步:集成更多扩展功能

更多扩展功能(发送轨迹消息、发送订单消息、留言相关功能等),请参考客服云Android SDK API

“显示满意度评价邀请”功能可参考Android版商城demo集成。

SDK更新日志

版本更新信息请查看更新日志。

Android SDK(访客端) 更新日志