添加心跳检测机制,
authorsnickersun <scy@incartech.cn>
Thu, 5 Mar 2020 05:28:59 +0000 (13:28 +0800)
committersnickersun <scy@incartech.cn>
Thu, 5 Mar 2020 05:28:59 +0000 (13:28 +0800)
1、发送心跳包5秒检测一次服务器响应,
2、检测到响应停止检测,没检测则重发一次心跳包,继续检测,
3、6次没检测到则停止检测。
添加服务器socket连接重试机制,
1、每次心跳都检测服务器是否正常(包括socket连接和心跳包响应)任何一个有问题,都重新连接服务器
2、每20秒重新连接一次,尝试6次,如果成功则提示在检测,如果6次还是失败,则停止检测,直到下一次心跳包的检测。

编译最新版本:V369

app/release/ICSer_V367_2003022337_release.apk [deleted file]
app/release/ICSer_V369_2003051322_release.apk [new file with mode: 0644]
app/src/main/java/com/enqualcomm/support/CoreService.java
app/src/main/java/com/enqualcomm/support/MainActivity.java
app/src/main/java/com/enqualcomm/support/service/Deliver.java
app/src/main/java/com/enqualcomm/support/service/KeepAlive.java
app/src/main/java/com/enqualcomm/support/utils/DeviceInfoUtil.java
app/version_code.properties

diff --git a/app/release/ICSer_V367_2003022337_release.apk b/app/release/ICSer_V367_2003022337_release.apk
deleted file mode 100644 (file)
index 1e5ef02..0000000
Binary files a/app/release/ICSer_V367_2003022337_release.apk and /dev/null differ
diff --git a/app/release/ICSer_V369_2003051322_release.apk b/app/release/ICSer_V369_2003051322_release.apk
new file mode 100644 (file)
index 0000000..c9270f0
Binary files /dev/null and b/app/release/ICSer_V369_2003051322_release.apk differ
index abf3ce8..4283fcb 100644 (file)
@@ -675,7 +675,14 @@ public class CoreService extends Service {
                         return Service.START_STICKY;\r
                     }else if (HEART_ALARM.equals(paramIntent.getAction())) {\r
                         if (this.mKeepAlive != null) {\r
-                            this.mKeepAlive.onHeartAlarm(this.connection, this.runtime);\r
+\r
+                            if (connection.isServerConnected()&& runtime.isServerProtocolConnected()) {\r
+                                this.mKeepAlive.onHeartAlarm(this.connection, this.runtime);\r
+                            }else{\r
+                                ICLogger.i("check 发送心跳包时,如果发现服务器没有响应,或者socket连接,则重新尝试连接服务器!");\r
+                                connection.disconnectServer();\r
+                                this.startConnectionRetryTimer();\r
+                            }\r
                             setHeartAlarm();\r
                             if (Config.LOG_TOFILE) FileOutputUtil.fileOutput(runtime.getCacheDir(), "alarmCycle", "HEART_ALARM alarmCycle  " );\r
                             return Service.START_STICKY;\r
@@ -832,6 +839,9 @@ public class CoreService extends Service {
 \r
     private Timer mTimer_retry_connect=null;\r
 \r
+    private static int retry_connect_count=0;  //当前重试次数\r
+    private static int retry_connect_max_times=6; //最大重试次数 6次 , 即只重试2分钟,下一次重试将在下一个心跳包时进行。\r
+    private static int retry_cocnnect_cycle=20; //重试间隔20秒\r
     private void log(String msg) {\r
         ICLogger.log(TAG,msg);\r
     }\r
@@ -850,7 +860,7 @@ public class CoreService extends Service {
             //如果开始进行连接重\r
                 // {\r
             // 试,证明网络断开的,那么KeepAlive也需要重连(心跳包)\r
-\r
+            retry_connect_count=0;\r
             KeepAlive.isConnected = false;\r
             if (mTimer_retry_connect != null) {\r
                 mTimer_retry_connect.schedule(new TimerTask() {\r
@@ -867,18 +877,31 @@ public class CoreService extends Service {
     public void ReConnectToServer(){\r
 \r
         if (SimSignalUtil.checkNet(runtime.getContextProxy().context) ) {\r
-            String ip=runtime.getDnsUtil().getServerIP_ByDNSCache(runtime.getHost());\r
-            if (null != ip && !ip.equals(runtime.getSrvIP())) {\r
-                runtime.setSrvIP(ip);\r
-            }\r
-            this.connection.connect(this.runtime.getSrvIP(), this.runtime.getPort());\r
-\r
-            //里面如果连接成功 connectionOpen 会先发送 AP00 登录包 和发送AP03 心跳包 ,都成功则停止重试\r
-            if (connection.isServerConnected() && KeepAlive.isConnected) {\r
+            //里面如果连接成功 connectionOpen 会先发送 AP00 登录包 和发送AP03 心跳包 ,\r
+            // isServerConnected 成功则停止重试, KeepAlive会检测AP03心跳包的成功与否。此处只管socket连接是否成功\r
+            if (connection.isServerConnected()) {\r
+                ICLogger.i("retry  如果连接成功则停止重试!");\r
                 stopConnectionRetryTimer();\r
+            }else {\r
+                if (retry_connect_count >= retry_connect_max_times) {\r
+\r
+                    ICLogger.i("retry " + retry_connect_count + " 次 >= " + retry_connect_max_times + " ,停止重试!等待下一次心跳再重试!");\r
+                    stopConnectionRetryTimer();\r
+\r
+                } else {\r
+                    retry_connect_count++;\r
+                    String ip = runtime.getDnsUtil().getServerIP_ByDNSCache(runtime.getHost());\r
+                    if (null != ip && !ip.equals(runtime.getSrvIP())) {\r
+                        runtime.setSrvIP(ip);\r
+                    }\r
+                    ICLogger.i("retry 第" + retry_connect_count + " 次 , 连接服务器!");\r
+                    this.connection.connect(this.runtime.getSrvIP(), this.runtime.getPort());\r
+\r
+                }\r
             }\r
         }else{\r
             //没有网络就不用重新尝试连接网络了。网络连接后再重新尝试联网\r
+            ICLogger.i("retry 没有网络就不用重新尝试连接网络了。网络连接后再重新尝试联网!");\r
             stopConnectionRetryTimer();\r
         }\r
     }\r
index a6537e8..eefe225 100644 (file)
@@ -15,6 +15,7 @@ import android.widget.TextView;
 import android.widget.ToggleButton;
 
 import com.enqualcomm.support.R;
+import com.enqualcomm.support.adapter.protocolAPIHelper;
 import com.enqualcomm.support.utils.DeviceInfoUtil;
 import com.enqualcomm.support.utils.SimSignalUtil;
 import com.ic.jni.ICJniUtils;
@@ -23,6 +24,10 @@ import com.enqualcomm.support.utils.ICLogger;
 
 import java.util.Timer;
 import java.util.TimerTask;
+import java.util.concurrent.TimeUnit;
+
+import rx.Observable;
+import rx.functions.Action1;
 
 public class MainActivity extends AppCompatActivity {
     TextView tv;
@@ -133,7 +138,13 @@ public class MainActivity extends AppCompatActivity {
                 case R.id.btnConnect:
                     //进行连接Socket:这里使用的是,在本地上开启了一个服务器。
                     stopService(new Intent(MainActivity.this,CoreService.class));// protocol service
-                    startService(new Intent(MainActivity.this,CoreService.class));// protocol service
+
+                    //delay 5秒再重启
+                    Observable.timer(5000L, TimeUnit.MILLISECONDS).subscribe(new Action1<Long>() {
+                        public void call(Long param1Long) {
+                            startService(new Intent(MainActivity.this,CoreService.class));// protocol service
+                        }
+                    });
 
 
                     break;
index b979ca9..c7f0db5 100644 (file)
@@ -165,7 +165,7 @@ public class Deliver extends AbstractConnectionService {
       //如果信号不好,把msg放回去\r
       ret=false;\r
     } else {\r
-      if (connection.isServerConnected() == false || !KeepAlive.isConnected) {\r
+      if (connection.isServerConnected() == false || !mRuntime.isServerProtocolConnected()) {\r
         ret=false;\r
       }\r
     }\r
@@ -276,7 +276,7 @@ public static void sendLocationMSG( String Msg){
       ServiceUtil.offerQueue(protocolAPIHelper.genStringMessage("queue",Msg));\r
       triggerSendThread();\r
     }else {\r
-      if (connection.isServerConnected() && KeepAlive.isConnected) {\r
+      if (checkNetwork()) {\r
         ICLogger.i(" first send " + Msg);\r
         connection.send(protocolAPIHelper.genStringMessage("queue",Msg));\r
       } else {\r
@@ -300,7 +300,7 @@ public static void sendLocationMSG( String Msg){
   }\r
 \r
   public static PowerManager.WakeLock WakeLockForGetWifiList(Runtime paramRuntime) {\r
-    PowerManager.WakeLock wakeLock = ((PowerManager)(paramRuntime.getContextProxy()).context.getSystemService(Context.POWER_SERVICE)).newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, RECEIVE_WAKE_LOCKTAG);\r
+    PowerManager.WakeLock wakeLock = ((PowerManager)(paramRuntime.getContextProxy()).context.getSystemService(Context.POWER_SERVICE)).newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, Deliver.class.getSimpleName());\r
     wakeLock.acquire(120000L);\r
     return wakeLock;\r
   }\r
@@ -321,7 +321,7 @@ public static void sendLocationMSG( String Msg){
   }\r
   \r
   public PowerManager.WakeLock getWakeLock() {\r
-    PowerManager.WakeLock wakeLock = ((PowerManager)(this.mRuntime.getContextProxy()).context.getSystemService(Context.POWER_SERVICE)).newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, RECEIVE_WAKE_LOCKTAG);\r
+    PowerManager.WakeLock wakeLock = ((PowerManager)(this.mRuntime.getContextProxy()).context.getSystemService(Context.POWER_SERVICE)).newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, Deliver.class.getSimpleName());\r
     wakeLock.acquire(40000L);\r
     return wakeLock;\r
   }\r
index a22aac2..8df8006 100644 (file)
@@ -21,7 +21,10 @@ import com.enqualcomm.support.utils.NettyConnection;
 import com.enqualcomm.support.utils.NetworkObservable;\r
 import com.enqualcomm.support.utils.ServiceUtil;\r
 import com.enqualcomm.support.bean.Runtime;\r
+import com.enqualcomm.support.utils.SimSignalUtil;\r
 \r
+import java.util.Timer;\r
+import java.util.TimerTask;\r
 import java.util.concurrent.TimeUnit;\r
 \r
 import rx.Observable;\r
@@ -76,11 +79,84 @@ public class KeepAlive extends AbstractConnectionService {
   private int totalAdjustTimes;\r
   \r
   private int whichTimeAdjust;\r
-  \r
-  static  {\r
-  \r
+\r
+//服务器收到AP03 会返回BP03,如果PB03 规定时间没收到,则认为发送心跳失败,需要重发,\r
+  private boolean is_heartBeat_send_success=false;\r
+  //如果重试5次还没有连接上,则需要重新断开连接重新连接服务器。\r
+  private int hearBeatResendCount=0;\r
+  private int MaxHeartbeatResendTime=6;\r
+  //每次retry发送心跳的间隔为20秒\r
+  private int heartBeatRetryTimeout=5;\r
+  //监测 心跳服务器响应的timer\r
+  private Timer mTimer_check_server_response=null;\r
+\r
+\r
+  public void startResponseCheckTimer(){\r
+    //联网再重试连接服务器\r
+    if (SimSignalUtil.checkNet(mRuntime.getContextProxy().context) ) {\r
+      stopResponseCheckTimer();\r
+      if (mTimer_check_server_response == null) {\r
+        mTimer_check_server_response = new Timer();\r
+      }\r
+\r
+      //开始检测重新计数\r
+      hearBeatResendCount=0;\r
+      //如果开始进行连接重\r
+      // {\r
+      // 试,证明网络断开的,那么KeepAlive也需要重连(心跳包)\r
+\r
+      if (mTimer_check_server_response != null) {\r
+        mTimer_check_server_response.schedule(new TimerTask() {\r
+          @Override\r
+          public void run() {\r
+            checkSrvResponse();\r
+          }\r
+        }, 0, heartBeatRetryTimeout*1000); //每5秒重试一次\r
+      }\r
+    }\r
   }\r
 \r
+\r
+  public void checkSrvResponse(){\r
+\r
+    if (SimSignalUtil.checkNet(mRuntime.getContextProxy().context) ) {\r
+\r
+\r
+      //如果收到服务器响应BP03,则停止重试,否则 继续发送AP03 心跳包,且继续检查响应\r
+      if (this.is_heartBeat_send_success ) {\r
+        ICLogger.i("checkSrvResponse 成功,停止检测!");\r
+        stopResponseCheckTimer();\r
+      }else{\r
+        //如果重试次数大于等于 最大重试次数,则停止重试,等下次心跳时间再行尝试。\r
+        if (hearBeatResendCount >= MaxHeartbeatResendTime){\r
+          ICLogger.i("checkSrvResponse "+hearBeatResendCount+"次 >= "+MaxHeartbeatResendTime+" , 则停止重试,等下次心跳时间再行尝试!");\r
+          stopResponseCheckTimer();\r
+        }else {\r
+          //重新发送AP03心跳包\r
+          ICLogger.i("checkSrvResponse 失败,第" + hearBeatResendCount + "次,重新发送AP03心跳包!");\r
+          //心跳开始发送的时候,先重置response检测标志\r
+          is_heartBeat_send_success = false;\r
+          hearBeatResendCount++;\r
+          connection.send(protocolAPIHelper.genStringMessage("heart", protocolAPIHelper.AP03(mRuntime)));\r
+        }\r
+      }\r
+\r
+    }else{\r
+      //没有网络就不用重新尝试连接网络了。网络连接后再重新尝试联网\r
+      ICLogger.i("checkSrvResponse stop , 没有网络就不用重新尝试检测服务器响应和重新发送心跳包了!");\r
+\r
+      stopResponseCheckTimer();\r
+    }\r
+  }\r
+\r
+  public void stopResponseCheckTimer(){\r
+    if (mTimer_check_server_response !=null){\r
+      mTimer_check_server_response.cancel();\r
+      mTimer_check_server_response = null;\r
+    }\r
+  }\r
+\r
+\r
   \r
   public void onAlarmClock(Connection paramConnection, Runtime paramRuntime) {\r
 \r
@@ -119,16 +195,18 @@ public class KeepAlive extends AbstractConnectionService {
             stringBuilder.append(this.first);\r
             ICLogger.i(stringBuilder.toString());\r
             if (param1Integer.intValue() > 0) {\r
+              //返回值大于0 证明是网络连接成功,开始重连服务器\r
               if (this.first) {\r
                 this.first = false;\r
                 return;\r
               }\r
+              ICLogger.i("数据网络连接成功,重新连接网络。");\r
               CoreService.getInstance().ReConnectToServer();\r
             } \r
           }\r
         });\r
     IntentFilter intentFilter = new IntentFilter();\r
-    intentFilter.addAction("android.intent.action.ACTION_SHUTDOWN_MOREINFO");\r
+    intentFilter.addAction("android.intent.action.ACTION_SHUTDOWN");\r
     this.mShutDownReceiver = new ShutDownReceiver();\r
     this.mContext.registerReceiver(this.mShutDownReceiver, intentFilter);\r
   }\r
@@ -137,6 +215,7 @@ public class KeepAlive extends AbstractConnectionService {
 \r
 //    if (isConnected)\r
     //如果KeepAlive被关闭说明网络有问题,因此开启重试联网机制\r
+    stopResponseCheckTimer();\r
     CoreService.getInstance().startConnectionRetryTimer();\r
     connectionError = true;\r
     isConnected = false;\r
@@ -151,7 +230,7 @@ public class KeepAlive extends AbstractConnectionService {
 //    CoreService.needLocateInAfterHeartBeat=true;\r
     return false;\r
   }\r
-  \r
+\r
   public boolean onConnectionOpen(Connection paramConnection, Runtime paramRuntime) {\r
 \r
     StringBuilder stringBuilder = new StringBuilder();\r
@@ -164,7 +243,6 @@ public class KeepAlive extends AbstractConnectionService {
 //    if (!connectionError) {\r
     connectionError = false;\r
 \r
-\r
     //发送登录包\r
     Observable.timer(500L, TimeUnit.MILLISECONDS).subscribe(new Action1<Long>() {\r
       public void call(Long param1Long) {\r
@@ -172,14 +250,20 @@ public class KeepAlive extends AbstractConnectionService {
 \r
       }\r
     });\r
-     //发送心跳包\r
+    //心跳开始发送的时候,先重置response检测标志\r
+    is_heartBeat_send_success=false;\r
+    //发送心跳包\r
     Observable.timer(5500L, TimeUnit.MILLISECONDS).subscribe(new Action1<Long>() {\r
       public void call(Long param1Long) {\r
+        //这时重新连接服务器才进行的连接,理论上close已经设置false,此次可以认为协议定然断开,所以设置为false作为双重保险。\r
+        mRuntime.setServerProtocolConnected(false);\r
         connection.send(protocolAPIHelper.genStringMessage("heart",protocolAPIHelper.AP03(paramRuntime)));\r
+        //发送完心跳后,开始检查服务器响应\r
+         startResponseCheckTimer();\r
       }\r
     });\r
 \r
-    isConnected = true;\r
+     isConnected = true;\r
     this.firstReConnected = true;\r
     this.idleTimeMillis = SystemClock.elapsedRealtime();\r
 \r
@@ -195,12 +279,17 @@ public class KeepAlive extends AbstractConnectionService {
   \r
   public void onHeartAlarm(NettyConnection paramNettyConnection, Runtime paramRuntime) {\r
     ICLogger.i("onHeartAlarm");\r
-//    UpdateHeartBeatTimeout();\r
-//    if (this.reCycleTimes == 0 && this.currentReConnectInterval != 11){\r
-//    paramNettyConnection.send(protocolAPIHelper.genStringMessage("AP00",protocolAPIHelper.AP00(paramRuntime)));\r
-      paramNettyConnection.send(protocolAPIHelper.genStringMessage("heart",protocolAPIHelper.AP03(paramRuntime)));\r
 \r
-    //    }\r
+    stopResponseCheckTimer();\r
+    //心跳开始发送的时候,先重置response检测标志\r
+    is_heartBeat_send_success=false;\r
+\r
+    //这个是正常心跳包,暂时不能认为服务器连接时失败的,所以正常发送检测。\r
+    //发送心跳包\r
+    connection.send(protocolAPIHelper.genStringMessage("heart",protocolAPIHelper.AP03(paramRuntime)));\r
+        //发送完心跳后,开始检查服务器响应\r
+    startResponseCheckTimer();\r
+\r
 \r
   }\r
 \r
@@ -212,11 +301,13 @@ public class KeepAlive extends AbstractConnectionService {
     }else if ("BP03".equals(paramStringMessage.cmd())){\r
 //      收到心跳才认为是已经连接了服务器\r
       paramRuntime.setServerProtocolConnected(true);\r
+//      isConnected = true;\r
+      is_heartBeat_send_success=true;\r
+//广播服务器连接成功的消息\r
       paramRuntime.getContextProxy().sendBroadcast(isConnected);\r
       LauncherCtrl.getInstance(this.mContext).setStatusBarIcon("server_connected", STATUS_BAR_STATE_SERVER_CONNECTED_ON);\r
 //      Deliver.triggerSendThread(); //链接上就尝试清除 buffer中的数据\r
       CoreService.getInstance().stopConnectionRetryTimer();\r
-\r
       if (CoreService.needLocateInAfterHeartBeat==true){\r
         //第一次启动或者系统Close后重连的时候,重置LocationCycle\r
         CoreService.needLocateInAfterHeartBeat=false;\r
@@ -235,10 +326,14 @@ public class KeepAlive extends AbstractConnectionService {
   class ShutDownReceiver extends BroadcastReceiver {\r
     public void onReceive(Context param1Context, Intent param1Intent) {\r
       boolean bool = param1Intent.getBooleanExtra("reboot", false);\r
-      if (KeepAlive.this.mRuntime.getBatteryLow() && !KeepAlive.this.mRuntime.getBatterychanging() && !bool && !KeepAlive.this.mRuntime.isShutdown()){\r
+      ICLogger.i("Shutdown Received! reboot="+bool);\r
+      if (KeepAlive.this.mRuntime.getBatteryLow() && !KeepAlive.this.mRuntime.getBatterychanging() && !bool && !KeepAlive.this.mRuntime.isShutdown()/*不是服务器让关闭的*/){\r
 \r
           KeepAlive.this.mRuntime.setAlarmType(false,KeepAlive.this.mRuntime.getBatteryLow(),false,false);\r
           KeepAlive.this.connection.send(protocolAPIHelper.genStringMessage("AP10",protocolAPIHelper.AP10(KeepAlive.this.mRuntime)));\r
+\r
+          ICLogger.i("Shutdown Received! send AP10 !");\r
+\r
       }\r
 \r
     }\r
index 70dedfd..87dc469 100644 (file)
@@ -10,6 +10,7 @@ import android.os.Build;
 import android.provider.Settings;\r
 import android.telephony.TelephonyManager;\r
 \r
+import com.enqualcomm.support.CoreService;\r
 import com.enqualcomm.support.bean.StepCount;\r
 import com.enqualcomm.support.bean.Runtime;\r
 import com.enqualcomm.support.service.KeepAlive;\r
@@ -194,7 +195,7 @@ public class DeviceInfoUtil {
             .append(SimSignalUtil.hasSimCard(runtime.getContextProxy().context)?" SIM ":" NoSIM ")\r
             .append(sim.getNetworkType()==SimSignalUtil.IS_2G?"2G":(sim.getNetworkType()==SimSignalUtil.IS_3G)?"3G":(sim.getNetworkType()==SimSignalUtil.IS_4G?"4G":"unknown"))\r
             .append(" [").append(runtime.getSignalStrength()).append(",Mini:").append(SimSignalUtil.getMinSignalStrength(sim.getNetworkType())).append("]")\r
-            .append("\n KeepAlive ").append(KeepAlive.isConnected).append(" , HBcycle ").append(runtime.getHeartBeatCycle())\r
+            .append("\n SocketConnection ").append(KeepAlive.isConnected).append(" , HBcycle ").append(runtime.getHeartBeatCycle())\r
             .append("\n ServerConnected is ").append(runtime.isServerProtocolConnected())\r
             .append(" \n Bat ").append(runtime.getBattery()).append(",").append(runtime.getBatteryVotage())\r
             .append(" StepCount ").append(runtime.getTotalStepCount())\r
index e96a412..d458487 100644 (file)
@@ -1,2 +1,2 @@
-#Mon Mar 02 23:37:05 CST 2020\r
-VERSION_CODE=367\r
+#Thu Mar 05 13:22:46 CST 2020\r
+VERSION_CODE=369\r