HDLSDK.zipBinary files differ
HDLSDK/app/src/main/java/com/hdl/hdlsdk/MainActivity.java
@@ -71,7 +71,10 @@ super.onDestroy(); removeAllTopicsListener(); } void init(){ HDLLinkConfig.getInstance().setLocalSecret("7d04c4e3c2b7d600"); HDLLinkConfig.getInstance().setGatewayId("1473119283609321473"); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -80,9 +83,9 @@ tv = findViewById(R.id.state_tv); rv = findViewById(R.id.rv); rv.setLayoutManager(new LinearLayoutManager(this)); init(); checkIfCertified(); initDeviceInfo(); registerAllTopicsListener(); ActivityResultLauncher<String[]> launcher = registerForActivityResult(new ActivityResultContracts.RequestMultiplePermissions(), new ActivityResultCallback<Map<String, Boolean>>() { @@ -202,6 +205,7 @@ @Override public void onMessage(Object msg) { LinkResponse response = (LinkResponse) msg; handleLinkResponse(response); } }; HDLLink.getInstance().registerAllTopicsListener(allTopicsListener); @@ -250,6 +254,24 @@ HDLLink.getInstance().removeAllTopicsListener(allTopicsListener); } void initDeviceInfo() { AuthenticateRequest.AuthenticateDeviceInfoBean infoBean = new AuthenticateRequest.AuthenticateDeviceInfoBean(); infoBean.setDeviceMAC("123456789"); infoBean.setIPMAC("12345678900"); infoBean.setDeviceName("音乐播放器");//设备名字 infoBean.setDeviceModel("MCLog.431");//设备型号 infoBean.setAccessMode("WIFI"); infoBean.setIPGateway("192.168.88.1"); infoBean.setIPAddress("192.168.88.100"); infoBean.setGateway_type("music.standard"); infoBean.setHw_version("HW2.0"); infoBean.setFw_version("Fw1.0"); infoBean.setOID("010105000000FE08"); infoBean.setSid("010105000000FE08110100000000"); HDLLinkConfig.getInstance().setDeviceInfoBean(infoBean); } /** * 入网认证 */ @@ -262,7 +284,7 @@ String macStr = "AA000000000000BB";//设备唯一MAC地址 String secret = "87ae414b7a853f65";//通过spk和mac提交云端认证后分配的secret //正式服务器 // //正式服务器 // String spkStr = "screen.mirror";//产品spk // String macStr = "AA000000000000AC";//设备唯一MAC地址 // String secret = "ee62124c151b737c";//通过spk和mac提交云端认证后分配的secret @@ -290,13 +312,14 @@ infoBean.setDeviceModel("HDL");// infoBean.setAccessMode("WIFI"); infoBean.setIPGateway("192.168.88.1"); infoBean.setIPAddress(IpUtils.getIP(this)); infoBean.setIPAddress(IpUtils.getIP(this));//根据真实的IP地址填写 infoBean.setOID("010105000000FE08"); infoBean.setSid("010105000000FE08110100000000"); infoBean.setHw_version("1.0"); infoBean.setFw_version("1.0"); // infoBean.set AuthenticateRequest.VersionBean[] versionBeans = new AuthenticateRequest.VersionBean[]{new AuthenticateRequest.VersionBean("FW", versionString), new AuthenticateRequest.VersionBean("HW", "1956F")}; infoBean.setVersions(versionBeans); AuthenticateRequest request = new AuthenticateRequest(IdUtils.getUUId(), time, infoBean, authbean); HDLLink.getInstance().startAuthenticateRequest(request, new HDLLinkCallBack() { @Override HDLSDK/hdl-common/build.gradle
@@ -9,7 +9,7 @@ minSdkVersion rootProject.minSdkVersion targetSdkVersion rootProject.targetSdkVersion versionCode 2 versionName "1.0.2" versionName "1.0.5" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" consumerProguardFiles "consumer-rules.pro" HDLSDK/hdl-common/src/main/java/com/hdl/sdk/common/config/TopicConstant.java
@@ -77,4 +77,14 @@ //8.6场景删除 public static final String SCENE_DELETE = "/user/%s/custom/scene/delete"; /** * 设备连接TCP之前广播 */ public static final String BROADCAST="/user/all/custom/gateway/broadcast"; /** * 主网关回复 */ public static final String BROADCAST_REPLY="/user/all/custom/gateway/broadcast_reply"; } HDLSDK/hdl-connect/build.gradle
@@ -8,8 +8,8 @@ defaultConfig { minSdkVersion rootProject.minSdkVersion targetSdkVersion rootProject.targetSdkVersion versionCode 3 versionName "1.0.2" versionCode 2 versionName "1.0.5" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" consumerProguardFiles "consumer-rules.pro" @@ -44,4 +44,4 @@ // //加密 // implementation 'cn.hutool:hutool-all:5.6.5' // implementation 'org.bouncycastle:bcprov-jdk15on:1.60' } } HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/HDLLink.java
@@ -177,14 +177,25 @@ } /** * 通用UDP广播发送指令 * 通用UDP发送指令 * 1秒没响应就让他重新发送,重试3次 * @param topic 发送数据 * @param bodyStr body内容 * @param callBack 回调 */ public void udpSendMsg(String topic, String bodyStr, HDLLinkResponseCallBack callBack) { HDLAuthSocket.getInstance().udpSendMsg(topic, bodyStr, callBack); HDLAuthSocket.getInstance().udpSendMsg(topic, bodyStr,false, callBack); } /** * 通用广播UDP发送指令 * 1秒没响应就让他重新发送,重试3次 * @param topic 发送数据 * @param bodyStr body内容 * @param callBack 回调 */ public void udpBroadcastSendMsg(String topic, String bodyStr, HDLLinkResponseCallBack callBack) { HDLAuthSocket.getInstance().udpSendMsg(topic, bodyStr,true, callBack); } /** @@ -206,7 +217,17 @@ * @param bodyStr 回复的主题 */ public void udpSendMsg(String topic, String bodyStr) { HDLAuthSocket.getInstance().udpSendMsg(topic, bodyStr); HDLAuthSocket.getInstance().udpSendMsg(topic, bodyStr,false); } /** * 通用广播发送指令 只发一次,不监听回复,不重发 * * @param topic 发送数据 * @param bodyStr 回复的主题 */ public void udpBroadcastSendMsg(String topic, String bodyStr) { HDLAuthSocket.getInstance().udpSendMsg(topic, bodyStr,true); } /** HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/bean/LinkRequest.java
@@ -4,6 +4,7 @@ import androidx.annotation.NonNull; import com.hdl.sdk.common.utils.LogUtils; import com.hdl.sdk.connect.config.HDLLinkConfig; import com.hdl.sdk.common.utils.ByteUtils; import com.hdl.sdk.connect.utils.AesUtil; @@ -87,6 +88,7 @@ String headString = "Topic:" + getTopic() + "\r\n" + "Length:" + dataBytes.length + "\r\n" + "\r\n"; byte[] headBytes = headString.getBytes("utf-8"); byte[] sendBytes = ByteUtils.concatBytes(headBytes, dataBytes); LogUtils.i(headString + "\r\n" + data); return sendBytes; } else { HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/bean/request/AuthenticateRequest.java
@@ -34,15 +34,45 @@ this.auth = auth; } /** * 认证信息 */ public static class AuthBean implements Serializable { /** * 设备MACKey */ private String mac_key;//(mac+secret)的两次md5值 /** * 设备spk */ private String spk; /** * 请求信息 */ private RequestBean request;//设备相关信息 /** * MAC key * @return */ public String getMACKey() { return mac_key; } /** * MACkey * @param value */ public void setMACKey(String value) { this.mac_key = value; } /** * SPK * @return */ public String getSpk() { return spk; } /** * SPK * @param value */ public void setSpk(String value) { this.spk = value; } public RequestBean getRequest() { return request; } @@ -51,6 +81,13 @@ public AuthBean() { } /** * 认证信息 * @param mac_key mac key * @param spk 产品spk * @param request 请求对象 */ public AuthBean(String mac_key, String spk, RequestBean request) { this.mac_key = mac_key; this.spk = spk; @@ -71,16 +108,52 @@ this.firmware_version = firmware_version; } /** * 设备MAC * @return */ public String getMAC() { return mac; } /** * 设备MAC * @param value */ public void setMAC(String value) { this.mac = value; } /** * 厂家 * @return */ public String getSupplier() { return supplier; } /** * 厂家 * @param value */ public void setSupplier(String value) { this.supplier = value; } /** * 硬件版本 * @return */ public String getHardwareModel() { return hardware_model; } /** * 硬件版本 * @param value */ public void setHardwareModel(String value) { this.hardware_model = value; } /** * 软件版本 * @return */ public String getFirmwareVersion() { return firmware_version; } /** * 软件版本 * @param value */ public void setFirmwareVersion(String value) { this.firmware_version = value; } } @@ -97,46 +170,197 @@ private String ip_gateway; private String dns1 = "114.114.114.114"; private String dns2 = "8.8.8.8"; private VersionBean[] versions; private String gateway_type; private String hw_version; private String fw_version; public String getOID() { return oid; } /** * 设备Oid * @param value */ public void setOID(String value) { this.oid = value; } public String getDeviceMAC() { return device_mac; } /** * 设备Mac * @param value */ public void setDeviceMAC(String value) { this.device_mac = value; } /** * 设备名 * @return */ public String getDeviceName() { return device_name; } /** * 设备名 * @param value */ public void setDeviceName(String value) { this.device_name = value; } /** * 设备型号 * @return */ public String getDeviceModel() { return device_model; } /** * 设备型号 * @param value */ public void setDeviceModel(String value) { this.device_model = value; } /** * 连接类型,有线还是无线 * @return */ public String getAccessMode() { return access_mode; } /** * 连接类型,有线还是无线 * @param value */ public void setAccessMode(String value) { this.access_mode = value; } /** * 设备sid * @return */ public String getSid() { return sid; } /** * 设备sid * @param value */ public void setSid(String value) { this.sid = value; } /** * 设备IPMAC * @return */ public String getIPMAC() { return ip_mac; } /** * 设备IPMAC * @param value */ public void setIPMAC(String value) { this.ip_mac = value; } /** * 设备IP地址 * @return */ public String getIPAddress() { return ip_address; } /** * 设备IP地址 * @param value */ public void setIPAddress(String value) { this.ip_address = value; } /** * 子网掩码 * @return */ public String getNetmask() { return netmask; } /** * 子网掩码 * @param value */ public void setNetmask(String value) { this.netmask = value; } /** * 网关IP * @return */ public String getIPGateway() { return ip_gateway; } /** * 网关IP * @param value */ public void setIPGateway(String value) { this.ip_gateway = value; } /** * DNS1 * @return */ public String getDns1() { return dns1; } /** * DNS1 * @param value */ public void setDns1(String value) { this.dns1 = value; } /** * DNS2 * @return */ public String getDns2() { return dns2; } /** * DNS2 * @param value */ public void setDns2(String value) { this.dns2 = value; } public VersionBean[] getVersions() { return versions; } public void setVersions(VersionBean[] value) { this.versions = value; } public VersionBean[] getVersions() {return null; } public void setVersions(VersionBean[] value) { } /** * 网关类型 * @return */ public String getGateway_type() { return gateway_type; } /** * 网关类型 * @param gateway_type */ public void setGateway_type(String gateway_type) { this.gateway_type = gateway_type; } /** * 硬件版本 * @return */ public String getHw_version() { return hw_version; } /** *硬件版本 * @param */ public void setHw_version(String hw_version) { this.hw_version = hw_version; } /** * 固件版本 * @return */ public String getFw_version() { return fw_version; } /** * 固件版本 * @param fw_version */ public void setFw_version(String fw_version) { this.fw_version = fw_version; } } public static class VersionBean implements Serializable{ HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/bean/request/BroadcastRequest.java
New file @@ -0,0 +1,54 @@ package com.hdl.sdk.connect.bean.request; import java.io.Serializable; /** * Created by jlchen on 11/11/21. * * /user/all/custom/gateway/broadcast */ public class BroadcastRequest implements Serializable { private String id; private String time_stamp; private AuthenticateRequest.AuthenticateDeviceInfoBean objects;//当前设备基本信息 private String code;// public BroadcastRequest(String id, String time_stamp, AuthenticateRequest.AuthenticateDeviceInfoBean objects, String code) { this.id = id; this.time_stamp = time_stamp; this.objects = objects; this.code = code; } public String getId() { return id; } public void setId(String id) { this.id = id; } public String getTime_stamp() { return time_stamp; } public void setTime_stamp(String time_stamp) { this.time_stamp = time_stamp; } public AuthenticateRequest.AuthenticateDeviceInfoBean getObjects() { return objects; } public void setObjects(AuthenticateRequest.AuthenticateDeviceInfoBean objects) { this.objects = objects; } public String getCode() { return code; } public void setCode(String code) { this.code = code; } } HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/bean/request/PropertyReadRequest.java
@@ -1,9 +1,12 @@ package com.hdl.sdk.connect.bean.request; import java.io.Serializable; /** * Created by Tong on 2021/10/8. */ public class PropertyReadRequest { public class PropertyReadRequest implements Serializable { private String sid; HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/config/HDLLinkConfig.java
@@ -3,7 +3,9 @@ import android.text.TextUtils; import com.hdl.sdk.common.config.TopicConstant; import com.hdl.sdk.common.utils.LogUtils; import com.hdl.sdk.common.utils.SPUtils; import com.hdl.sdk.connect.bean.request.AuthenticateRequest; import com.hdl.sdk.connect.bean.response.GatewaySearchBean; @@ -23,6 +25,8 @@ private String ipAddress; private boolean isLocalEncrypt;//网关是否需要加密通讯 private GatewaySearchBean currentGateway;//当前网关 private AuthenticateRequest.AuthenticateDeviceInfoBean deviceInfoBean;//当前设备基本信息 /** * instance @@ -111,11 +115,15 @@ } public String getLocalSecret() { LogUtils.i("HDLLinkConfig","密钥是:"+localSecret); return localSecret; } public String getGatewayId() { return gatewayId; } public void setGatewayId(String gatewayId) { this.gatewayId=gatewayId; } public String getIpAddress() { @@ -160,6 +168,7 @@ return (!topicStr.contains(TopicConstant.GATEWAY_AUTH_BROADCAST) //网关广播入网指令 && !topicStr.contains(TopicConstant.DEIVCE_AUTH_REQUEST) //入网认证 && !topicStr.contains(TopicConstant.GATEWAY_SEARCH) //搜索网关主题 && !topicStr.equals(TopicConstant.BROADCAST) && isLocalEncrypt//启用加密标志 ); } @@ -174,4 +183,11 @@ return String.format(topicStr, gatewayId); } public AuthenticateRequest.AuthenticateDeviceInfoBean getDeviceInfoBean() { return deviceInfoBean; } public void setDeviceInfoBean(AuthenticateRequest.AuthenticateDeviceInfoBean deviceInfoBean) { this.deviceInfoBean = deviceInfoBean; } } HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/protocol/LinkMessageDecoder.java
@@ -1,8 +1,12 @@ package com.hdl.sdk.connect.protocol; import android.os.Build; import android.util.Log; import androidx.annotation.RequiresApi; import com.google.gson.internal.bind.DateTypeAdapter; import com.hdl.sdk.common.utils.LogUtils; import com.hdl.sdk.connect.config.HDLLinkConfig; import com.hdl.sdk.common.event.EventDispatcher; @@ -13,6 +17,7 @@ import com.hdl.sdk.socket.codec.ByteToMessageDecoder; import java.util.ArrayList; import java.util.Base64; import java.util.List; /** @@ -111,8 +116,9 @@ } } @RequiresApi(api = Build.VERSION_CODES.O) @Override protected LinkResponse decoder(Object msg) throws Exception { protected synchronized LinkResponse decoder(Object msg) throws Exception { if (msg instanceof byte[]) { bytes.addAll(ByteUtils.toByteList((byte[]) msg)); //如果多条命令打包在一条数据中,都需要处理完 @@ -154,18 +160,22 @@ if (HDLLinkConfig.getInstance().ifNeedEncrypt(response.getTopic())) { //需要解密 byte[] bodyBytes = AesUtil.aesDecrypt(body, HDLLinkConfig.getInstance().getLocalSecret()); // byte[] bodyBytes = AESUtils.decryptAES(body,AuthenticateConfig.getInstance().getLocalSecret()); if (bodyBytes != null) { response.setData(new String(bodyBytes, "utf-8")); // LogUtils.i("TAG", "解密 主题:"+response.getTopic()+ " body: "+response.getData()); body = bodyBytes; } else { //解密失败,返回原数据 response.setData(new String(body, "utf-8")); try { LogUtils.e("解密失败,数据内容是:\r\n" + Base64.getEncoder().encodeToString(body)); } catch (Exception e) { } } } else { response.setData(new String(body, "utf-8")); } String bodyString = new String(body, "utf-8"); //非正常数据,返回 if (!(bodyString.startsWith("{") || bodyString.startsWith("["))) { continue; } response.setData(bodyString); LogUtils.i( "LinkMessageDecoder->decoder:" + response.getTopic() + "\r\n" + response.getData()); //解析完成,topic发送一次 EventDispatcher.getInstance().post(response.getTopic(), response); HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/socket/HDLAuthSocket.java
@@ -359,9 +359,10 @@ * * @param topic 发送数据 * @param bodyStr 回复的主题 * @param broadcast 是否要广播 * @param callBack 回调 */ public void udpSendMsg(String topic, String bodyStr, HDLLinkResponseCallBack callBack) { public void udpSendMsg(String topic, String bodyStr,boolean broadcast, HDLLinkResponseCallBack callBack) { if (TextUtils.isEmpty(topic) || TextUtils.isEmpty(bodyStr)) { if (callBack != null) { callBack.onError(HDLLinkException.getErrorWithCode(HDLLinkCode.HDL_DATA_NULL_ERROR)); @@ -378,6 +379,9 @@ LinkRequest message = new LinkRequest(topic, bodyStr); String ip = HDLLinkConfig.getInstance().getIpAddress(); if(broadcast) { ip = IpUtils.getBroadcastAddress(); } HdlSocketHelper.sendUdp(getUdpBoot(), ip, UDP_PORT, message, new HdlSocketHelper.HdlSocketListener() { @Override public void onSucceed(Object msg) { @@ -399,8 +403,9 @@ * * @param topic 发送数据 * @param bodyStr 回复的主题 * @param broadcast 是否广播 */ public void udpSendMsg(String topic, String bodyStr) { public void udpSendMsg(String topic, String bodyStr,boolean broadcast) { if (TextUtils.isEmpty(topic) || TextUtils.isEmpty(bodyStr)) { LogUtils.e("udpSendMsg", "参数不能为空"); return; @@ -410,7 +415,10 @@ return; } LinkRequest message = new LinkRequest(topic, bodyStr); String ip = HDLLinkConfig.getInstance().getIpAddress();// IpUtils.getBroadcastAddress(); String ip = HDLLinkConfig.getInstance().getIpAddress(); if(broadcast) { ip = IpUtils.getBroadcastAddress(); } HdlSocketHelper.sendUdpOne(getUdpBoot(), ip, UDP_PORT, message); } HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/socket/HDLSocket.java
@@ -1,42 +1,37 @@ package com.hdl.sdk.connect.socket; import android.text.TextUtils; import android.util.Log; import com.google.gson.JsonObject; import com.google.gson.reflect.TypeToken; import com.hdl.sdk.common.config.TopicConstant; import com.hdl.sdk.common.event.EventDispatcher; import com.hdl.sdk.common.event.EventListener; import com.hdl.sdk.common.exception.HDLLinkCode; import com.hdl.sdk.common.exception.HDLLinkException; import com.hdl.sdk.common.utils.IdUtils; import com.hdl.sdk.common.utils.IpUtils; import com.hdl.sdk.common.utils.LogUtils; import com.hdl.sdk.common.utils.SPUtils; import com.hdl.sdk.common.utils.ThreadToolUtils; import com.hdl.sdk.common.utils.gson.GsonConvert; import com.hdl.sdk.connect.bean.request.BroadcastRequest; import com.hdl.sdk.connect.bean.response.BaseLocalResponse; import com.hdl.sdk.connect.bean.request.DeviceControlRequest; import com.hdl.sdk.connect.bean.request.FunctionAttributeRequest; import com.hdl.sdk.connect.bean.response.GatewaySearchBean; import com.hdl.sdk.connect.bean.LinkRequest; import com.hdl.sdk.connect.bean.LinkResponse; import com.hdl.sdk.connect.bean.request.PropertyReadRequest; import com.hdl.sdk.connect.bean.request.PropertyUpRequest; import com.hdl.sdk.connect.callback.BaseCallBack; import com.hdl.sdk.connect.callback.HDLLinkCallBack; import com.hdl.sdk.connect.callback.HDLLinkResponseCallBack; import com.hdl.sdk.connect.config.HDLLinkConfig; import com.hdl.sdk.connect.protocol.LinkMessageDecoder; import com.hdl.sdk.connect.protocol.LinkMessageEncoder; import com.hdl.sdk.socket.SocketBoot; import com.hdl.sdk.socket.SocketOptions; import com.hdl.sdk.socket.client.TcpClient; import com.hdl.sdk.socket.client.UdpClient; import com.hdl.sdk.socket.codec.MessagePipeLine; import com.hdl.sdk.socket.listener.ConnectStatusListener; import com.hdl.sdk.socket.listener.SendListener; import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.List; import java.util.concurrent.ScheduledExecutorService; @@ -63,7 +58,7 @@ statusListener = new ConnectStatusListener() { @Override public void onConnecting() { broadcastRequest(); } @Override @@ -78,6 +73,31 @@ }; } /** * 广播自身信息给主网关 */ private void broadcastRequest() { String time = String.valueOf(System.currentTimeMillis()); if (null == HDLLinkConfig.getInstance().getDeviceInfoBean()) { LogUtils.i("DeviceInfoBean为空,请设置当前对象"); return; } BroadcastRequest request = new BroadcastRequest(IdUtils.getUUId(), time, HDLLinkConfig.getInstance().getDeviceInfoBean(), "200"); HDLAuthSocket.getInstance().udpSendMsg(TopicConstant.BROADCAST, GsonConvert.getGson().toJson(request),true); HDLAuthSocket.getInstance().udpSendMsg(TopicConstant.BROADCAST, GsonConvert.getGson().toJson(request), true, new HDLLinkResponseCallBack() { @Override public void onSuccess(LinkResponse msg) { LogUtils.i("广播信息给主网关成功!"); } @Override public void onError(HDLLinkException e) { } }); HDLAuthSocket.getInstance().udpSendMsg(TopicConstant.BROADCAST, GsonConvert.getGson().toJson(request),true); } private static class SingletonInstance { private static final HDLSocket INSTANCE = new HDLSocket(); } @@ -86,17 +106,17 @@ return SingletonInstance.INSTANCE; } SocketOptions options; private SocketOptions getTcpOptions() { final SocketOptions options = new SocketOptions(); if(null!=options){ return options; } options = new SocketOptions(); final MessagePipeLine pipeLine = new MessagePipeLine(); pipeLine.add(new LinkMessageDecoder()); pipeLine.add(new LinkMessageEncoder()); options.setHandleMessage(pipeLine); options.setEnabledHeartbeat(false);//是否开启心跳包发送检测 // options.setHeartbeatTimeInterval(10*1000L); // options.setHeartbeatData("TCP"); // options.setEnabledHeartbeat(true);//是否开启心跳包发送检测 options.addConnectStatusListener(statusListener); return options; } @@ -387,11 +407,14 @@ public SocketBoot getTcp() throws RuntimeException { if (TextUtils.isEmpty(getTcpIp())) { LogUtils.e("请搜索网关"); throw new RuntimeException("请搜索网关"); } if (tcpBoot == null) { //如果没有初始化,或者网关IP更改了,就重新初始化 if (tcpBoot == null||!getTcpOptions().getIp().equals(getTcpIp())) { tcpBoot = TcpClient.init(getTcpIp(), getTcpPort(), getTcpOptions()); } return tcpBoot; } HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/socket/HdlSocketHelper.java
@@ -21,7 +21,7 @@ */ public class HdlSocketHelper { private static final Long DEF_SEND_TIMEOUT = 1000L; private static final Long DEF_SEND_TIMEOUT = 500L; private static final int DEF_MAX_RETRY = 4; private static final int DEF_SEND_ONE = 1; HDLSDK/hdl-socket/build.gradle
@@ -9,7 +9,7 @@ minSdkVersion rootProject.minSdkVersion targetSdkVersion rootProject.targetSdkVersion versionCode 2 versionName "1.0.2" versionName "1.0.5" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" consumerProguardFiles "consumer-rules.pro" HDLSDK/hdl-socket/src/main/java/com/hdl/sdk/socket/SocketBoot.java
@@ -27,25 +27,19 @@ public class SocketBoot { private ExecutorService connectThread; private ScheduledExecutorService heartbeatThread; private ExecutorService sendThread; private ExecutorService receiveThread; private ScheduledExecutorService delayThread; private final IClient client; // public IClient getClient() { // return client; // } /** * socket是否在运行 * tcp是否已经连接 */ private final AtomicBoolean isRun = new AtomicBoolean(false); private boolean connected=false; private final AtomicBoolean isOpenRetry = new AtomicBoolean(false); private final AtomicInteger resendCount = new AtomicInteger(0); public IClient getClient() { return client; } private final BlockingQueue<SocketRequest> mMessageQueue = new LinkedBlockingDeque<>(); @@ -53,88 +47,42 @@ public SocketBoot(IClient client) { this.client = client; initConnectThread(); initReceiveThread(); initSendThread(); } public ScheduledExecutorService getHeartBeat() { if (heartbeatThread == null) { heartbeatThread = ThreadToolUtils.getInstance().newScheduledThreadPool(1); } return heartbeatThread; } public void connect() { resendCount.set(0); resetConnect(true); isOpenRetry.set(true); } public synchronized void resetConnect(boolean isFirst) { final int maxRetry = client.getOptions().getMaxRetry(); if (maxRetry == 0 && resendCount.get() > 0 || (maxRetry > 0 && maxRetry + 1 < resendCount.get())) { LogUtils.d("====", "===重连次数达到最大=="); return; } if (!client.isConnect()) { if (connectThread == null) { connectThread = ThreadToolUtils.getInstance().newFixedThreadPool(1); } connectThread.execute(new Runnable() { @Override public void run() { client.onConnectStatus(ConnectStatus.CONNECTING); if (!isFirst) { try { resendCount.set(resendCount.get() + 1); Thread.sleep(300L); LogUtils.d("====", "==重连第" + resendCount + "次=="); } catch (Exception ignored) { } } try { client.connect(); isRun.set(true); if (client.isConnect()) { LogUtils.d("====", "====连接成功===="); startHeartbeat(); initSendThread(); initReceiveThread(); client.onConnectStatus(ConnectStatus.CONNECTED); resendCount.set(0); } else { throw new ConnectException(); } } catch (Exception e) { e.printStackTrace(); LogUtils.d("====", "===连接失败===" + e); //再判断一下有没有连接 if (!client.isConnect()) { isRun.set(false); client.onConnectStatus(ConnectStatus.DISCONNECT); stopHeartbeat(); disconnectError(); } } } }); /** * 连接tcp,内部维护掉,可以不用开放外部,根据这个业务我特性处理好 */ private synchronized void connect() { try { LogUtils.i("TCP连接"); client.onConnectStatus(ConnectStatus.CONNECTING); Thread.sleep(700); client.connect(); connected=true; client.onConnectStatus(ConnectStatus.CONNECTED); }catch(Exception e) { LogUtils.e("连接异常"+e.getMessage()); } } public void initSendThread() { /** * 初始化发送线程,只需要初始化一次 */ private void initSendThread() { if (sendThread == null) { sendThread = ThreadToolUtils.getInstance().newFixedThreadPool(1); } sendThread.execute(new Runnable() { @Override public void run() { while (isRun.get()) { if (client.isConnect()) { sendThread.execute(new Runnable() { @Override public void run() { while (true) { try { SocketRequest socketRequest = mMessageQueue.take(); final String sendStr = new String(socketRequest.getData(), 0, socketRequest.getData().length); LogUtils.i("发送数据:"+sendStr); // final String sendStr = new String(socketRequest.getData(), 0, socketRequest.getData().length); // LogUtils.i("发送数据:" + sendStr); final String action = socketRequest.getAction(); try { client.sendMsg(socketRequest.getData()); @@ -145,33 +93,22 @@ } } } catch (Exception e) { connected = false; LogUtils.e("发送失败:" + e.getMessage()); if (!TextUtils.isEmpty(action)) { SendListener sendListener = sendMap.get(action); if (sendListener != null) { sendListener.onError(); } } stopHeartbeat(); if (sendThread != null) { sendThread.shutdownNow(); } if (isRun.get()) { disconnectError(); } } } catch (InterruptedException ignored) { } catch (Exception e) { } } } LogUtils.d("=====", "==发送线程关闭=="); } }); }); } } /** @@ -183,151 +120,94 @@ receiveThread.execute(new Runnable() { @Override public void run() { while (isRun.get()) { if (client.isConnect()) { try { while (true) { try { if (connected) { //读取数据 client.onHandleResponse(); } catch (Exception e) { e.printStackTrace(); disconnectError(); } else { try { Thread.sleep(1000); } catch (Exception ee) { } } } catch (Exception e) { connected = false; LogUtils.e("接收数据线程异常" + e.getMessage()); } } LogUtils.i("Socket 线程退出接收数据"); } }); } } /** * 初始化重新连接线程 */ private void initConnectThread() { if (connectThread == null) { connectThread = ThreadToolUtils.getInstance().newFixedThreadPool(1); //一定时间检测一次连接情况,没有连接就执行连接,连接统一由这里维护 connectThread.execute(new Runnable() { @Override public void run() { while (true) { try { if (!connected) { reconect(); } Thread.sleep(10*1000); } catch (Exception e) { public void startHeartbeat() { if (heartbeatThread != null) { heartbeatThread.shutdownNow(); heartbeatThread = null; } if (client.getOptions() == null || client.getOptions().getHeartbeatTimeInterval() <= 0 || !client.getOptions().isEnabledHeartbeat()) { return; } getHeartBeat().scheduleWithFixedDelay(new Runnable() { @Override public void run() { if (isRun.get()) { // LogUtils.d("====", "===发送心跳包==="); if (client.getOptions() != null) { final byte[] heartBeat = client.getOptions().getHeartbeatData(); if (heartBeat != null) { sendMsg(heartBeat, false, null); } else { sendMsg(new byte[0], false, null); } } } } }, client.getOptions().getHeartbeatTimeInterval(), client.getOptions().getHeartbeatTimeInterval(), TimeUnit.MILLISECONDS); } public void stopHeartbeat() { if (heartbeatThread != null) { heartbeatThread.shutdownNow(); heartbeatThread = null; }); } } /** * 重新连接 */ private void reconect() { disconnect(); connect(); } /** * 发送无需回调 * @param msg 发送的数据 */ public void sendMsg(byte[] msg) { sendMsg(msg, true, null); sendMsg(msg, null); } public void sendMsg(byte[] msg, SendListener listener) { sendMsg(msg, true, listener); } /** * @param listener 一般情况无需监听 */ private void sendMsg(byte[] msg, boolean isRefreshRetry, SendListener listener) { if (isRefreshRetry) { //重置连接次数 resendCount.set(0); } public void sendMsg(byte[] msg, SendListener listener) { try { SocketRequest request = new SocketRequest(msg); if (listener != null && !TextUtils.isEmpty(request.getAction())) { sendMap.put(request.getAction(), listener); } mMessageQueue.put(request); } catch (InterruptedException ignored) { } catch (Exception e) { } if (!client.isConnect()) { resetConnect(false); } } /** * 发生错误,重连 * 关闭连接 */ private void disconnectError() { disconnect(); isRun.set(false); if (isOpenRetry.get()) { if (delayThread != null) { delayThread.shutdownNow(); } delayThread = ThreadToolUtils.getInstance().newScheduledThreadPool(1); delayThread.schedule(new Runnable() { @Override public void run() { if (!client.isConnect() && isOpenRetry.get()) { resetConnect(false); } } }, 3000, TimeUnit.MILLISECONDS); } } private synchronized void disconnect() { if (client.isConnect()) { try { client.disconnect(); //断开连接 client.onConnectStatus(ConnectStatus.DISCONNECT); } } } catch (Exception e) { public synchronized void close() { isOpenRetry.set(false); isRun.set(false); if (connectThread != null) { connectThread.shutdownNow(); connectThread = null; } if (heartbeatThread != null) { heartbeatThread.shutdownNow(); heartbeatThread = null; } if (sendThread != null) { sendThread.shutdownNow(); sendThread = null; } if (receiveThread != null) { receiveThread.shutdownNow(); receiveThread = null; } sendMap.clear(); client.disconnect(); mMessageQueue.clear(); } public synchronized void release() { close(); if (client != null && client.getOptions() != null) { client.getOptions().clearConnectStatusListener(); } } public boolean isConnect() { return client.isConnect(); } } HDLSDK/hdl-socket/src/main/java/com/hdl/sdk/socket/SocketOptions.java
@@ -14,17 +14,9 @@ */ public class SocketOptions { //设置读取缓存 private int readMaxBufferSize = 512; //发送心跳包 private boolean isEnabledHeartbeat = true; //心跳包 private byte[] heartbeatData; //心跳包时间间隔 private long heartbeatTimeInterval = 300L; //发送目标地址IP private String ip=""; private int port; //处理数据 private IHandleMessage handleMessage; @@ -32,18 +24,22 @@ //监听状态 private List<ConnectStatusListener> mConnectStatusListener; //最大重连次数,小于0无限次数,等于0不重连 private int maxRetry = -1; private boolean isTcpNoDelay; private boolean isReuseAddress; //保持活动状态 private boolean isKeepAlive; private boolean isOOBInline; private int sendBufferSize; private int receiveBufferSize; private int soTimeout; private boolean soLinger; public String getIp() { return ip; } public int getPort() { return port; } public void setPort(int port) { this.port = port; } public void setIp(String ip) { this.ip = ip; } public IHandleMessage getHandleMessage() { return handleMessage; @@ -51,38 +47,6 @@ public void setHandleMessage(IHandleMessage handleMessage) { this.handleMessage = handleMessage; } public boolean isEnabledHeartbeat() { return isEnabledHeartbeat; } public void setEnabledHeartbeat(boolean enabledHeartbeat) { isEnabledHeartbeat = enabledHeartbeat; } public byte[] getHeartbeatData() { return heartbeatData; } public void setHeartbeatData(byte[] heartbeatData) { this.heartbeatData = heartbeatData; } public void setHeartbeatData(String heartbeatData) { try { this.heartbeatData = heartbeatData.getBytes("utf-8"); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } } public long getHeartbeatTimeInterval() { return heartbeatTimeInterval; } public void setHeartbeatTimeInterval(long heartbeatTimeInterval) { this.heartbeatTimeInterval = heartbeatTimeInterval; } public void clearConnectStatusListener() { @@ -104,26 +68,8 @@ } } public List<ConnectStatusListener> getConnectStatusListener() { return mConnectStatusListener; } public int getMaxRetry() { return maxRetry; } public void setMaxRetry(int maxRetry) { this.maxRetry = maxRetry; } public int getReadMaxBufferSize() { return readMaxBufferSize; } public void setReadMaxBufferSize(int readMaxBufferSize) { this.readMaxBufferSize = readMaxBufferSize; } } HDLSDK/hdl-socket/src/main/java/com/hdl/sdk/socket/client/IClient.java
@@ -12,11 +12,6 @@ void disconnect(); /** * 是否已经连接 */ boolean isConnect(); SocketOptions getOptions(); HDLSDK/hdl-socket/src/main/java/com/hdl/sdk/socket/client/TcpClient.java
@@ -3,6 +3,7 @@ import com.hdl.sdk.common.utils.ByteUtils; import com.hdl.sdk.common.utils.LogUtils; import com.hdl.sdk.common.utils.ThreadToolUtils; import com.hdl.sdk.socket.SocketBoot; import com.hdl.sdk.socket.SocketOptions; @@ -15,6 +16,8 @@ import java.io.OutputStream; import java.net.InetSocketAddress; import java.net.Socket; import java.net.SocketAddress; import java.util.ArrayList; import java.util.List; @@ -31,12 +34,32 @@ private Socket mSocket; private byte[] readBuffer; private final static List<TcpClient> tcpClientList = new ArrayList(); /** * 从连接池中找出当前IP及端口的连接客户端 * @param ipAdderss 连接IP地址 * @param port 连接端口 * @return */ public static TcpClient getTcpClientByIP(String ipAdderss,int port) { for(TcpClient tcpClient:tcpClientList){ if(tcpClient.ip.equals(ipAdderss)&&tcpClient.port==port) { return tcpClient; } } return null; } private byte[] readBuffer = new byte[4*1024]; private TcpClient(String ip, int port, SocketOptions socketOptions) { this.socketOptions = socketOptions; this.ip = ip; this.port = port; socketOptions.setIp(ip); socketOptions.setPort(port); } public static SocketBoot init(String ip, int port, SocketOptions options) { @@ -46,14 +69,19 @@ @Override public void connect() throws Exception { mSocket = getSocket(); SocketOptions options = getOptions(); mSocket.connect(new InetSocketAddress(ip, port)); // SocketOptions options = getOptions(); mSocket.connect(new InetSocketAddress(ip, port), 3 * 1000); mSocket.setTcpNoDelay(true); mSocket.setReuseAddress(true); mSocket.setKeepAlive(true); readBuffer = new byte[options.getReadMaxBufferSize()]; mSocket.setSoTimeout(20 * 1000); tcpClientList.add(this); } @Override @@ -68,16 +96,6 @@ } @Override public boolean isConnect() { if (mSocket == null) { return false; } return mSocket.isConnected() && !mSocket.isClosed(); } @Override public synchronized SocketOptions getOptions() { if (socketOptions == null) { socketOptions = new SocketOptions(); @@ -89,12 +107,17 @@ public void onHandleResponse() throws Exception { final InputStream stream = getInputStream(); if (stream != null && getOptions() != null) { int len=0; while ( (len=getInputStream().read(readBuffer)) != -1) { while ( true) { int len=getInputStream().read(readBuffer); if(len<=0){ throw new Exception("接收异常,接收数据长度len="+len); } IHandleMessage handleMessage = getOptions().getHandleMessage(); if (handleMessage != null) { byte []bytes = new byte[len]; System.arraycopy(readBuffer,0,bytes,0,len); LogUtils.i("收到TCP数据",new String(bytes)); //完整的数据才回调 handleMessage.read(bytes); } @@ -106,14 +129,10 @@ public void sendMsg(byte[] msg) throws Exception { final OutputStream outputStream = getOutStream(); if (outputStream != null && getOptions() != null) { try { IHandleMessage handleMessage = getOptions().getHandleMessage(); handleMessage.write(handleMessage.write(msg)); getOutStream().write(msg); } finally { outputStream.write(msg); outputStream.flush(); } } } HDLSDK_DEMO.zipBinary files differ
HDLSDK_DEMO/app/libs/hdl-common-V1.0.2.aarBinary files differ
HDLSDK_DEMO/app/libs/hdl-common-V1.0.3.aarBinary files differ
HDLSDK_DEMO/app/libs/hdl-connect-V1.0.2.aarBinary files differ
HDLSDK_DEMO/app/libs/hdl-connect-V1.0.3.aarBinary files differ
HDLSDK_DEMO/app/libs/hdl-socket-V1.0.2.aarBinary files differ
HDLSDK_DEMO/app/libs/hdl-socket-V1.0.3.aarBinary files differ