@ProjectName: NettyChat
8 | *@ClassName: ExecutorServiceFactory.java
9 | *@PackageName: com.freddy.kulaims
10 | * 11 | *@Description: 线程池工厂,负责重连和心跳线程调度
12 | * 13 | *@author: FreddyChen
14 | *@date: 2019/04/05 05:12
15 | *@email: chenshichao@outlook.com
16 | */ 17 | public class ExecutorServiceFactory { 18 | 19 | private ExecutorService bossPool;// 管理线程组,负责重连 20 | private ExecutorService workPool;// 工作线程组,负责心跳 21 | 22 | /** 23 | * 初始化boss线程池 24 | */ 25 | public synchronized void initBossLoopGroup() { 26 | destroyBossLoopGroup(); 27 | bossPool = Executors.newSingleThreadExecutor(); 28 | } 29 | 30 | /** 31 | * 初始化work线程池 32 | */ 33 | public synchronized void initWorkLoopGroup() { 34 | destroyWorkLoopGroup(); 35 | workPool = Executors.newSingleThreadExecutor(); 36 | } 37 | 38 | /** 39 | * 执行boss任务 40 | * 41 | * @param r 42 | */ 43 | public void execBossTask(Runnable r) { 44 | if (bossPool == null) { 45 | initBossLoopGroup(); 46 | } 47 | bossPool.execute(r); 48 | } 49 | 50 | /** 51 | * 执行work任务 52 | * 53 | * @param r 54 | */ 55 | public void execWorkTask(Runnable r) { 56 | if (workPool == null) { 57 | initWorkLoopGroup(); 58 | } 59 | workPool.execute(r); 60 | } 61 | 62 | /** 63 | * 释放boss线程池 64 | */ 65 | public synchronized void destroyBossLoopGroup() { 66 | if (bossPool != null) { 67 | try { 68 | bossPool.shutdownNow(); 69 | } catch (Throwable t) { 70 | t.printStackTrace(); 71 | } finally { 72 | bossPool = null; 73 | } 74 | } 75 | } 76 | 77 | /** 78 | * 释放work线程池 79 | */ 80 | public synchronized void destroyWorkLoopGroup() { 81 | if (workPool != null) { 82 | try { 83 | workPool.shutdownNow(); 84 | } catch (Throwable t) { 85 | t.printStackTrace(); 86 | } finally { 87 | workPool = null; 88 | } 89 | } 90 | } 91 | 92 | /** 93 | * 释放所有线程池 94 | */ 95 | public synchronized void destroy() { 96 | destroyBossLoopGroup(); 97 | destroyWorkLoopGroup(); 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /src/main/java/com/freddy/kulaims/IMSKit.java: -------------------------------------------------------------------------------- 1 | package com.freddy.kulaims; 2 | 3 | import android.content.Context; 4 | import android.util.Log; 5 | 6 | import com.freddy.kulaims.config.CommunicationProtocol; 7 | import com.freddy.kulaims.config.IMSOptions; 8 | import com.freddy.kulaims.config.ImplementationMode; 9 | import com.freddy.kulaims.config.TransportProtocol; 10 | import com.freddy.kulaims.interf.IMSInterface; 11 | import com.freddy.kulaims.listener.IMSConnectStatusListener; 12 | import com.freddy.kulaims.listener.IMSMsgReceivedListener; 13 | 14 | /** 15 | * IMS核心类 16 | */ 17 | public class IMSKit { 18 | 19 | private static final String TAG = "FreddyChen";// todo 不知道为什么tag为IMSKit的时候,Logcat无法打印日志 20 | private IMSInterface ims; 21 | 22 | private IMSKit() { 23 | } 24 | 25 | public static IMSKit getInstance() { 26 | return SingletonHolder.INSTANCE; 27 | } 28 | 29 | private static final class SingletonHolder { 30 | private static final IMSKit INSTANCE = new IMSKit(); 31 | } 32 | 33 | public boolean init(Context context, IMSOptions options, IMSConnectStatusListener connectStatusListener, IMSMsgReceivedListener msgReceivedListener) { 34 | Log.d(TAG, "IMSKit初始化开始"); 35 | if (context == null) { 36 | Log.w(TAG, "IMSKit初始化失败:Context 为 null"); 37 | return false; 38 | } 39 | 40 | if (options == null) { 41 | Log.w(TAG, "IMSKit初始化失败:IMSOptions 为 null"); 42 | return false; 43 | } 44 | 45 | ImplementationMode implementationMode = options.getImplementationMode(); 46 | if (implementationMode == null) { 47 | Log.w(TAG, "IMSKit初始化失败:ImplementationMode 为 null"); 48 | return false; 49 | } 50 | 51 | CommunicationProtocol communicationProtocol = options.getCommunicationProtocol(); 52 | if (communicationProtocol == null) { 53 | Log.w(TAG, "IMSKit初始化失败:CommunicationProtocol 为 null"); 54 | return false; 55 | } 56 | 57 | TransportProtocol transportProtocol = options.getTransportProtocol(); 58 | if (transportProtocol == null) { 59 | Log.w(TAG, "IMSKit初始化失败:TransportProtocol 为 null"); 60 | return false; 61 | } 62 | 63 | ims = IMSFactory.getIMS(implementationMode, communicationProtocol); 64 | if (ims == null) { 65 | Log.w(TAG, "IMSKit初始化失败:ims 为 null"); 66 | return false; 67 | } 68 | 69 | boolean initialized = ims.init(context, options, connectStatusListener, msgReceivedListener); 70 | if (!initialized) { 71 | Log.w(TAG, "IMSKit初始化失败:请查看 " + ims.getClass().getSimpleName() + " 相关的日志"); 72 | return false; 73 | } 74 | 75 | Log.d(TAG, "IMSKit初始化完成\nims = " + ims.getClass().getSimpleName() + "\noptions = " + options); 76 | return true; 77 | } 78 | 79 | public void connect() { 80 | if (ims == null) { 81 | Log.d(TAG, "IMSKit启动失败"); 82 | return; 83 | } 84 | 85 | ims.connect(); 86 | } 87 | 88 | public void disconnect() { 89 | if(ims == null) return; 90 | ims.release(); 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /src/main/java/com/freddy/kulaims/bean/IMSMsg.java: -------------------------------------------------------------------------------- 1 | package com.freddy.kulaims.bean; 2 | 3 | import com.freddy.kulaims.utils.UUID; 4 | 5 | /** 6 | * @author FreddyChen 7 | * @name IMS消息 8 | * @date 2020/05/21 16:38 9 | * @email chenshichao@outlook.com 10 | * @github https://github.com/FreddyChen 11 | * @desc 通用的消息格式定义,可转换成json或protobuf传输 12 | */ 13 | public class IMSMsg { 14 | private String msgId;// 消息唯一标识 15 | private int msgType; // 消息类型 16 | private String sender;// 发送者标识 17 | private String receiver;// 接收者标识 18 | private long timestamp;// 消息发送时间,单位:毫秒 19 | private int report;// 消息发送状态报告 20 | private String content;// 消息内容 21 | private int contentType;// 消息内容类型 22 | private String data; // 扩展字段,以key/value形式存储的json字符串 23 | 24 | public IMSMsg(Builder builder) { 25 | if(builder == null) { 26 | return; 27 | } 28 | 29 | this.msgId = builder.msgId; 30 | this.msgType = builder.msgType; 31 | this.sender = builder.sender; 32 | this.receiver = builder.receiver; 33 | this.timestamp = builder.timestamp; 34 | this.report = builder.report; 35 | this.content = builder.content; 36 | this.contentType = builder.contentType; 37 | this.data = builder.data; 38 | } 39 | 40 | public String getMsgId() { 41 | return msgId; 42 | } 43 | 44 | public int getMsgType() { 45 | return msgType; 46 | } 47 | 48 | public String getSender() { 49 | return sender; 50 | } 51 | 52 | public String getReceiver() { 53 | return receiver; 54 | } 55 | 56 | public long getTimestamp() { 57 | return timestamp; 58 | } 59 | 60 | public int getReport() { 61 | return report; 62 | } 63 | 64 | public String getContent() { 65 | return content; 66 | } 67 | 68 | public int getContentType() { 69 | return contentType; 70 | } 71 | 72 | public String getData() { 73 | return data; 74 | } 75 | 76 | public static class Builder { 77 | private String msgId;// 消息唯一标识 78 | private int msgType; // 消息类型 79 | private String sender;// 发送者标识 80 | private String receiver;// 接收者标识 81 | private long timestamp;// 消息发送时间,单位:毫秒 82 | private int report;// 消息发送状态报告 83 | private String content;// 消息内容 84 | private int contentType;// 消息内容类型 85 | private String data; // 扩展字段,以key/value形式存储的json字符串 86 | 87 | public Builder() { 88 | this.msgId = UUID.generateShortUuid(); 89 | } 90 | 91 | public Builder setMsgType(int msgType) { 92 | this.msgType = msgType; 93 | return this; 94 | } 95 | 96 | public Builder setSender(String sender) { 97 | this.sender = sender; 98 | return this; 99 | } 100 | 101 | public Builder setReceiver(String receiver) { 102 | this.receiver = receiver; 103 | return this; 104 | } 105 | 106 | public Builder setTimestamp(long timestamp) { 107 | this.timestamp = timestamp; 108 | return this; 109 | } 110 | 111 | public Builder setReport(int report) { 112 | this.report = report; 113 | return this; 114 | } 115 | 116 | public Builder setContent(String content) { 117 | this.content = content; 118 | return this; 119 | } 120 | 121 | public Builder setContentType(int contentType) { 122 | this.contentType = contentType; 123 | return this; 124 | } 125 | 126 | public Builder setData(String data) { 127 | this.data = data; 128 | return this; 129 | } 130 | 131 | public IMSMsg build() { 132 | return new IMSMsg(this); 133 | } 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /src/main/java/com/freddy/kulaims/net/NetworkManager.java: -------------------------------------------------------------------------------- 1 | package com.freddy.kulaims.net; 2 | 3 | import android.content.Context; 4 | import android.net.ConnectivityManager; 5 | import android.net.Network; 6 | import android.net.NetworkCapabilities; 7 | import android.net.NetworkRequest; 8 | import android.util.Log; 9 | 10 | import androidx.annotation.NonNull; 11 | 12 | import java.util.ArrayList; 13 | import java.util.List; 14 | 15 | public class NetworkManager extends ConnectivityManager.NetworkCallback { 16 | 17 | private static final String TAG = NetworkManager.class.getSimpleName(); 18 | private List