在您阅读此文档之前,我们假定您已经具备了基础的 Android 应用开发经验,并能够理解相关基础概念。
仓库地址:GitHub Android
ScreenShot

集成Mixdesk SDK
Environment Required
- JDK7+
AndroidStudio
在您的 build.gradle
文件中添加以下依赖:
implementation 'com.mixdesk:androidx:0.0.1'
implementation 'com.github.bumptech.glide:glide:4.9.0'
annotationProcessor 'com.github.bumptech.glide:compiler:4.9.0'
如果使用的是 glide 3.x,可以参考相关文档进行配置。
使用Mixdesk
1.初始化
MXConfig.init(this, "Your Appkey", new OnInitCallback() {
@Override
public void onSuccess(String clientId) {
Toast.makeText(MainActivity.this, "init success", Toast.LENGTH_SHORT).show();
}
@Override
public void onFailure(int code, String message) {
Toast.makeText(MainActivity.this, "int failure", Toast.LENGTH_SHORT).show();
}
});
如果您不知道 Appkey,请使用Mixdesk管理员帐号登录Mixdesk,在「接入」 -> 「APP SDK」 菜单中查看。
2.启动对话界面
初始化成功后,就可以直接启动对话界面
Intent intent = new MXIntentBuilder(this).build();
startActivity(intent);
4.Android M 权限处理
如果你的 App 需要兼容 Android M,需要处理权限问题。参考 Demo。
5.Android O 权限处理
如果你的 App 需要兼容 Android O,需要在 App 后台的时候确保关闭Mixdesk服务。
MXManager.getInstance(context).closeMixdeskService();
6.常见使用场景
绑定自定义账号
开发者的 App 有自己的账号系统,希望每个账号对应不同的顾客,有不同的聊天记录。那就需要开发者在启动对话的时候,绑定账号:
Intent intent = new MXIntentBuilder(this)
.setCustomizedId("开发者的 id") // 相同的 id 会被识别为同一个顾客
.build();
startActivity(intent);
设置顾客信息
开发者希望顾客上线的时候,能够上传(或者更新)一些用户的自定义信息:
HashMap<String, String> clientInfo = new HashMap<>();
clientInfo.put("name", "富坚义博");
clientInfo.put("avatar", "https://s3.cn-north-1.amazonaws.com.cn/pics.meiqia.bucket/1dee88eabfbd7bd4");
clientInfo.put("gender", "男");
clientInfo.put("tel", "1300000000");
clientInfo.put("技能1", "休刊");
HashMap<String, String> updateInfo = new HashMap<>();
updateInfo.put("name", "update name");
Intent intent = new MXIntentBuilder(this)
.setClientInfo(clientInfo) // 设置顾客信息 PS: 这个接口只会生效一次,如果需要更新顾客信息,需要调用更新接口
// .updateClientInfo(updateInfo) // 更新顾客信息 PS: 如果客服在工作台更改了顾客信息,更新接口会覆盖之前的内容
.build();
startActivity(intent);
7.常见问题列表
(这里可以添加常见问题的解答)
API 接口介绍
SDK 提供了丰富的 API 接口,主要包括:
- 设置当前 Client 上线
- 绑定Mixdesk id 并设置上线
- 绑定自定义 id 并设置上线
- 设置顾客离线
- 发送文字消息 / 图片消息 / 语音消息
- 从服务器获取历史消息
- 从本地获取历史消息
- 设置用户的设备唯一标识
- 开发者自定义当前顾客的信息
- 获取当前正在接待的客服信息
- 获取当前顾客的 id
- 获取一个新的顾客
- 更新消息阅读状态
- 结束当前对话
- 给客服发送「正在输入」
- 切换当前顾客
- 获取未读消息
- 接收即时消息
- 获取 SDK 版本号
- 离线消息推送
- 设置接收推送的服务器地址
- 设置用户的设备唯一标识
- 关闭Mixdesk服务
- 开启Mixdesk服务
- 推送消息数据结构
获取 MXManager 实例后,
MXManager mxManager = MXManager.getInstacne(context);
就可以调用下面的接口:
设置当前 Client 上线
初始化 SDK 成功后,会默认生成一个顾客,如果没有更改过顾客 id,将以默认生成的顾客上线。
/**
* 设置当前 Client 上线
*
* @param onlineCallback 回调
*/
setCurrentClientOnline(final OnClientOnlineCallback onlineCallback)
绑定Mixdesk id 并设置上线
开发者可通过 【获取当前顾客的 id】 接口,取得顾客 id ,保存到开发者的服务端,以此来绑定顾客和开发者用户系统。 如果开发者保存了顾客 id,可调用如下接口让其上线。调用此接口后,当前可用的顾客即为开发者传的顾客 id。
/**
* 绑定Mixdesk id,并设置上线
*
* @param mxClientId Mixdesk id
* @param onlineCallback 回调接口
*/
setClientOnlineWithClientId(String mxClientId, final OnClientOnlineCallback onlineCallback)
MXConversationActivity.class 内部调用了此接口,所以可以直接通过 MXIntentBuilder 来构造 intent。
Example:
// 假设 mixdesk_id 是Mixdesk生成的顾客 id
Intent intent = new MXIntentBuilder(this)
.setClientId(mixdesk_id)
.build();
startActivity(intent);
绑定自定义 id 并设置上线
如果开发者不愿保存「Mixdesk顾客 id」来绑定自己的用户系统,也可以将自己的用户 id当做参数,进行顾客的上线,Mixdesk将会为开发者绑定一个顾客,下次开发者直接调用如下接口,就能让这个绑定的顾客上线。 调用此接口后,当前可用的顾客即为该自定义 id 对应的顾客 id。
特别注意:传给Mixdesk的自定义 id 不能为自增长的,否则非常容易受到中间人攻击,此情况的开发者建议保存Mixdesk顾客 id,自定义id为长度不超过 32 位的字符串。
顾客 id 是由你来生成的,请保证每个顾客拥有独一无二的 id ,否则会出现多个客户串消息的情况!
/**
* 绑定自定义 id,并设置上线
*
* @param customizedId 自定义 id
* @param onlineCallback 回调接口
*/
setClientOnlineWithCustomizedId(String customizedId, final OnClientOnlineCallback onlineCallback)
MXConversationActivity.class 内部调用了此接口,所以可以直接通过 MXIntentBuilder 来构造 intent。
Example:
// 假设 developer@dev.com 是开发者的用户 id
Intent intent = new MXIntentBuilder(this)
.setCustomizedId("developer@dev.com") // 相同的 id 会被识别为同一个顾客
.build();
startActivity(intent);
设置顾客离线
设置顾客离线后,将停止监听客服发送的消息,开发者不会再监听到即时消息广播。
如果设置了顾客离线,并且在Mixdesk工作台配置了推送服务器,则客服发送的消息将会发送给开发者的服务端。
Mixdesk建议:如果退出界面后需要监听客服消息,不设置顾客离线,这样开发者仍能监听到收到消息的广播,以便提醒顾客有新消息。
/**
* 设置顾客离线
* 需要初始化成功后才能调用
* 如果设置了顾客离线,则客服发送的消息将会发送给开发者的推送服务器
*/
setClientOffline()
发送文字消息 / 图片消息 / 语音消息
/**
* 发送文字消息
*
* @param content 消息内容
* @param onMessageSendCallback 消息状态回调
*/
sendTextMessage(String content, final OnMessageSendCallback onMessageSendCallback)
/**
* 发送图片消息
*
* @param localPath 图片的本地路径
* @param onMessageSendCallback 消息状态回调
*/
sendPhotoMessage(String localPath, final OnMessageSendCallback onMessageSendCallback)
/**
* 发送语音消息
*
* @param localPath 语音的本地路径
* @param onMessageSendCallback 消息状态回调
*/
sendVoiceMessage(String localPath, final OnMessageSendCallback onMessageSendCallback)
从服务器获取历史消息
/**
* 从服务器获取历史消息
*
* @param lastMessageCreateOn 获取该日期之前的消息
* @param length 获取的消息长度
* @param onGetMessageListCallback 回调
*/
getMessageFromService(final long lastMessageCreateOn, final int length, final OnGetMessageListCallback onGetMessageListCallback)
从本地获取历史消息
/**
* 从服务器获取历史消息
*
* @param lastMessageCreateOn 获取该日期之前的消息
* @param length 获取的消息长度
* @param onGetMessageListCallback 回调
*/
getMessageFromDatabase(final long lastMessageCreateOn, final int length, final OnGetMessageListCallback onGetMessageListCallback)
设置用户的设备唯一标识
/**
* 设置用户的设备唯一标识
*
* @param token 唯一标识
*/
registerDeviceToken(String token, OkHttpUtils.OnRegisterDeviceTokenCallback onRegisterDeviceTokenCallback)
App 进入后台后,Mixdesk推送给开发者服务端的消息数据格式中,会有 deviceToken 的字段。
Mixdesk推送消息给开发者服务端的数据格式,可参考【推送消息数据结构】。
开发者自定义当前顾客的信息
/**
* 开发者自定义当前顾客的信息,用于展示给客服
*
* @param clientInfo 顾客信息
* @param onClientInfoCallback 回调
*/
setClientInfo(Map<String, String> clientInfo, OnClientInfoCallback onClientInfoCallback)
为了让客服能更准确帮助用户,开发者可上传不同用户的属性信息。示例如下:
Map<String, String> info = new HashMap<>();
info.put("name", "富坚义博");
info.put("avatar", "https://s3.cn-north-1.amazonaws.com.cn/pics.meiqia.bucket/1dee88eabfbd7bd4");
info.put("gender", "男");
info.put("tel", "111111");
info.put("技能1", "休刊");
info.put("技能2", "外出取材");
info.put("技能3", "打麻将");
MXManager.getInstance(context).setClientInfo(info, new OnClientInfoCallback());
MQConversationActivity.class 内部调用了此接口,所以可以直接通过 MQIntentBuilder 来构造 intent。
HashMap<String, String> clientInfo = new HashMap<>();
clientInfo.put("name", "富坚义博");
clientInfo.put("avatar", "https://s3.cn-north-1.amazonaws.com.cn/pics.meiqia.bucket/1dee88eabfbd7bd4");
clientInfo.put("gender", "男");
clientInfo.put("tel", "1300000000");
clientInfo.put("技能1", "休刊");
Intent intent = new MXIntentBuilder(this)
.setClientInfo(clientInfo)
.build();
startActivity(intent);
以下字段是Mixdesk定义好的,开发者可通过上方提到的接口,直接对下方的字段进行设置:
Key | 说明 |
---|---|
name | 真实姓名 |
tel | 电话 |
comment | 备注 |
邮件 | |
avatar | 头像 URL |
tags | 标签,数组形式,且必须是企业中已经存在的标签 |
获取当前正在接待的客服信息
/**
* 获取当前正在接待的客服信息
*
* @return 如果存在,返回当前客服信息;不存在,返回 null
*/
getCurrentAgent()
获取当前顾客的 id
/**
* 获取当前顾客的顾客 id,开发者可保存该顾客id,下次使用 setClientOnlineWithMQClientId 接口来让该顾客登陆Mixdesk客服系统
*
* @return 当前顾客 id
*/
getCurrentClientId()
获取一个新的顾客
/**
* 获取一个新的顾客
*
* @param onGetMQClientIdCallBack 回调
*/
createClient(OnGetMQClientIdCallBackOn onGetMQClientIdCallBack)
如果开发者想初始化一个新的顾客,可调用此接口。
该顾客没有任何历史记录及用户信息。
更新消息阅读状态
/**
* 更新消息阅读状态
*
* @param messageId 消息id
* @param isRead 将替换的状态
*/
updateMessage(long messageId, boolean isRead)
结束当前对话
/**
* 结束当前对话
*
* @param onEndConversationCallback 回调
*/
endCurrentConversation(OnEndConversationCallback onEndConversationCallback)
给客服发送「正在输入」
/**
* 将用户正在输入的内容,提供给客服查看。该接口没有调用限制,但每1秒内只会向服务器发送一次数据
*
* @param content 正在输入的内容
*/
sendClientInputtingWithContent(String content)
切换当前顾客
/**
* 切换当前顾客
*
* @param clientIdOrCustomizedId clientId 或者 customized
* @param simpleCallback 回调
*/
MQManager.getInstance(context).setCurrentClient(String clientIdOrCustomizedId, SimpleCallback simpleCallback);
获取未读消息
退出界面后收到的消息,都将算作未读消息。
/**
* 获取当前 Client 的未读消息
*
* @param onGetMessageListCallback 回调
*/
MQManager.getInstance(context).getUnreadMessages(new OnGetMessageListCallback());
/**
* 获取指定 ClientId 或者 customized 顾客的未读消息
*
* @param clientIdOrCustomizedId clientId 或者 customized
* @param onGetMessageListCallback 回调
*/
MQManager.getInstance(context).getUnreadMessages(String clientIdOrCustomizedId, new OnGetMessageListCallback());
接收即时消息
在未开启【离线消息推送】的情况下,开发者可以通过注册一个 BroadcastReceiver ,监听广播
注意:必须通过 LocalBroadcastManager 注册 和 取消注册 BroadcastReceiver。
Example:
// 注册
LocalBroadcastManager.getInstance(this).registerReceiver(messageReceiver, intentFilter);
// 取消注册
LocalBroadcastManager.getInstance(this).unregisterReceiver(messageReceiver);
BroadcastReceiver:
public class MessageReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
// 获取 ACTION
final String action = intent.getAction();
// 接收新消息
if (MXMessageManager.ACTION_NEW_MESSAGE_RECEIVED.equals(action)) {
// 从 intent 获取消息 id
String msgId = intent.getStringExtra("msgId");
// 从 MCMessageManager 获取消息对象
MXMessageManager messageManager = MXMessageManager.getInstance(context);
}
// 客服正在输入
else if (MXMessageManager.ACTION_AGENT_INPUTTING.equals(action)) {
// do something
}
// 客服转接
else if (MXMessageManager.ACTION_AGENT_CHANGE_EVENT.equals(action)) {
// 获取转接后的客服
MXAgent mxAgent = messageManager.getCurrentAgent();
// do something
}
}
}
获取 SDK 版本号
/**
* 获取 SDK 版本号
*/
getSDKVersion()
设置用户的设备唯一标识
/**
* 设置用户的设备唯一标识
*
* @param token 唯一标识
*/
registerDeviceToken(String token, OkHttpUtils.OnRegisterDeviceTokenCallback onRegisterDeviceTokenCallback)
关闭Mixdesk服务,Mixdesk推送给开发者服务端的消息数据格式中,会有 deviceToken 的字段。
关闭Mixdesk服务
关闭服务后,将停止监听消息,此时Mixdesk服务端将会推送消息给开发者提供的消息推送服务端,如下代码:
MQManager.getInstance(context).closeService();
Mixdesk建议:在 App 后台以后,关闭Mixdesk服务。App 进入前台,如果需要监听客服消息,再开启Mixdesk服务。
开启Mixdesk服务
开启服务后,将重新监听消息,此时Mixdesk服务端将不会推送消息给开发者提供的消息推送服务端,如下代码:
MQManager.getInstance(context).openService();
Mixdesk建议:在 App 后台以后,关闭Mixdesk服务。App 进入前台,如果需要监听客服消息,再开启Mixdesk服务。
自定义UI
通过配置文件自定义
自定义属性名 | 说明 | 默认值 |
---|---|---|
MXConfig.ui.titleGravity | 居中对齐 MXTitleGravity.CENTER、居左对齐 MXTitleGravity.LEFT | MXTitleGravity.CENTER |
通过资源文件自定义
通过在自己工程中覆盖相应资源ID的方式配置自定义 UI(这里只列出常用自定义属性,如需特殊定制,请查看Mixdesk SDK 源码里相应的资源 ID 并在自己工程中覆盖)
自定义属性名 | 说明 |
---|---|
mx_activity_bg | Activity 背景颜色资源 |
mx_activity_title_textColor | 标题栏文字颜色资源 |
mx_chat_left_textColor | 聊天界面左边气泡文字颜色资源 |
mx_chat_right_textColor | 聊天界面右边气泡文字颜色资源 |
mx_chat_left_bubble | 聊天界面左边气泡背景颜色资源 |
mx_chat_right_bubble | 聊天界面右边气泡背景颜色资源 |
mx_ic_back.png | 左上角返回箭头图片资源 |
通过Java代码自定义
以下属性可通过 Java 代码的方式配置(不建议使用这种方式)
自定义属性名 | 说明 |
---|---|
MXConfig.ui.backArrowIconResId | 标题栏返回箭头图片的资源 ID |
MXConfig.ui.titleBackgroundResId | 标题栏背景颜色的资源 ID |
MXConfig.ui.titleTextColorResId | 标题栏文字颜色的资源 ID |
MXConfig.ui.leftChatBubbleColorResId | 聊天界面左边气泡背景颜色的资源 ID |
MXConfig.ui.rightChatBubbleColorResId | 聊天界面右边气泡背景颜色的资源 ID |
MXConfig.ui.leftChatTextColorResId | 聊天界面左边气泡文字颜色的资源 ID |
MXConfig.ui.rightChatTextColorResId | 聊天界面右边气泡文字颜色的资源 ID |
自定义业务
属性说明 | 说明 | 默认值 |
---|---|---|
MXConfig.isVoiceSwitchOpen | 是否开启语音功能 | 默认为 true |
MXConfig.isSoundSwitchOpen | 是否开启声音提示 | 默认为 true |
MXConfig.isLoadMessagesFromNativeOpen | 是否加载本地数据 | 默认为 false |
MXConfig.isShowClientAvatar | 是否显示客户头像 | 默认为 false |
代码混淆
如果您的项目使用了代码混淆,请在 proguard-rules.pro
文件中添加以下规则:
# OkHttp相关
-keepattributes Signature
-keepattributes *Annotation*
-keep class com.squareup.okhttp3.** { *; }
-keep interface com.squareup.okhttp3.** { *; }
-dontwarn com.squareup.okhttp3.**
# Okio相关
-keep class sun.misc.Unsafe { *; }
-dontwarn java.nio.file.*
-dontwarn org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement
-dontwarn okio.**
# UIL相关
-keep class com.nostra13.universalimageloader.** { *; }
-keepclassmembers class com.nostra13.universalimageloader.** {*;}
-dontwarn com.nostra13.universalimageloader.**
# Glide相关
-keep class com.bumptech.glide.Glide { *; }
-keep public class * implements com.bumptech.glide.module.GlideModule
-keep public enum com.bumptech.glide.load.resource.bitmap.ImageHeaderParser$** {
**[] $VALUES;
public *;
}
-dontwarn com.bumptech.glide.**
# Picasso相关
-keep class com.squareup.picasso.Picasso { *; }
-dontwarn com.squareup.okhttp.**
-dontwarn com.squareup.picasso.**
# xUtils3相关
-keepattributes Signature,*Annotation*
-keep public class org.xutils.** {
public protected *;
}
-keep public interface org.xutils.** {
public protected *;
}
-keepclassmembers class * extends org.xutils.** {
public protected *;
}
-keepclassmembers @org.xutils.db.annotation.* class * {*;}
-keepclassmembers @org.xutils.http.annotation.* class * {*;}
-keepclassmembers class * {
@org.xutils.view.annotation.Event <methods>;
}
-dontwarn org.xutils.**