|
@@ -1,7 +1,13 @@
|
|
|
package cn.org.bjca.trust.android.lib.im.im.manager;
|
|
|
|
|
|
+import android.annotation.SuppressLint;
|
|
|
+import android.os.Handler;
|
|
|
+import android.os.Looper;
|
|
|
+import android.os.Message;
|
|
|
import android.util.Log;
|
|
|
|
|
|
+import androidx.annotation.NonNull;
|
|
|
+
|
|
|
import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
|
|
|
import org.eclipse.paho.client.mqttv3.MqttCallbackExtended;
|
|
|
import org.eclipse.paho.client.mqttv3.MqttClient;
|
|
@@ -10,13 +16,23 @@ import org.eclipse.paho.client.mqttv3.MqttException;
|
|
|
import org.eclipse.paho.client.mqttv3.MqttMessage;
|
|
|
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
|
|
|
|
|
|
+import java.util.ArrayList;
|
|
|
+import java.util.HashMap;
|
|
|
+import java.util.List;
|
|
|
+import java.util.Map;
|
|
|
+
|
|
|
import cn.org.bjca.trust.android.lib.im.cfg.Constant;
|
|
|
import cn.org.bjca.trust.android.lib.im.common.DeviceHelper;
|
|
|
import cn.org.bjca.trust.android.lib.im.common.json.GsonImplHelp;
|
|
|
+import cn.org.bjca.trust.android.lib.im.enums.MsgType;
|
|
|
+import cn.org.bjca.trust.android.lib.im.enums.PacketType;
|
|
|
import cn.org.bjca.trust.android.lib.im.im.bean.PacketMessage;
|
|
|
import cn.org.bjca.trust.android.lib.im.im.kit.IMInterface;
|
|
|
import cn.org.bjca.trust.android.lib.im.im.msg.ConnectMessage;
|
|
|
+import cn.org.bjca.trust.android.lib.im.im.msg.ConnectedMessage;
|
|
|
import cn.org.bjca.trust.android.lib.im.im.msg.SZYXMessage;
|
|
|
+import cn.org.bjca.trust.android.lib.im.im.msg.SendAckMessage;
|
|
|
+import cn.org.bjca.trust.android.lib.im.im.msg.message.SZYXTextMessage;
|
|
|
import cn.org.bjca.trust.android.lib.im.im.opt.ImConnectOptions;
|
|
|
import cn.org.bjca.trust.android.lib.im.kit.IMSDKCallback;
|
|
|
import cn.org.bjca.trust.android.lib.im.kit.IMSDKListener;
|
|
@@ -26,6 +42,25 @@ import kotlin.text.Charsets;
|
|
|
public class ImManager implements IMInterface {
|
|
|
private final String TAG = "ImManager";
|
|
|
|
|
|
+ //登录成功
|
|
|
+ private String topic_connected;
|
|
|
+
|
|
|
+ // 新消息到达
|
|
|
+ private String topic_arrive;
|
|
|
+
|
|
|
+ // 发送消息应答
|
|
|
+ private String topic_send_ack;
|
|
|
+
|
|
|
+ // 心跳应答
|
|
|
+ private String topic_pang;
|
|
|
+
|
|
|
+
|
|
|
+ // 数据请求回复
|
|
|
+ private String topic_result;
|
|
|
+
|
|
|
+ // 系统消息
|
|
|
+ private String topic_system;
|
|
|
+
|
|
|
private MqttClient mqttClient;
|
|
|
private MqttConnectOptions connectOptions;
|
|
|
|
|
@@ -33,15 +68,18 @@ public class ImManager implements IMInterface {
|
|
|
|
|
|
private IMSDKListener statusListener;
|
|
|
|
|
|
+ private final List<MsgListener> msgListeners = new ArrayList<>();
|
|
|
+ private final Map<String, IMSDKCallback> msgListenerMap = new HashMap<>();
|
|
|
+
|
|
|
|
|
|
@Override
|
|
|
public void addMsgListener(MsgListener listener) {
|
|
|
-
|
|
|
+ msgListeners.add(listener);
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
public void removeMsgListener(MsgListener listener) {
|
|
|
-
|
|
|
+ msgListeners.remove(listener);
|
|
|
}
|
|
|
|
|
|
@Override
|
|
@@ -54,6 +92,16 @@ public class ImManager implements IMInterface {
|
|
|
this.statusListener = null;
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+ private void initTopic() {
|
|
|
+ topic_send_ack = Constant.getSdkAppID() + "/" + PacketType.SEND_ACK + Constant.getUserId();
|
|
|
+ topic_connected = Constant.getSdkAppID() + "/" + PacketType.CONNECTED + Constant.getUserId();
|
|
|
+ topic_arrive = Constant.getSdkAppID() + "/" + PacketType.ARRIVE + Constant.getUserId();
|
|
|
+ topic_pang = Constant.getSdkAppID() + "/" + PacketType.PANG + Constant.getUserId();
|
|
|
+ topic_result = Constant.getSdkAppID() + "/" + PacketType.RESULT + Constant.getUserId();
|
|
|
+ topic_system = Constant.getSdkAppID() + "/" + PacketType.SYSTEM + Constant.getUserId();
|
|
|
+ }
|
|
|
+
|
|
|
@Override
|
|
|
public void login(ImConnectOptions imConnectOptions) {
|
|
|
if (this.isConnect()) this.logout();
|
|
@@ -65,6 +113,7 @@ public class ImManager implements IMInterface {
|
|
|
connectOptions.setConnectionTimeout(30);
|
|
|
connectOptions.setKeepAliveInterval(20);
|
|
|
connectOptions.setAutomaticReconnect(true);
|
|
|
+ initTopic();
|
|
|
|
|
|
try {
|
|
|
mqttClient = new MqttClient("tcp://" + imConnectOptions.getHost() + ":" + imConnectOptions.getPort(),
|
|
@@ -76,11 +125,13 @@ public class ImManager implements IMInterface {
|
|
|
status = 0;
|
|
|
if (reconnect) return;
|
|
|
try {
|
|
|
- mqttClient.subscribe(Constant.getSdkAppID() + "/message:" + Constant.getUserId(), 2);
|
|
|
- mqttClient.subscribe(Constant.getSdkAppID() + "/pang:" + Constant.getUserId(), 2);
|
|
|
- mqttClient.subscribe(Constant.getSdkAppID() + "/connect:" + Constant.getUserId(), 2);
|
|
|
- mqttClient.subscribe(Constant.getSdkAppID() + "/result:" + Constant.getUserId(), 2);
|
|
|
- mqttClient.subscribe(Constant.getSdkAppID() + "/notice:" + Constant.getUserId(), 2);
|
|
|
+ mqttClient.subscribe(topic_connected, 2);
|
|
|
+ mqttClient.subscribe(topic_arrive, 2);
|
|
|
+ mqttClient.subscribe(topic_send_ack, 2);
|
|
|
+ mqttClient.subscribe(topic_pang, 2);
|
|
|
+ mqttClient.subscribe(topic_result, 2);
|
|
|
+ mqttClient.subscribe(topic_system, 2);
|
|
|
+ Log.e("======>connectComplete", topic_send_ack);
|
|
|
} catch (MqttException e) {
|
|
|
Log.e(TAG, "=====>connectComplete", e);
|
|
|
}
|
|
@@ -97,12 +148,52 @@ public class ImManager implements IMInterface {
|
|
|
|
|
|
@Override
|
|
|
public void messageArrived(String topic, MqttMessage message) throws Exception {
|
|
|
- Log.e("======>messageArrived", topic + "::" + new String(message.getPayload(), Charsets.UTF_8));
|
|
|
+ String msg = new String(message.getPayload(), Charsets.UTF_8);
|
|
|
+ // 登录应答
|
|
|
+ if (topic.equals(topic_connected)) {
|
|
|
+ ConnectedMessage connectedMessage = GsonImplHelp.get().toObject(msg, ConnectedMessage.class);
|
|
|
+ if (connectedMessage.getStatus() == 200) {
|
|
|
+ if (statusListener != null) statusListener.onConnectSuccess();
|
|
|
+ } else {
|
|
|
+ if (statusListener != null)
|
|
|
+ statusListener.onConnectFailed(connectedMessage.getStatus(), connectedMessage.getMsg());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 发送消息应答
|
|
|
+ else if (topic.equals(topic_send_ack)) {
|
|
|
+ SendAckMessage sendAckMessage = GsonImplHelp.get().toObject(msg, SendAckMessage.class);
|
|
|
+
|
|
|
+ Message m = new Message();
|
|
|
+ m.obj = sendAckMessage.getAckId();
|
|
|
+ m.what = 10002;
|
|
|
+ handler.sendMessage(m);
|
|
|
+
|
|
|
+ }
|
|
|
+ // 新消息送达
|
|
|
+ else if (topic.equals(topic_arrive)) {
|
|
|
+ SZYXMessage szyxMessage = GsonImplHelp.get().toObject(msg, SZYXMessage.class);
|
|
|
+ sendAckMsg(szyxMessage.getMsgId());
|
|
|
+ Log.d("======>新消息送达", topic + "::\n" + msg);
|
|
|
+ for (MsgListener listener : msgListeners) {
|
|
|
+ listener.messageArrive(new ArrayList<SZYXMessage>() {
|
|
|
+ {
|
|
|
+ add(szyxMessage);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+ } else
|
|
|
+ Log.e("======>messageArrived", topic + "::" + msg);
|
|
|
+
|
|
|
+
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
public void deliveryComplete(IMqttDeliveryToken token) {
|
|
|
- Log.e("======>deliveryComplete", "token.getMessage().toString()");
|
|
|
+ try {
|
|
|
+ if (token.getMessage() != null && token.getMessage().getPayload() != null)
|
|
|
+ Log.e("======>deliveryComplete", new String(token.getMessage().getPayload(), Charsets.UTF_8));
|
|
|
+ } catch (MqttException ignored) {
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
});
|
|
@@ -145,17 +236,47 @@ public class ImManager implements IMInterface {
|
|
|
return this.status == 1;
|
|
|
}
|
|
|
|
|
|
+ @Override
|
|
|
+ public SZYXMessage createMsg(MsgType msgType, String toUserId, boolean isGroup, Object message, String describe) {
|
|
|
+
|
|
|
+ SZYXMessage szyxMessage = new SZYXMessage(msgType);
|
|
|
+ szyxMessage.setArrive(false);
|
|
|
+ szyxMessage.setDescribe(describe);
|
|
|
+ szyxMessage.setGroup(isGroup);
|
|
|
+ szyxMessage.setStatus(1);
|
|
|
+ szyxMessage.setFromClient(UserManager.getInstance().getUserInfo());
|
|
|
+ if (isGroup)
|
|
|
+ szyxMessage.setGroupID(toUserId);
|
|
|
+ else
|
|
|
+ szyxMessage.setToClientId(toUserId);
|
|
|
+ switch (msgType) {
|
|
|
+ case Text:
|
|
|
+ szyxMessage.setTextMessage((SZYXTextMessage) message);
|
|
|
+ break;
|
|
|
+ case Voice:
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ return szyxMessage;
|
|
|
+ }
|
|
|
+
|
|
|
@Override
|
|
|
public void sendSZYXMessage(SZYXMessage message, IMSDKCallback callback) {
|
|
|
- sendPacketMessage(message, callback);
|
|
|
+ sendPacketMessage(PacketType.SEND, message, callback);
|
|
|
}
|
|
|
|
|
|
private void sendConnectMsg() {
|
|
|
ConnectMessage message = new ConnectMessage(DeviceHelper.getDevice());
|
|
|
- sendPacketMessage(message, null);
|
|
|
+ sendPacketMessage(PacketType.CONNECT, message, null);
|
|
|
+ }
|
|
|
+
|
|
|
+ private void sendAckMsg(String msgId) {
|
|
|
+ SendAckMessage message = new SendAckMessage();
|
|
|
+ message.setMsgId(msgId);
|
|
|
+ sendPacketMessage(PacketType.SEND_ACK, message, null);
|
|
|
}
|
|
|
|
|
|
- private void sendPacketMessage(PacketMessage message, IMSDKCallback callback) {
|
|
|
+ private void sendPacketMessage(PacketType packetType, PacketMessage message, IMSDKCallback callback) {
|
|
|
if (null == connectOptions) {
|
|
|
if (null != callback) callback.failed(204, "未登录");
|
|
|
return;
|
|
@@ -166,10 +287,63 @@ public class ImManager implements IMInterface {
|
|
|
}
|
|
|
String msg = GsonImplHelp.get().toJson(message);
|
|
|
try {
|
|
|
- mqttClient.publish("server", msg.getBytes(Charsets.UTF_8), 2, false);
|
|
|
+ mqttClient.publish("server" + packetType, msg.getBytes(Charsets.UTF_8), 2, false);
|
|
|
+ // 如果是发送的消息,需要应答
|
|
|
+ if (PacketType.SEND == packetType) {
|
|
|
+ if (null != callback)
|
|
|
+ msgListenerMap.put(message.getMsgId(), callback);
|
|
|
+ else msgListenerMap.put(message.getMsgId(), new IMSDKCallback() {
|
|
|
+ @Override
|
|
|
+ public void success() {
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void failed(int code, String error) {
|
|
|
+
|
|
|
+ }
|
|
|
+ });
|
|
|
+ Message m = new Message();
|
|
|
+ m.obj = message.getMsgId();
|
|
|
+ m.what = 10001;
|
|
|
+ handler.sendMessageDelayed(m, 1500);
|
|
|
+ }
|
|
|
} catch (MqttException e) {
|
|
|
if (null != callback) callback.failed(206, e.getMessage());
|
|
|
}
|
|
|
|
|
|
}
|
|
|
+
|
|
|
+ private final Handler handler = new Handler(Looper.getMainLooper()) {
|
|
|
+ @SuppressLint("HandlerLeak")
|
|
|
+ @Override
|
|
|
+ public void handleMessage(@NonNull Message msg) {
|
|
|
+ super.handleMessage(msg);
|
|
|
+ String msgId = (String) msg.obj;
|
|
|
+ switch (msg.what) {
|
|
|
+ case 10001:
|
|
|
+ IMSDKCallback callback = msgListenerMap.get(msgId);
|
|
|
+ if (null != callback) {
|
|
|
+ callback.failed(207, "发送超时");
|
|
|
+ msgListenerMap.remove(msgId);
|
|
|
+
|
|
|
+ for (MsgListener listener : msgListeners) {
|
|
|
+ listener.statusChange(msgId, -1);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case 10002:
|
|
|
+ IMSDKCallback callback1 = msgListenerMap.get(msgId);
|
|
|
+ if (null != callback1) {
|
|
|
+ for (MsgListener listener : msgListeners) {
|
|
|
+ listener.statusChange(msgId, 0);
|
|
|
+ }
|
|
|
+ callback1.success();
|
|
|
+ msgListenerMap.remove(msgId);
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
}
|