企信需要实现的功能
先梳理一下优悦家装企信的逻辑,主要要满足群聊和消息推送功能。
群聊
一个项目(Project)分为两个群,一个客服群,一个工作群。
消息
消息分为很多种,有工作提醒,装修提醒,薪资提醒等等。
设计思路
和服务器商议决定,采用websocket协议,传输json字符串,实现消息通信。
每一种业务都对应一种业务ID,比如
public static final int HEARTBEAT_CLIENT = 1;//心跳业务ID(客户端发送)
public static final int HEARTBEAT_SERVER = 2;//心跳业务ID(服务器返回)
public static final int USER_LOGIN = 1001; //用户登陆业务ID
public static final int USER_LOGIN_SUCCEED = 1010;//登陆成功业务ID
public static final int USER_LOGIN_ERROR = 1020;//登陆失败业务ID
public static final int USER_LOGIN_IN_OTHER_PLACES = 1030;//该用户登陆在其他地方登陆
......
WebSocket实现
采用的开源的java-websocket实现,这个库封装好了websocket的连接,发送,接受消息的代码,使用简单!
简单流程
当APP启动时,打开websocket的连接,当用户登陆后,绑定用户。绑定用户成功后,就可以正常的发送的和接送消息。
打开websocket的连接
在MyApplication.java类
QXConfig config = new QXConfig("com.keith.renovation", BuildConfig.SERVER_WS_URL);
config.setClientName("APP_B");
QXIMClient.init(this, config);
上述代码,会启动一个service服务,最终调用java-websocket的连接方法,打开websocket连接。
- 绑定用户
QXIMClient.bind(token);
调用上述代码会,发送登陆的消息给服务器,如果登陆成功,服务器会返回登陆成功的消息通知客服端,如果登陆失败,服务器会发送登陆失败的消息通知客户端。
发送消息
调用QXIMClient.java的sendMessage()发送消息,会将消息转换成json字符串,然后发送给服务器。如果发送成功,服务器会返回成功的消息通知客服端,如果发送失败,服务器会发送登陆失败的消息通知客户端。
如何接受消息
先通过QXIMClient.registerMessageReceiveListener注册listener,当有消息来之后,就可以在listener的onQXMessageReceive方法接收到,当你不需要接收消息的时候,记得unregister防止内存泄露,采用所谓的观察者模式!
群消息
普通文本消息(QXGroupTextMessage.java)
图片消息(QXGroupImageMessage.java)
位置消息(QXGroupLocationMessage.java)
文档消息(QXGroupDocumentMessage.java)
语音消息(QXGroupVoiceMessage.java)
群成员变动消息(QXGroupMemberMessage.java)
群消息的存储
将消息统一存储到sqlite3中,对应的实体类(GroupMessageEntity.java)
private int id;//主键ID
private String messageId;//本地生成的ID
private String sn;//服务器生成消息序列号
private int businessId;//业务ID,区分是什么消息(文本?图片?位置?)
private long groupId;//群ID
private long userId;//发送者ID
private long toUserId; //消息发送给谁
private String groupType;//群类型(客服/同事)
private String fromSource;//消息来源
private boolean cancelFlag = false;//消息是否被撤销
private int status = STATUS_GET;//消息状态(发送成功/发送失败/已接受/发送中)
@Column(nullable = true)
private String content;//发送消息的json字符串,这个很重要,通过它可以转化成消息类
private String text;//文本消息发送消息的文本内容,(这个是为了通过关键字搜索内容)
private long createTime;//发送/接收时间
当发送/接受到群消息时,将消息存储到数据库,具体代码
private void processGroupMessage(QXGroupMessage groupMessage){
if(groupMessage == null){
return;
}
//通知监听
for(OnMessageReceiveListener listener: mMessageReceiveList){
listener.onQXMessageReceive(groupMessage);
}
//保存消息到数据库
sendQXMessageToByStoreHandler(groupMessage, WHAT_MESSAGE_RECV);
sendQXMessageReceipt(groupMessage.getMsgId());
}
由于聊天界面(如下图所示)有显示项目群的最后收到的一条消息,所以还需要在项目信息(ProjectEntity.java)里面存储最后收到的一条群消息。
private String messageId;
private String lastMessage;//最后收到的这条消息
private long lastMessageFromGroupId;//最后一条消息来自的群ID
private long lastMessageTime;//最后一条消息的发送的时间
private int lastMessageStatus;//最后一条消息状态
private int unreadWorkNum;//工作群未读的消息个数
private int unreadCustomerNum;//客户群是未读的消息个数
private long workGroupId;//工作群ID
private long customerGroupId;//客服群ID
当发送或者/接收到群消息时,就去更新项目信息中最后一条消息的相关信息,如下所示。
mMessageStoreHandler = new Handler(mHandlerThread.getLooper()){
@Override
public void handleMessage(Message msg) {
//TODO should process android.database.sqlite.SQLiteDatabaseLockedException: database is locked (code 5):
if(msg.obj instanceof QXCancelMessage){
//收到撤销消息
cancelMessage((QXCancelMessage) msg.obj, msg.what == WHAT_MESSAGE_RECV);
return;
}
if(msg.obj instanceof QXGroupMessage){
//收到群消息
saveQXMessage((QXGroupMessage)msg.obj, msg.what == WHAT_MESSAGE_RECV);
}else if(msg.obj instanceof QXReceiptSuccessMessage){
//消息发送成功的回执消息
QXReceiptSuccessMessage messageSuccessReceipt = (QXReceiptSuccessMessage)msg.obj;
saveQXMessageSuccessReceipt(messageSuccessReceipt);
}else if(msg.obj instanceof QXReceiptErrorMessage){
//消息发送失败的回执消息
QXReceiptErrorMessage messageSuccessReceipt = (QXReceiptErrorMessage)msg.obj;
saveQXMessageErrorReceipt(messageSuccessReceipt);
}else if(msg.obj instanceof QXProjectMessage){
//收到项目消息
modifyProjectStatus((QXProjectMessage) msg.obj);
}
}
};
消息推送部分
行政工作提醒
行政工作模块,分为通知、任务、日志、审批。如果想监听到工作消息,可以通过QXIMClient.registerOnExecutiveListener方法。
应用模块里面的消息
调用QXIMClient.registerOnQXWorkMessageListener方法,可以收到 实力龙发、促销活动、问题处理、企业公告 的消息。
装修模块提醒
调用QXIMClient.registerOnProjectMessageListener方法,可以收到 节点验收、客户洽谈、项目进度 的消息。
界面部分
聊天界面
聊天界面时最复杂的界面(ChatActivity),所以只针对聊天界面作一个说明
如上图所示,界面分为三个部分,第一部分是title,第二部分是content,由fragment构成,第三部分是键盘(注意,为了方便处理,键盘部分在fragment中)
第一部分不多说。第二部分,是一个listView。第三部分是利用github上的一个键盘,具体点击