app/src/main/java/safeluck/drive/evaluation/MainActivity.java
@@ -321,6 +321,7 @@ MyLog.i(TAG,"TCP连接成功"); //TODO 判断SPUtils 是否保存有des密码;如果没有则进行注册JKMessage0100,如果有密码则进行鉴权JKMessage0101 String hexPwd = (String) SPUtils.get(this,SPUtils.DES_HEX_PWD,""); MessageProcessor.getInstance().addBeatHeart(10); if (TextUtils.isEmpty(hexPwd)){ JKMessage0100 jkRegisterMessage = new JKMessage0100(); app/src/main/java/safeluck/drive/evaluation/fragment/TcpFragment.java
@@ -291,7 +291,7 @@ @Override public void run() { JKMessage0002 jkMessage0002 = new JKMessage0002(); jkMessage0002.checksum = 0x7e; // jkMessage0002.checksum = 0x7e; MessageProcessor.getInstance().sendMessage(jkMessage0002); Log.i(TAG, "run: 5s一次"); } app/src/main/java/safeluck/drive/evaluation/im/IMSClientBootstrap.java
@@ -107,4 +107,10 @@ imsClient.sendMsg(message); } } public void addHeartbeat(int seconds){ if (isActive){ imsClient.addHeartbeatHandler(seconds); } } } app/src/main/java/safeluck/drive/evaluation/im/IMSEventListener.java
@@ -2,6 +2,9 @@ import com.anyun.im_lib.listener.OnEventListener; import safeluck.drive.evaluation.platformMessage.JKMessage0002; import safeluck.drive.evaluation.platformMessage.utils.MessageEscaper; /** * MyApplication2 * Created by lzw on 2019/12/12. 16:12:40 @@ -12,10 +15,11 @@ private String userId; private String token; private MessageEscaper messageEscaper; public IMSEventListener(String userId, String token) { this.userId = userId; this.token = token; messageEscaper = new MessageEscaper(); } @Override @@ -71,4 +75,10 @@ public byte[] getRegisterMessage() { return null; } @Override public byte[] getHearbeatMsg() { JKMessage0002 jkMessage0002 = new JKMessage0002(); return messageEscaper.escape(jkMessage0002.toBytes()); } } app/src/main/java/safeluck/drive/evaluation/im/IMessageProcessor.java
@@ -11,4 +11,6 @@ public interface IMessageProcessor { void receiveMsg(byte[] message); void sendMessage(JK2019MessageBase msg); void addBeatHeart(int seconds); } app/src/main/java/safeluck/drive/evaluation/im/MessageProcessor.java
@@ -8,6 +8,7 @@ import androidx.work.WorkManager; import com.anyun.exam.lib.MyLog; import com.anyun.im_lib.interf.IMSClientInteface; import com.anyun.im_lib.util.ByteUtil; import com.google.gson.Gson; import com.safeluck.aykj.utils.BytesUtils; @@ -105,4 +106,11 @@ } }); } @Override public void addBeatHeart(int seconds) { if (IMSClientBootstrap.getInstance().isActive()){ IMSClientBootstrap.getInstance().addHeartbeat(seconds); } } } im_lib/src/main/java/com/anyun/im_lib/HeartbeatHandler.java
@@ -1,6 +1,13 @@ package com.anyun.im_lib; import com.anyun.im_lib.netty.NettyTcpClient; import com.anyun.im_lib.util.MyLog; import com.safeluck.aykj.utils.BytesUtils; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.handler.timeout.IdleState; import io.netty.handler.timeout.IdleStateEvent; /** * MyApplication2 @@ -9,4 +16,50 @@ * All Rights Saved! Chongqing AnYun Tech co. LTD */ public class HeartbeatHandler extends ChannelInboundHandlerAdapter { private NettyTcpClient imsClient; public HeartbeatHandler(NettyTcpClient imsClient) { this.imsClient = imsClient; } private HeartbeatTask heartbeatTask; private class HeartbeatTask implements Runnable { private ChannelHandlerContext ctx; public HeartbeatTask(ChannelHandlerContext ctx) { this.ctx = ctx; } @Override public void run() { if (ctx.channel().isActive()) { byte []heartbeatMsg = imsClient.getHeartbeatMsg(); if (heartbeatMsg == null) { return; } MyLog.i("发送心跳消息,message=" + BytesUtils.bytesToHexString(heartbeatMsg) + "当前心跳间隔为:" +imsClient.getHeartbeatInterval() + "ms\n"); imsClient.sendMsg(heartbeatMsg, false); } } } @Override public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { super.userEventTriggered(ctx, evt); if (evt instanceof IdleStateEvent){ IdleState state = ((IdleStateEvent)evt).state(); MyLog.i("Netty TCP Idlestate="+state.name()); switch (state){ case READER_IDLE: // 规定时间内没收到服务端心跳包响应,进行重连操作 break; case WRITER_IDLE: // 规定时间内没向服务端发送心跳包,即发送一个心跳包 if (heartbeatTask == null) { heartbeatTask = new HeartbeatTask(ctx); } imsClient.getLoopGroup().execWorkTask(heartbeatTask); break; } } } } im_lib/src/main/java/com/anyun/im_lib/IMSConfig.java
@@ -10,7 +10,7 @@ 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_FOREGROUND = 10 * 1000; public static final int DEFAULT_HEARTBEAT_INTERVAL_BACKGROUND = 30 * 1000; /*** 应用在前台标识***/ im_lib/src/main/java/com/anyun/im_lib/interf/IMSClientInteface.java
@@ -112,4 +112,8 @@ //获取注册消息 byte[] getRegisterMessage(); byte[] getHeartbeatMsg(); void addHeartbeatHandler(int seconds); } im_lib/src/main/java/com/anyun/im_lib/listener/OnEventListener.java
@@ -59,4 +59,6 @@ int getReConnectInterval(); //注册消息 byte[] getRegisterMessage(); byte[] getHearbeatMsg(); } im_lib/src/main/java/com/anyun/im_lib/netty/NettyTcpClient.java
@@ -17,6 +17,7 @@ import java.nio.ByteBuffer; import java.util.Vector; import java.util.concurrent.TimeUnit; import java.util.function.ToDoubleBiFunction; import io.netty.bootstrap.Bootstrap; @@ -405,6 +406,34 @@ return null; } @Override public byte[] getHeartbeatMsg() { if (mOnEventListener != null){ return mOnEventListener.getHearbeatMsg(); } return null; } /** * 增加心跳, * @param heartBeatInterval 秒 */ @Override public void addHeartbeatHandler(int heartBeatInterval){ this.heartBeatInterval = heartBeatInterval*1000; _addHeartbeatHandler(); } public int getHeartbeatInterval() { return this.heartBeatInterval; } public ExecutorServiceFactory getLoopGroup() { return loopGroup; } /** * 重连任务 @@ -522,6 +551,37 @@ } private void _addHeartbeatHandler(){ MyLog.i("add HeartbeatHandler"); if (channel == null || !channel.isActive() || channel.pipeline()==null){ MyLog.i("PlatformMessage","添加心跳handler失败"); return; } try { if(channel.pipeline().get(IdleStateHandler.class.getSimpleName()) != null){ MyLog.i("PlatformMessage","之前存在的读写超时handler,先移除掉,再重新添加"); channel.pipeline().remove(IdleStateHandler.class.getSimpleName()); } // 3次心跳没响应,代表连接已断开 //设定IdleStateHandler心跳检测每四秒进行一次写检测,如果四秒内write()方法未被调用则触发一次userEventTrigger()方法,实现客户端每四秒向服务端发送一次消息; channel.pipeline().addFirst(IdleStateHandler.class.getSimpleName(), new IdleStateHandler( 0, heartBeatInterval, 0, TimeUnit.MILLISECONDS)); // 重新添加HeartbeatHandler if (channel.pipeline().get(HeartbeatHandler.class.getSimpleName()) != null) { channel.pipeline().remove(HeartbeatHandler.class.getSimpleName()); } if (channel.pipeline().get(TCPReadHandler.class.getSimpleName()) != null) { MyLog.i("之前存在的先移除掉,再重新添加HeartbeatHandler"); channel.pipeline().addBefore(TCPReadHandler.class.getSimpleName(), HeartbeatHandler.class.getSimpleName(), new HeartbeatHandler(this)); } } catch (Exception e) { e.printStackTrace(); MyLog.i("添加心跳消息管理handler失败,reason:" + e.getMessage()); } } } im_lib/src/main/java/com/safeluck/aykj/message/BinMessageBase.java
@@ -168,7 +168,7 @@ try { Object value = fieldDefine.field.get(this); String hex = fieldDefine.coder.encode(value); Log.i("PlatformMessage", "FieldName: "+fieldDefine.field.getName()+" hex:"+hex); // Log.i("PlatformMessage", "FieldName: "+fieldDefine.field.getName()+" hex:"+hex); if (hex == null) { fieldDefine.relativeLengthField.set(this, 0); } else { @@ -211,8 +211,7 @@ hex = this.getPaddingLeftString(hex,fieldDefine.getFieldLen()*2, BytesUtils.toHexString(fieldDefine.length.paddingByte())); } } // System.out.println(hex); Log.i("PlatformMessage value", "FieldName: "+fieldDefine.field.getName()+" hex:"+hex); // Log.i("PlatformMessage value", "FieldName: "+fieldDefine.field.getName()+" hex:"+hex); sb.append(hex); } catch (IllegalAccessException e) { this.buildException(e.getMessage());