From 13f7b5e09031ac94f10de3d4ced32143fb6fc326 Mon Sep 17 00:00:00 2001
From: yy1717 <fctom1215@outlook.com>
Date: 星期一, 30 十二月 2019 17:34:54 +0800
Subject: [PATCH] 首次加入ndk
---
im_lib/src/main/AndroidManifest.xml | 2
im_lib/src/main/java/com/anyun/im_lib/MsgTimeOutTimerManager.java | 33 +
im_lib/src/main/java/com/anyun/im_lib/netty/TCPChannelInitializerHandler.java | 44 ++
im_lib/.gitignore | 1
im_lib/src/main/java/com/anyun/im_lib/interf/IMSClientInteface.java | 114 +++++
im_lib/libs/netty-all-4.1.43.jar | 0
im_lib/src/main/java/com/anyun/im_lib/HeartbeatRespHandler.java | 22 +
im_lib/src/main/java/com/anyun/im_lib/netty/NettyTcpClient.java | 378 ++++++++++++++++++
im_lib/build.gradle | 34 +
im_lib/src/main/java/com/anyun/im_lib/ExecutorServiceFactory.java | 100 +++++
im_lib/src/main/java/com/anyun/im_lib/listener/IMSConnectStatusCallback.java | 20 +
im_lib/src/androidTest/java/com/anyun/im_lib/ExampleInstrumentedTest.java | 27 +
im_lib/src/main/java/com/anyun/im_lib/MsgTimeoutTimer.java | 36 +
im_lib/src/test/java/com/anyun/im_lib/ExampleUnitTest.java | 17
im_lib/src/main/java/com/anyun/im_lib/IMSClientFactory.java | 16
im_lib/src/main/java/com/anyun/im_lib/listener/OnEventListener.java | 51 ++
im_lib/src/main/java/com/anyun/im_lib/HeartbeatHandler.java | 12
im_lib/src/main/java/com/anyun/im_lib/im/IMSClientBootstrap.java | 61 +++
im_lib/proguard-rules.pro | 21 +
im_lib/src/main/java/com/anyun/im_lib/LoginAuthRespHandler.java | 42 ++
im_lib/src/main/res/values/strings.xml | 3
im_lib/src/main/java/com/anyun/im_lib/IMSConfig.java | 28 +
im_lib/src/main/java/com/anyun/im_lib/MsgDispatcher.java | 15
im_lib/src/main/java/com/anyun/im_lib/netty/TCPReadHandler.java | 65 +++
im_lib/consumer-rules.pro | 0
25 files changed, 1,142 insertions(+), 0 deletions(-)
diff --git a/im_lib/.gitignore b/im_lib/.gitignore
new file mode 100644
index 0000000..796b96d
--- /dev/null
+++ b/im_lib/.gitignore
@@ -0,0 +1 @@
+/build
diff --git a/im_lib/build.gradle b/im_lib/build.gradle
new file mode 100644
index 0000000..8ac8395
--- /dev/null
+++ b/im_lib/build.gradle
@@ -0,0 +1,34 @@
+apply plugin: 'com.android.library'
+
+android {
+ compileSdkVersion 29
+
+
+ defaultConfig {
+ minSdkVersion 21
+ targetSdkVersion 29
+ versionCode 1
+ versionName "1.0"
+
+ testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+ consumerProguardFiles 'consumer-rules.pro'
+ }
+
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+ }
+ }
+
+}
+
+dependencies {
+ implementation fileTree(dir: 'libs', include: ['*.jar'])
+
+ implementation 'androidx.appcompat:appcompat:1.0.2'
+ testImplementation 'junit:junit:4.12'
+ androidTestImplementation 'androidx.test.ext:junit:1.1.1'
+ androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
+ implementation fileTree(dir: 'libs', include: ['*.aar', '*.jar'], exclude: [])
+}
diff --git a/im_lib/consumer-rules.pro b/im_lib/consumer-rules.pro
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/im_lib/consumer-rules.pro
diff --git a/im_lib/libs/netty-all-4.1.43.jar b/im_lib/libs/netty-all-4.1.43.jar
new file mode 100644
index 0000000..a0b8316
--- /dev/null
+++ b/im_lib/libs/netty-all-4.1.43.jar
Binary files differ
diff --git a/im_lib/proguard-rules.pro b/im_lib/proguard-rules.pro
new file mode 100644
index 0000000..f1b4245
--- /dev/null
+++ b/im_lib/proguard-rules.pro
@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
diff --git a/im_lib/src/androidTest/java/com/anyun/im_lib/ExampleInstrumentedTest.java b/im_lib/src/androidTest/java/com/anyun/im_lib/ExampleInstrumentedTest.java
new file mode 100644
index 0000000..e58f22a
--- /dev/null
+++ b/im_lib/src/androidTest/java/com/anyun/im_lib/ExampleInstrumentedTest.java
@@ -0,0 +1,27 @@
+package com.anyun.im_lib;
+
+import android.content.Context;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.*;
+
+/**
+ * Instrumented test, which will execute on an Android device.
+ *
+ * @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
+ */
+@RunWith(AndroidJUnit4.class)
+public class ExampleInstrumentedTest {
+ @Test
+ public void useAppContext() {
+ // Context of the app under test.
+ Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
+
+ assertEquals("com.anyun.im_lib.test", appContext.getPackageName());
+ }
+}
diff --git a/im_lib/src/main/AndroidManifest.xml b/im_lib/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..a7663f8
--- /dev/null
+++ b/im_lib/src/main/AndroidManifest.xml
@@ -0,0 +1,2 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.anyun.im_lib" />
diff --git a/im_lib/src/main/java/com/anyun/im_lib/ExecutorServiceFactory.java b/im_lib/src/main/java/com/anyun/im_lib/ExecutorServiceFactory.java
new file mode 100644
index 0000000..410c052
--- /dev/null
+++ b/im_lib/src/main/java/com/anyun/im_lib/ExecutorServiceFactory.java
@@ -0,0 +1,100 @@
+package com.anyun.im_lib;
+
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+/**
+ * MyApplication2
+ * Created by lzw on 2019/12/2. 14:15:59
+ * 閭锛�632393724@qq.com
+ * All Rights Saved! Chongqing AnYun Tech co. LTD
+ */
+public class ExecutorServiceFactory {
+
+ /*** 绠$悊绾跨▼缁勶紝璐熻矗閲嶈繛***/
+ private ExecutorService bossPool;
+ /*** 宸ヤ綔绾跨▼缁勶紝璐熻矗蹇冭烦***/
+ private ExecutorService workPool;
+
+ /**
+ * 鍒濆鍖朆oss绾跨▼姹�
+ */
+ public synchronized void initBossLoopGroup(){
+ initBossLoopGroup(1);
+ }
+
+ /**
+ * 鍒濆鍖杦ork绾跨▼姹�
+ */
+ public synchronized void initWorkLoopGroup(){
+ initWorkLoopGroup(1);
+ }
+
+ /**
+ * 鎵цBoss浠诲姟
+ * @param runnable
+ */
+ public void execBossTask(Runnable runnable){
+ if (bossPool == null){
+ initBossLoopGroup();
+ }
+ bossPool.execute(runnable);
+ }
+ /**
+ * 鎵цwork浠诲姟
+ * @param runnable
+ */
+ public void execWorkTask(Runnable runnable){
+ if (workPool == null){
+ initWorkLoopGroup();
+ }
+ workPool.execute(runnable);
+ }
+
+ private void initWorkLoopGroup(int size) {
+ destroyWorkLoopGroup();
+ workPool = Executors.newFixedThreadPool(size);
+ }
+
+ private void initBossLoopGroup(int size) {
+ destroyBossLoopGroup();
+ bossPool = Executors.newFixedThreadPool(size);
+ }
+
+ /**
+ * 閲婃斁boss绾跨▼姹�
+ */
+ private void destroyBossLoopGroup() {
+ if (bossPool != null){
+ try {
+ bossPool.shutdownNow();
+ } catch (Exception e) {
+ e.printStackTrace();
+ } finally {
+ bossPool = null;
+ }
+ }
+ }
+ /**
+ * 閲婃斁work绾跨▼姹�
+ */
+ public void destroyWorkLoopGroup() {
+ if (workPool != null){
+ try {
+ workPool.shutdownNow();
+ } catch (Exception e) {
+ e.printStackTrace();
+ } finally {
+ workPool = null;
+ }
+ }
+ }
+
+ /**
+ * 閲婃斁鎵�鏈夌嚎绋�
+ */
+ public void destroy() {
+ destroyBossLoopGroup();
+ destroyWorkLoopGroup();
+ }
+}
diff --git a/im_lib/src/main/java/com/anyun/im_lib/HeartbeatHandler.java b/im_lib/src/main/java/com/anyun/im_lib/HeartbeatHandler.java
new file mode 100644
index 0000000..a0e4314
--- /dev/null
+++ b/im_lib/src/main/java/com/anyun/im_lib/HeartbeatHandler.java
@@ -0,0 +1,12 @@
+package com.anyun.im_lib;
+
+import io.netty.channel.ChannelInboundHandlerAdapter;
+
+/**
+ * MyApplication2
+ * Created by lzw on 2019/12/4. 11:31:25
+ * 閭锛�632393724@qq.com
+ * All Rights Saved! Chongqing AnYun Tech co. LTD
+ */
+public class HeartbeatHandler extends ChannelInboundHandlerAdapter {
+}
diff --git a/im_lib/src/main/java/com/anyun/im_lib/HeartbeatRespHandler.java b/im_lib/src/main/java/com/anyun/im_lib/HeartbeatRespHandler.java
new file mode 100644
index 0000000..ba1c8bf
--- /dev/null
+++ b/im_lib/src/main/java/com/anyun/im_lib/HeartbeatRespHandler.java
@@ -0,0 +1,22 @@
+package com.anyun.im_lib;
+
+import com.anyun.im_lib.interf.IMSClientInteface;
+
+import io.netty.channel.ChannelInboundHandlerAdapter;
+
+/**
+ * MyApplication2
+ * Created by lzw on 2019/12/4. 11:50:05
+ * 閭锛�632393724@qq.com
+ * All Rights Saved! Chongqing AnYun Tech co. LTD
+ */
+public class HeartbeatRespHandler extends ChannelInboundHandlerAdapter {
+
+ private static final String TAG = HeartbeatRespHandler.class.getSimpleName();
+
+ private IMSClientInteface imsClient;
+
+ public HeartbeatRespHandler(IMSClientInteface imsClient) {
+ this.imsClient = imsClient;
+ }
+}
diff --git a/im_lib/src/main/java/com/anyun/im_lib/IMSClientFactory.java b/im_lib/src/main/java/com/anyun/im_lib/IMSClientFactory.java
new file mode 100644
index 0000000..d3f69dc
--- /dev/null
+++ b/im_lib/src/main/java/com/anyun/im_lib/IMSClientFactory.java
@@ -0,0 +1,16 @@
+package com.anyun.im_lib;
+
+import com.anyun.im_lib.interf.IMSClientInteface;
+import com.anyun.im_lib.netty.NettyTcpClient;
+
+/**
+ * MyApplication2
+ * Created by lzw on 2019/12/2. 13:13:44
+ * 閭锛�632393724@qq.com
+ * All Rights Saved! Chongqing AnYun Tech co. LTD
+ */
+public class IMSClientFactory {
+ public static IMSClientInteface getIMSClient() {
+ return NettyTcpClient.getInstance();
+ }
+}
diff --git a/im_lib/src/main/java/com/anyun/im_lib/IMSConfig.java b/im_lib/src/main/java/com/anyun/im_lib/IMSConfig.java
new file mode 100644
index 0000000..b091c5c
--- /dev/null
+++ b/im_lib/src/main/java/com/anyun/im_lib/IMSConfig.java
@@ -0,0 +1,28 @@
+package com.anyun.im_lib;
+
+/**
+ * MyApplication2
+ * Created by lzw on 2019/12/2. 14:16:22
+ * 閭锛�632393724@qq.com
+ * All Rights Saved! Chongqing AnYun Tech co. LTD
+ */
+public class IMSConfig {
+ public static final int CONNECT_STATE_FAILURE = -1;
+ public static final int DEFAULT_RECONNECT_BASE_DELAY_TIME = 3 * 1000;
+ public static final int DEFAULT_CONNECT_TIMEOUT = 10 * 1000;
+ public static final int DEFAULT_HEARTBEAT_INTERVAL_FOREGROUND = 3 * 1000;
+ public static final int DEFAULT_HEARTBEAT_INTERVAL_BACKGROUND = 30 * 1000;
+
+ /*** 搴旂敤鍦ㄥ墠鍙版爣璇�***/
+ public static final int APP_STATUS_FOREGROUND = 0;
+ /*** 搴旂敤鍦ㄥ悗鍙版爣璇�***/
+ public static final int APP_STATUS_BACKGROUND = -1;
+ /*** 榛樿娑堟伅鍙戦�佸け璐ラ噸鍙戞鏁� ***/
+ public static final int DEFAULT_RESEND_COUNT = 3;
+ public static final int DEFAULT_RESEND_INTERVAL = 8 * 1000;
+
+ /******榛樿閲嶈繛涓�涓懆鏈熷け璐ラ棿闅旀椂闀�******/
+ public static final int DEFAULT_RECONNECT_INTERVAL = 3 * 1000;
+ public static final int CONNECT_STATE_CONNECTING = 0;
+ public static final int CONNECT_STATE_SUCCESSFUL = 1;
+}
diff --git a/im_lib/src/main/java/com/anyun/im_lib/LoginAuthRespHandler.java b/im_lib/src/main/java/com/anyun/im_lib/LoginAuthRespHandler.java
new file mode 100644
index 0000000..a3c6191
--- /dev/null
+++ b/im_lib/src/main/java/com/anyun/im_lib/LoginAuthRespHandler.java
@@ -0,0 +1,42 @@
+package com.anyun.im_lib;
+
+import android.util.Log;
+
+import com.anyun.im_lib.interf.IMSClientInteface;
+
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.channel.ChannelInboundHandlerAdapter;
+
+/**
+ * MyApplication2
+ * 璁惧閴存潈
+ * Created by lzw on 2019/12/4. 11:25:33
+ * 閭锛�632393724@qq.com
+ * All Rights Saved! Chongqing AnYun Tech co. LTD
+ */
+public class LoginAuthRespHandler extends ChannelInboundHandlerAdapter {
+
+ private static final String TAG = LoginAuthRespHandler.class.getSimpleName();
+ private IMSClientInteface imsClient;
+
+ /**
+ * 鏋勯�犲嚱鏁�
+ * @param imsClient
+ */
+ public LoginAuthRespHandler(IMSClientInteface imsClient) {
+ this.imsClient = imsClient;
+ }
+
+ @Override
+ public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
+ super.channelReadComplete(ctx);
+ Log.i(TAG, "channelReadComplete");
+ }
+
+ @Override
+ public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
+ super.channelRead(ctx, msg);
+ Log.i(TAG, "channelRead");
+ // TODO: 2019/12/4
+ }
+}
diff --git a/im_lib/src/main/java/com/anyun/im_lib/MsgDispatcher.java b/im_lib/src/main/java/com/anyun/im_lib/MsgDispatcher.java
new file mode 100644
index 0000000..93da0f0
--- /dev/null
+++ b/im_lib/src/main/java/com/anyun/im_lib/MsgDispatcher.java
@@ -0,0 +1,15 @@
+package com.anyun.im_lib;
+
+import com.anyun.im_lib.listener.OnEventListener;
+
+/**
+ * MyApplication2
+ * Created by lzw on 2019/12/2. 14:02:14
+ * 閭锛�632393724@qq.com
+ * All Rights Saved! Chongqing AnYun Tech co. LTD
+ */
+public class MsgDispatcher {
+ public void setOnEventListener(OnEventListener listener) {
+
+ }
+}
diff --git a/im_lib/src/main/java/com/anyun/im_lib/MsgTimeOutTimerManager.java b/im_lib/src/main/java/com/anyun/im_lib/MsgTimeOutTimerManager.java
new file mode 100644
index 0000000..33635fb
--- /dev/null
+++ b/im_lib/src/main/java/com/anyun/im_lib/MsgTimeOutTimerManager.java
@@ -0,0 +1,33 @@
+package com.anyun.im_lib;
+
+import com.anyun.im_lib.interf.IMSClientInteface;
+import com.anyun.im_lib.netty.NettyTcpClient;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * MyApplication2
+ * Created by lzw on 2019/12/2. 14:03:15
+ * 閭锛�632393724@qq.com
+ * All Rights Saved! Chongqing AnYun Tech co. LTD
+ */
+public class MsgTimeOutTimerManager {
+ private IMSClientInteface imsClient;
+ private Map<String,MsgTimeoutTimer> mMsgTimeoutMap = new HashMap<>();
+
+ public MsgTimeOutTimerManager(NettyTcpClient nettyTcpClient) {
+ this.imsClient = nettyTcpClient;
+ }
+
+ /**
+ * 娣诲姞娑堟伅鍒板彂閫佽秴鏃剁鐞嗗櫒
+ * @param message
+ */
+ public void add(String message){
+
+ if (message == null ){
+
+ }
+ }
+}
diff --git a/im_lib/src/main/java/com/anyun/im_lib/MsgTimeoutTimer.java b/im_lib/src/main/java/com/anyun/im_lib/MsgTimeoutTimer.java
new file mode 100644
index 0000000..eaf3747
--- /dev/null
+++ b/im_lib/src/main/java/com/anyun/im_lib/MsgTimeoutTimer.java
@@ -0,0 +1,36 @@
+package com.anyun.im_lib;
+
+import android.util.Log;
+
+import com.anyun.im_lib.interf.IMSClientInteface;
+
+import java.util.Timer;
+import java.util.TimerTask;
+
+/**
+ * MyApplication2
+ * Created by lzw on 2019/12/2. 15:09:39
+ * 閭锛�632393724@qq.com
+ * All Rights Saved! Chongqing AnYun Tech co. LTD
+ */
+public class MsgTimeoutTimer extends Timer {
+ private static final String TAG = "MsgTimeoutTimer";
+ private IMSClientInteface imsClient;
+ private Object message;//鍙戦�佺殑娑堟伅
+ private int currentResendCount;//褰撳墠閲嶅彂娆℃暟
+ private MsgTimeoutTask task;//娑堟伅鍙戦�佽秴鏃朵换鍔�
+
+ public MsgTimeoutTimer(IMSClientInteface imsClient) {
+ Log.i(TAG, "MsgTimeoutTimer: ");
+ this.imsClient = imsClient;
+ this.schedule(task,imsClient.getResendInterval(),imsClient.getResendInterval());
+ }
+
+ private class MsgTimeoutTask extends TimerTask{
+
+ @Override
+ public void run() {
+
+ }
+ }
+}
diff --git a/im_lib/src/main/java/com/anyun/im_lib/im/IMSClientBootstrap.java b/im_lib/src/main/java/com/anyun/im_lib/im/IMSClientBootstrap.java
new file mode 100644
index 0000000..d4d001c
--- /dev/null
+++ b/im_lib/src/main/java/com/anyun/im_lib/im/IMSClientBootstrap.java
@@ -0,0 +1,61 @@
+package com.anyun.im_lib.im;
+
+import android.util.Log;
+
+import com.anyun.im_lib.IMSClientFactory;
+import com.anyun.im_lib.interf.IMSClientInteface;
+
+import java.util.Vector;
+
+import static android.content.ContentValues.TAG;
+
+/**
+ * MyApplication2
+ * Created by lzw on 2019/12/2. 11:56:55
+ * 閭锛�632393724@qq.com
+ * All Rights Saved! Chongqing AnYun Tech co. LTD
+ */
+public class IMSClientBootstrap {
+
+ private static final IMSClientBootstrap INSTANCE= new IMSClientBootstrap();
+ private IMSClientInteface imsClient;
+
+ /**鏍囪IMSClientBootstrap鏄惁宸茬粡鍒濆鍖�**/
+ private boolean isAlive;
+
+ /**
+ *
+ * @param userId
+ * @param token
+ * @param hosts
+ * @param appStatus
+ */
+ public synchronized void init(String userId,String token,String hosts,int appStatus){
+ if (!isAlive){
+ Vector<String> serverUrlList = convertHosts(hosts);
+ if (serverUrlList == null || serverUrlList.size() ==0){
+ Log.i(TAG, "init IMLibClientBootstrap error,ims hosts is null");
+ return;
+ }
+ isAlive = true;
+ Log.i(TAG, "init IMLibClientBootstrap ,server="+hosts);
+ }
+ if (null != imsClient){
+ imsClient.close();
+ }
+ //鍒濆鍖朓MSClientInteface
+ imsClient = IMSClientFactory.getIMSClient();
+ updateAppStatus(appStatus);
+// imsClient.init(serverUrlList,new OnEventListener(userId,token),new IMSConnectStatusCallback());
+ }
+
+
+
+ private void updateAppStatus(int appStatus) {
+ }
+
+ private Vector<String> convertHosts(String hosts) {
+ //TODO
+ return null;
+ }
+}
diff --git a/im_lib/src/main/java/com/anyun/im_lib/interf/IMSClientInteface.java b/im_lib/src/main/java/com/anyun/im_lib/interf/IMSClientInteface.java
new file mode 100644
index 0000000..2f04a29
--- /dev/null
+++ b/im_lib/src/main/java/com/anyun/im_lib/interf/IMSClientInteface.java
@@ -0,0 +1,114 @@
+package com.anyun.im_lib.interf;
+
+import com.anyun.im_lib.MsgDispatcher;
+import com.anyun.im_lib.MsgTimeOutTimerManager;
+import com.anyun.im_lib.listener.IMSConnectStatusCallback;
+import com.anyun.im_lib.listener.OnEventListener;
+
+import java.util.Vector;
+
+/**
+ * MyApplication2
+ * Created by lzw on 2019/12/2. 11:58:51
+ * 閭锛�632393724@qq.com
+ * All Rights Saved! Chongqing AnYun Tech co. LTD
+ */
+public interface IMSClientInteface {
+ /**
+ * 鍒濆鍖�
+ * @param serverUrlList
+ * @param listener
+ * @param callback
+ */
+ void init(Vector<String> serverUrlList, OnEventListener listener, IMSConnectStatusCallback callback);
+
+ /**
+ * 閲嶇疆杩炴帴锛屼篃灏辨槸閲嶈繛
+ * 棣栨杩炴帴涔熷彲璁や负鏄噸杩�
+ */
+ void resetConnect();
+ /**
+ * 閲嶇疆杩炴帴锛屼篃灏辨槸閲嶈繛
+ * 棣栨杩炴帴涔熷彲璁や负鏄噸杩�
+ * 閲嶈浇
+ * @param isFirst 鏄惁棣栨杩炴帴
+ */
+ void resetConnect(boolean isFirst);
+
+ /**
+ * 鍏抽棴杩炴帴锛屽悓鏃堕噴鏀捐祫婧�
+ */
+ void close();
+
+ /**
+ * 琛ㄧずims鏄惁宸茬粡鍏抽棴
+ * @return
+ */
+ boolean isClosed();
+
+ /**
+ * 鍙戦�佹秷鎭�
+ * @param msg
+ */
+ void sendMsg(String msg);
+
+ /**
+ * 鍙戦�佹秷鎭�
+ * 閲嶈浇
+ * @param msg
+ * @param isJoinTimeoutManager 鏄惁鍔犲叆瓒呮椂绠$悊鍣�
+ */
+ void sendMsg(String msg, boolean isJoinTimeoutManager);
+
+ /**
+ * 鑾峰彇閲嶈繛闂撮殧鏃堕暱
+ * @return
+ */
+ int getReconnectInterval();
+
+
+ /**
+ * 鑾峰彇杩為棿闅旀椂闀�
+ * @return
+ */
+ int getConnectTimeout();
+ /**
+ * 鑾峰彇搴旂敤鍦ㄥ墠鍙版椂蹇冭烦闂撮殧
+ * @return
+ */
+ int getForegroundHeartbeatInterval();
+
+ /**
+ * 璁剧疆app鍓嶅悗鍙扮姸鎬�
+ * @param appStatus
+ */
+ void setAppStatus(int appStatus);
+
+ /**
+ * 鑾峰彇搴旂敤鍦ㄥ悗鍙版椂蹇冭烦闂撮殧
+ * @return
+ */
+ int getBackgroundHeartbeatInterval();
+
+ /**
+ * 鑾峰彇搴旂敤灞傛秷鎭彂閫佽秴鏃堕噸鍙戞鏁�
+ * @return
+ */
+ int getResendCount();
+
+ /**
+ * 鑾峰彇搴旂敤灞傛秷鎭彂閫佽秴鏃堕棿闅�
+ * @return
+ */
+ int getResendInterval();
+
+ /**
+ * 鑾峰彇娑堟伅杞彂鍣�
+ * @return
+ */
+ MsgDispatcher getMsgDispatcher();
+
+ MsgTimeOutTimerManager getMsgTimeOutTimerManager();
+
+
+}
diff --git a/im_lib/src/main/java/com/anyun/im_lib/listener/IMSConnectStatusCallback.java b/im_lib/src/main/java/com/anyun/im_lib/listener/IMSConnectStatusCallback.java
new file mode 100644
index 0000000..f6a4f3e
--- /dev/null
+++ b/im_lib/src/main/java/com/anyun/im_lib/listener/IMSConnectStatusCallback.java
@@ -0,0 +1,20 @@
+package com.anyun.im_lib.listener;
+
+/**
+ * MyApplication2
+ * Created by lzw on 2019/12/2. 13:18:05
+ * 閭锛�632393724@qq.com
+ * All Rights Saved! Chongqing AnYun Tech co. LTD
+ */
+public interface IMSConnectStatusCallback {
+ /***ims杩炴帴涓�*/
+ void connecting();
+
+ /***ims杩炴帴鎴愬姛**/
+ void onConnected();
+
+ /***ims杩炴帴澶辫触**/
+ void onConnectFailed();
+
+
+}
diff --git a/im_lib/src/main/java/com/anyun/im_lib/listener/OnEventListener.java b/im_lib/src/main/java/com/anyun/im_lib/listener/OnEventListener.java
new file mode 100644
index 0000000..be669eb
--- /dev/null
+++ b/im_lib/src/main/java/com/anyun/im_lib/listener/OnEventListener.java
@@ -0,0 +1,51 @@
+package com.anyun.im_lib.listener;
+
+/**
+ * MyApplication2
+ * Created by lzw on 2019/12/2. 13:17:49
+ * 閭锛�632393724@qq.com
+ * All Rights Saved! Chongqing AnYun Tech co. LTD
+ */
+public interface OnEventListener {
+ /**
+ * 鍒嗗彂娑堟伅鍒板簲鐢ㄥ眰
+ * @param message
+ */
+ void dispatchMsg(Object message);
+
+ /**
+ * 浠庡簲鐢ㄥ眰鑾峰彇缃戠粶鏄惁鍙敤
+ * @return
+ */
+ boolean isNetWorkAvailable();
+
+ /**
+ * 鑾峰彇閲嶈繛闂撮殧鏃堕暱
+ * @return
+ */
+ int getConnectTimeout();
+
+ /**
+ * 鑾峰彇搴旂敤鍦ㄥ墠鍙版椂蹇冭烦闂撮殧
+ * @return
+ */
+ int getForegroundHeartbeatInterval();
+
+ /**
+ * 鑾峰彇搴旂敤鍦ㄥ悗鍙版椂蹇冭烦闂撮殧
+ * @return
+ */
+ int getBackgroundHeartbeatInterval();
+
+ /**
+ * 鑾峰彇搴旂敤灞傛秷鎭彂閫佽秴鏃堕噸鍙戞鏁�
+ * @return
+ */
+ int getResendCount();
+
+ /**
+ * 鑾峰彇搴旂敤灞傛秷鎭彂閫佽秴鏃堕棿闅�
+ * @return
+ */
+ int getResendInterval();
+}
diff --git a/im_lib/src/main/java/com/anyun/im_lib/netty/NettyTcpClient.java b/im_lib/src/main/java/com/anyun/im_lib/netty/NettyTcpClient.java
new file mode 100644
index 0000000..3cec3b8
--- /dev/null
+++ b/im_lib/src/main/java/com/anyun/im_lib/netty/NettyTcpClient.java
@@ -0,0 +1,378 @@
+package com.anyun.im_lib.netty;
+
+import android.text.TextUtils;
+import android.util.Log;
+
+import com.anyun.im_lib.ExecutorServiceFactory;
+import com.anyun.im_lib.HeartbeatHandler;
+import com.anyun.im_lib.IMSConfig;
+import com.anyun.im_lib.MsgDispatcher;
+import com.anyun.im_lib.MsgTimeOutTimerManager;
+import com.anyun.im_lib.interf.IMSClientInteface;
+import com.anyun.im_lib.listener.IMSConnectStatusCallback;
+import com.anyun.im_lib.listener.OnEventListener;
+
+import java.util.Vector;
+
+import io.netty.bootstrap.Bootstrap;
+import io.netty.channel.Channel;
+import io.netty.channel.ChannelOption;
+import io.netty.channel.EventLoopGroup;
+import io.netty.channel.nio.NioEventLoopGroup;
+import io.netty.channel.socket.nio.NioSocketChannel;
+import io.netty.handler.timeout.IdleStateHandler;
+
+
+/**
+ * MyApplication2
+ * Created by lzw on 2019/12/2. 13:14:52
+ * 閭锛�632393724@qq.com
+ * All Rights Saved! Chongqing AnYun Tech co. LTD
+ */
+public class NettyTcpClient implements IMSClientInteface {
+
+ private static final String TAG = NettyTcpClient.class.getSimpleName();
+
+ private static volatile NettyTcpClient instance;
+
+ private Bootstrap bootstrap;
+ private Channel channel;
+
+ /****鏍囪瘑IMS鏄惁宸插叧闂�***/
+ private boolean isClosed = false;
+
+ /****ims鏈嶅姟鍣ㄥ湴鍧�缁�***/
+ private Vector<String> serverUrlList;
+
+ /****涓庡簲鐢ㄥ眰浜や簰鐨刲istener***/
+ private OnEventListener mOnEventListener;
+ /*** ims杩炴帴鐘舵�佸洖璋冪洃鍚櫒**/
+ private IMSConnectStatusCallback imsConnectStatusCallback;
+
+ /****娑堟伅杞彂鍣�***/
+ private MsgDispatcher msgDispatcher;
+
+ /***绾跨▼姹犲伐鍘�**/
+ private ExecutorServiceFactory loopGroup;
+
+ /****鏄惁姝e湪杩涜閲嶈繛***/
+ private boolean isReconnecting = false;
+ /*** ims杩炴帴鐘舵�侊紝鍒濆鍖栦负杩炴帴澶辫触 ***/
+ private int connectStatus = IMSConfig.CONNECT_STATE_FAILURE;
+
+ /*** 閲嶈繛闂撮殧鏃堕暱 ***/
+ private int reconnectInterval = IMSConfig.DEFAULT_RECONNECT_BASE_DELAY_TIME;
+ /*** 杩炴帴瓒呮椂鏃堕暱 ***/
+ private int connectTimeOut = IMSConfig.DEFAULT_CONNECT_TIMEOUT;
+
+ private int heartBeatInterval = IMSConfig.DEFAULT_HEARTBEAT_INTERVAL_FOREGROUND;
+ private int foregroundHeartBeatInterval = IMSConfig.DEFAULT_HEARTBEAT_INTERVAL_FOREGROUND;
+ private int backgroundHeartBeatInterval = IMSConfig.DEFAULT_HEARTBEAT_INTERVAL_BACKGROUND;
+
+ private int appStatus = IMSConfig.APP_STATUS_FOREGROUND;
+ /*** 娑堟伅鍙戦�佽秴鏃堕噸鍙戞鏁�***/
+ private int resendCount = IMSConfig.DEFAULT_RESEND_COUNT;
+ /*** 娑堟伅鍙戦�佸け璐ラ噸鍙戦棿闅旀椂闀�***/
+ private int resendInterval = IMSConfig.DEFAULT_RESEND_INTERVAL;
+
+ /*** 褰撳墠杩炴帴host***/
+ private String currentHost = null;
+ /*** 褰撳墠杩炴帴port***/
+ private int currentPort = -1;
+ /*** 娑堟伅鍙戦�佽秴鏃跺畾鏃剁鐞嗗櫒***/
+ private MsgTimeOutTimerManager msgTimeOutTimerManager;
+
+
+ private NettyTcpClient(){
+
+ }
+
+ public static IMSClientInteface getInstance() {
+ if (null == instance){
+ synchronized (NettyTcpClient.class){
+ if (null==instance){
+ instance = new NettyTcpClient();
+ }
+ }
+ }
+ return instance;
+ }
+
+ /**
+ * 鍒濆鍖�
+ * @param serverUrlList 鏈嶅姟鍣ㄥ湴鍧�鍒楄〃
+ * @param listener 涓庡簲鐢ㄥ眰浜や簰鐨刲istener
+ * @param callback ims杩炴帴鐘舵�佸洖璋�
+ */
+ @Override
+ public void init(Vector<String> serverUrlList, OnEventListener listener, IMSConnectStatusCallback callback) {
+ close();
+ isClosed = false;
+ this.serverUrlList = serverUrlList;
+ this.mOnEventListener = listener;
+ this.imsConnectStatusCallback = callback;
+ msgDispatcher = new MsgDispatcher();
+ msgDispatcher.setOnEventListener(listener);
+ loopGroup = new ExecutorServiceFactory();
+ loopGroup.initBossLoopGroup();
+ msgTimeOutTimerManager = new MsgTimeOutTimerManager(this);
+ /*** 杩涜绗竴娆¤繛鎺�***/
+ resetConnect(true);
+ }
+
+ @Override
+ public void resetConnect() {
+ this.resetConnect(false);
+ }
+
+ @Override
+ public void resetConnect(boolean isFirst) {
+ if (!isFirst){
+ try {
+ Thread.sleep(IMSConfig.DEFAULT_RECONNECT_INTERVAL);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+ //鍙湁绗竴涓皟鐢ㄨ�呮墠鑳借祴鍊煎苟璋冪敤閲嶈繛
+ if (!isClosed && !isReconnecting){
+ synchronized (this){
+ if (!isClosed && !isReconnecting){
+ //鏍囪瘑閲嶈繛浠诲姟杩涜涓�...
+ isReconnecting = true;
+
+ onConnectStatusCallback(IMSConfig.CONNECT_STATE_CONNECTING);
+ closeChannel();
+ loopGroup.execBossTask(new ResetConnectRunnable(isFirst));
+ }
+ }
+ }
+ }
+
+ private class ResetConnectRunnable implements Runnable{
+ private boolean isFirst;
+ public ResetConnectRunnable(boolean isFirst) {
+ this.isFirst = isFirst;
+ }
+
+ @Override
+ public void run() {
+ if (!isFirst){
+ onConnectStatusCallback(IMSConfig.CONNECT_STATE_FAILURE);
+ }
+ try {
+ //閲嶈繛鏃讹紝閲婃斁宸ヤ綔缁勭嚎绋嬫睜锛屼篃灏辨槸鍋滄蹇冭烦
+ loopGroup.destroyWorkLoopGroup();
+ while (!isClosed){
+ if (!isNetworkAvaliable()){
+ try {
+ Thread.sleep(2000);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ continue;
+ }
+ //缃戠粶鍙敤鎵嶈繘琛岃繛鎺�
+ int status;
+ if ((status=reConnect()) == IMSConfig.CONNECT_STATE_SUCCESSFUL){
+ onConnectStatusCallback(status);
+ //杩炴帴鎴愬姛锛岃皟鍑哄惊鐜�
+ break;
+ }
+
+ if (status == IMSConfig.CONNECT_STATE_FAILURE){
+ onConnectStatusCallback(status);
+ try {
+ Thread.sleep(IMSConfig.DEFAULT_RECONNECT_INTERVAL);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ } finally {
+ //鏍囪瘑閲嶈繛浠诲姟鍋滄
+ isReconnecting = false;
+ }
+ }
+ }
+
+ /**
+ * 閲嶈繛锛岄娆¤繛鎺ヤ篃璁や负鏄涓�娆¢噸杩�
+ * @return
+ */
+ private int reConnect() {
+ if (!isClosed){
+ try {
+ //鍏堥噴鏀綞ventLoop绾跨▼缁�
+ if (bootstrap != null){
+ bootstrap.group().shutdownGracefully();
+ }
+ } finally {
+ bootstrap = null;
+ }
+ initBootstrap();
+ return connectServer();
+ }
+ return IMSConfig.CONNECT_STATE_FAILURE;
+ }
+
+ /***
+ * 鍒濆鍖朆ootstrap
+ */
+ private void initBootstrap() {
+ EventLoopGroup loopGroup = new NioEventLoopGroup(4);
+ bootstrap = new Bootstrap();
+ bootstrap.group(loopGroup).channel(NioSocketChannel.class);
+ // 璁剧疆璇ラ」浠ュ悗锛屽鏋滃湪涓ゅ皬鏃跺唴娌℃湁鏁版嵁閫氫俊鏃讹紝TCP浼氳嚜鍔ㄥ彂閫佷竴涓椿鍔ㄦ帰娴嬫暟鎹姤鏂�
+ bootstrap.option(ChannelOption.SO_KEEPALIVE,true);
+ bootstrap.option(ChannelOption.CONNECT_TIMEOUT_MILLIS,getConnectTimeout());
+ bootstrap.handler(new TCPChannelInitializerHandler(this));
+ }
+
+ private int connectServer(){
+ if (serverUrlList == null || serverUrlList.size() == 0){
+ return IMSConfig.CONNECT_STATE_FAILURE;
+ }
+ for (int i = 0; i < serverUrlList.size(); i++) {
+ String serverUrl = serverUrlList.get(i);
+ if (TextUtils.isEmpty(serverUrl)){
+ return IMSConfig.CONNECT_STATE_FAILURE;
+ }
+ }
+ }
+
+ private boolean isNetworkAvaliable() {
+ if (mOnEventListener != null){
+ return mOnEventListener.isNetWorkAvailable();
+ }
+ return false;
+ }
+
+ private void onConnectStatusCallback(int connectStateConnecting) {
+ }
+
+ @Override
+ public void close() {
+ if (isClosed){
+ return;
+ }
+ isClosed = true;
+ /*** 鍏抽棴channel***/
+ try {
+ closeChannel();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ /*** 鍏抽棴bootstrap ***/
+ try {
+ if (bootstrap != null){
+ bootstrap.group().shutdownGracefully();
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ /*** 閲婃斁绾跨▼姹� ***/
+ try {
+ if (loopGroup != null){
+ loopGroup.destroy();
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ } finally {
+ try {
+ if (serverUrlList != null){
+ serverUrlList.clear();
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ isReconnecting = false;
+ channel = null;
+ bootstrap = null;
+ }
+ }
+
+ private void closeChannel() {
+ if (channel != null){
+ removeHandler(HeartbeatHandler.class.getSimpleName());
+ removeHandler(TCPReadHandler.class.getSimpleName());
+ removeHandler(IdleStateHandler.class.getSimpleName());
+ }
+ }
+
+ /**
+ * 绉婚櫎鎸囧畾handler
+ * @param handlerName
+ */
+ private void removeHandler(String handlerName) {
+ try {
+ if (channel.pipeline().get(handlerName) != null){
+ channel.pipeline().remove(handlerName);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ Log.i(TAG, "removeHandler fail,handlerName="+handlerName);
+ }
+ }
+
+ @Override
+ public boolean isClosed() {
+ return false;
+ }
+
+ @Override
+ public void sendMsg(String msg) {
+
+ }
+
+ @Override
+ public void sendMsg(String msg, boolean isJoinTimeoutManager) {
+
+ }
+
+ @Override
+ public int getReconnectInterval() {
+ return 0;
+ }
+
+ @Override
+ public int getConnectTimeout() {
+ return 0;
+ }
+
+ @Override
+ public int getForegroundHeartbeatInterval() {
+ return 0;
+ }
+
+ @Override
+ public void setAppStatus(int appStatus) {
+
+ }
+
+ @Override
+ public int getBackgroundHeartbeatInterval() {
+ return 0;
+ }
+
+ @Override
+ public int getResendCount() {
+ return 0;
+ }
+
+ @Override
+ public int getResendInterval() {
+ return 0;
+ }
+
+ @Override
+ public MsgDispatcher getMsgDispatcher() {
+ return null;
+ }
+
+ @Override
+ public MsgTimeOutTimerManager getMsgTimeOutTimerManager() {
+ return null;
+ }
+}
diff --git a/im_lib/src/main/java/com/anyun/im_lib/netty/TCPChannelInitializerHandler.java b/im_lib/src/main/java/com/anyun/im_lib/netty/TCPChannelInitializerHandler.java
new file mode 100644
index 0000000..fe1b127
--- /dev/null
+++ b/im_lib/src/main/java/com/anyun/im_lib/netty/TCPChannelInitializerHandler.java
@@ -0,0 +1,44 @@
+package com.anyun.im_lib.netty;
+
+import com.anyun.im_lib.HeartbeatRespHandler;
+import com.anyun.im_lib.LoginAuthRespHandler;
+import com.anyun.im_lib.interf.IMSClientInteface;
+
+import io.netty.channel.Channel;
+import io.netty.channel.ChannelInitializer;
+import io.netty.channel.ChannelPipeline;
+
+/**
+ * MyApplication2
+ * channel鍒濆鍖�
+ * Created by lzw on 2019/12/2. 15:56:39
+ * 閭锛�632393724@qq.com
+ * All Rights Saved! Chongqing AnYun Tech co. LTD
+ */
+public class TCPChannelInitializerHandler extends ChannelInitializer<Channel> {
+
+ private IMSClientInteface imsClient;
+
+ public TCPChannelInitializerHandler(NettyTcpClient nettyTcpClient) {
+ this.imsClient = nettyTcpClient;
+ }
+
+ @Override
+ protected void initChannel(Channel channel) throws Exception {
+ ChannelPipeline pipeline = channel.pipeline();
+
+ //netty鎻愪緵鐨勮嚜瀹氫箟闀垮害瑙g爜鍣紝瑙e喅TP鎷嗗寘/绮樺寘闂
+
+ // TODO: 2019/12/4
+
+
+ //鎻℃墜璁よ瘉娑堟伅鐩稿簲澶勭悊handler
+ pipeline.addLast(LoginAuthRespHandler.class.getSimpleName(), new LoginAuthRespHandler(imsClient));
+
+ //蹇冭烦娑堟伅鍝嶅簲澶勭悊handler
+ pipeline.addLast(HeartbeatRespHandler.class.getSimpleName(), new HeartbeatRespHandler(imsClient));
+
+ //鎺ユ敹娑堟伅澶勭悊handler
+ pipeline.addLast(TCPReadHandler.class.getSimpleName(),new TCPReadHandler(imsClient));
+ }
+}
diff --git a/im_lib/src/main/java/com/anyun/im_lib/netty/TCPReadHandler.java b/im_lib/src/main/java/com/anyun/im_lib/netty/TCPReadHandler.java
new file mode 100644
index 0000000..5f898ed
--- /dev/null
+++ b/im_lib/src/main/java/com/anyun/im_lib/netty/TCPReadHandler.java
@@ -0,0 +1,65 @@
+package com.anyun.im_lib.netty;
+
+import android.util.Log;
+
+import com.anyun.im_lib.interf.IMSClientInteface;
+
+import io.netty.channel.Channel;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.channel.ChannelInboundHandlerAdapter;
+
+/**
+ * MyApplication2
+ * 娑堟伅鎺ユ敹澶勭悊handler
+ * Created by lzw on 2019/12/4. 10:58:43
+ * 閭锛�632393724@qq.com
+ * All Rights Saved! Chongqing AnYun Tech co. LTD
+ */
+public class TCPReadHandler extends ChannelInboundHandlerAdapter {
+
+ private static final String TAG = TCPReadHandler.class.getSimpleName();
+
+ private IMSClientInteface imsClient;
+
+ public TCPReadHandler(IMSClientInteface imsClient) {
+ this.imsClient = imsClient;
+ }
+
+ @Override
+ public void channelInactive(ChannelHandlerContext ctx) throws Exception {
+ super.channelActive(ctx);
+ Log.i(TAG, "channelInactive");
+ Channel channel = ctx.channel();
+ if (channel != null){
+ channel.close();
+ ctx.close();
+ }
+ //瑙﹀彂閲嶈繛
+ imsClient.resetConnect(false);
+ }
+
+ @Override
+ public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
+ super.exceptionCaught(ctx, cause);
+ Log.i(TAG, "exceptionCaught: "+cause.getMessage());
+ Channel channel = ctx.channel();
+ if (channel != null){
+ channel.close();
+ }
+ //瑙﹀彂閲嶈繛
+ imsClient.resetConnect(false);
+ }
+
+ @Override
+ public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
+ super.channelRead(ctx, msg);
+ // TODO: 2019/12/4
+
+ }
+
+ @Override
+ public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
+ super.channelReadComplete(ctx);
+ Log.i(TAG, "channelReadComplete");
+ }
+}
diff --git a/im_lib/src/main/res/values/strings.xml b/im_lib/src/main/res/values/strings.xml
new file mode 100644
index 0000000..be8be32
--- /dev/null
+++ b/im_lib/src/main/res/values/strings.xml
@@ -0,0 +1,3 @@
+<resources>
+ <string name="app_name">im_lib</string>
+</resources>
diff --git a/im_lib/src/test/java/com/anyun/im_lib/ExampleUnitTest.java b/im_lib/src/test/java/com/anyun/im_lib/ExampleUnitTest.java
new file mode 100644
index 0000000..1b5198b
--- /dev/null
+++ b/im_lib/src/test/java/com/anyun/im_lib/ExampleUnitTest.java
@@ -0,0 +1,17 @@
+package com.anyun.im_lib;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * Example local unit test, which will execute on the development machine (host).
+ *
+ * @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
+ */
+public class ExampleUnitTest {
+ @Test
+ public void addition_isCorrect() {
+ assertEquals(4, 2 + 2);
+ }
+}
\ No newline at end of file
--
Gitblit v1.8.0