Commit 0f266e4a by pye52

修复SCWebSocketClient的重连异常

1、不再提供SoftClose方法(没有意义)
2、不再重写close方法(WebSocket内部会调用,导致forceStop为true)
3、调整重连逻辑,由于重连失败也会回调onError方法,因此不需要同步监听重连是否成功
4、网络切换增加间隔判断,避免网络频繁切换
parent 9f13a128
package com.bgycc.smartcanteen.socket; package com.bgycc.smartcanteen.socket;
import android.annotation.SuppressLint;
import android.net.ConnectivityManager;
import android.net.Network;
import android.text.TextUtils; import android.text.TextUtils;
import androidx.annotation.NonNull;
import androidx.lifecycle.LiveData; import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData; import androidx.lifecycle.MutableLiveData;
...@@ -9,8 +13,7 @@ import com.bgycc.smartcanteen.entity.CheckDevice; ...@@ -9,8 +13,7 @@ import com.bgycc.smartcanteen.entity.CheckDevice;
import com.bgycc.smartcanteen.entity.Heartbeat; import com.bgycc.smartcanteen.entity.Heartbeat;
import com.bgycc.smartcanteen.executor.SCTaskExecutor; import com.bgycc.smartcanteen.executor.SCTaskExecutor;
import com.bgycc.smartcanteen.state.ConnectState; import com.bgycc.smartcanteen.state.ConnectState;
import com.bgycc.smartcanteen.utils.NetworkHelper; import com.bgycc.smartcanteen.utils.NetworkUtils;
import com.bgycc.smartcanteen.utils.WifiHelper;
import com.blankj.utilcode.util.LogUtils; import com.blankj.utilcode.util.LogUtils;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
...@@ -36,7 +39,9 @@ import static com.bgycc.smartcanteen.utils.SmartCanteenUtils.TAG; ...@@ -36,7 +39,9 @@ import static com.bgycc.smartcanteen.utils.SmartCanteenUtils.TAG;
*/ */
public class SCWebSocketClient extends WebSocketClient { public class SCWebSocketClient extends WebSocketClient {
private static final long HEARTBEAT_INTERVAL = 3 * 60 * 1000; private static final long HEARTBEAT_INTERVAL = 3 * 60 * 1000;
private static final long RECONNECT_DELAY = 5000; private static final long RECONNECT_DELAY = 5 * 1000;
private static final long SWITCH_INTERVAL = 15 * 1000;
private static final String RESPONSE_ACTION = "action"; private static final String RESPONSE_ACTION = "action";
private static final String RESPONSE_DATA = "data"; private static final String RESPONSE_DATA = "data";
private static final String CHECK_DEVICE = "CHECK_DEVICE"; private static final String CHECK_DEVICE = "CHECK_DEVICE";
...@@ -47,6 +52,8 @@ public class SCWebSocketClient extends WebSocketClient { ...@@ -47,6 +52,8 @@ public class SCWebSocketClient extends WebSocketClient {
private ScheduledFuture<?> heartbeatFuture; private ScheduledFuture<?> heartbeatFuture;
private ScheduledFuture<?> reconnectFuture; private ScheduledFuture<?> reconnectFuture;
private boolean forceStop = false; private boolean forceStop = false;
// 记录上一次网络切换的时间,避免网络切换过于频繁
private long lastSwitchTime = -1;
private List<SCWebSocketListener> listener = new ArrayList<>(); private List<SCWebSocketListener> listener = new ArrayList<>();
private MutableLiveData<ConnectState> connectState = new MutableLiveData<>(); private MutableLiveData<ConnectState> connectState = new MutableLiveData<>();
...@@ -64,6 +71,8 @@ public class SCWebSocketClient extends WebSocketClient { ...@@ -64,6 +71,8 @@ public class SCWebSocketClient extends WebSocketClient {
} }
public void tryConnect() { public void tryConnect() {
LogUtils.d(TAG, "尝试通过WebSocket链接服务器");
forceStop = false;
SCTaskExecutor.getInstance().executeOnDiskIO(() -> { SCTaskExecutor.getInstance().executeOnDiskIO(() -> {
try { try {
boolean connectResult = connectBlocking(10, TimeUnit.SECONDS); boolean connectResult = connectBlocking(10, TimeUnit.SECONDS);
...@@ -113,17 +122,16 @@ public class SCWebSocketClient extends WebSocketClient { ...@@ -113,17 +122,16 @@ public class SCWebSocketClient extends WebSocketClient {
LogUtils.d(TAG, "发送数据包: " + Arrays.toString(data)); LogUtils.d(TAG, "发送数据包: " + Arrays.toString(data));
} }
@Override public void realClose() {
public void close() { listener.clear();
stopHeartbeat();
if (reconnectFuture != null) { if (reconnectFuture != null) {
reconnectFuture.cancel(true); reconnectFuture.cancel(true);
reconnectFuture = null; reconnectFuture = null;
} }
listener.clear();
forceStop = true; forceStop = true;
LogUtils.d(TAG, "SCWebSocket close"); LogUtils.d(TAG, "SCWebSocket close");
super.close(); super.close();
stopHeartbeat();
} }
@Override @Override
...@@ -185,30 +193,34 @@ public class SCWebSocketClient extends WebSocketClient { ...@@ -185,30 +193,34 @@ public class SCWebSocketClient extends WebSocketClient {
if (forceStop) return; if (forceStop) return;
switchNetwork(); switchNetwork();
// socket链接断开后就无需继续定时发送心跳了
stopHeartbeat(); stopHeartbeat();
tryReconnect(); tryReconnect();
} }
@Override @Override
public void onError(Exception e) { public void onError(Exception e) {
LogUtils.i(TAG, "链接异常: " + e.getMessage(), e); LogUtils.e(TAG, "链接异常: " + e.getMessage(), e);
connectState.postValue(new ConnectState(ConnectState.OFFLINE)); connectState.postValue(new ConnectState(ConnectState.OFFLINE));
switchNetwork();
for (SCWebSocketListener l : listener) { for (SCWebSocketListener l : listener) {
l.onError(e); l.onError(e);
} }
if (forceStop) return;
switchNetwork();
stopHeartbeat(); stopHeartbeat();
tryReconnect(); tryReconnect();
} }
private void switchNetwork() { @SuppressLint("ObsoleteSdkInt")
// 保证Wifi状态启动 private synchronized void switchNetwork() {
if (!WifiHelper.isWifiEnabled()) { long currentTime = System.currentTimeMillis();
WifiHelper.setEnable(true); if ((currentTime - lastSwitchTime) < SWITCH_INTERVAL) {
return;
} }
NetworkHelper.switchNetwork(); lastSwitchTime = currentTime;
connectState.postValue(new ConnectState(ConnectState.CHANGE_NETWORK)); connectState.postValue(new ConnectState(ConnectState.CHANGE_NETWORK));
NetworkUtils.switchNetworkApi21(callback);
} }
private void tryReconnect() { private void tryReconnect() {
...@@ -228,26 +240,20 @@ public class SCWebSocketClient extends WebSocketClient { ...@@ -228,26 +240,20 @@ public class SCWebSocketClient extends WebSocketClient {
} }
}; };
private Runnable reconnectRunnable = new Runnable() { private Runnable reconnectRunnable = () -> {
LogUtils.d(TAG, "开始尝试重连");
connectState.postValue(new ConnectState(ConnectState.RECONNECTING));
for (SCWebSocketListener l : listener) {
l.onReconnect();
}
reconnect();
};
private ConnectivityManager.NetworkCallback callback = new ConnectivityManager.NetworkCallback() {
@Override @Override
public void run() { public void onAvailable(@NonNull Network network) {
LogUtils.d(TAG, "开始尝试重连"); NetworkUtils.unregisterNetworkCallback(this);
connectState.postValue(new ConnectState(ConnectState.RECONNECTING)); NetworkUtils.bindProcessToNetwork(network);
for (SCWebSocketListener l : listener) {
l.onReconnect();
}
try {
boolean result = reconnectBlocking();
if (result) {
LogUtils.d(TAG, "重连成功");
} else {
reconnectFuture = SCTaskExecutor.getInstance().schedule(reconnectRunnable, RECONNECT_DELAY, TimeUnit.MILLISECONDS);
LogUtils.d(TAG, "重连失败,一段时间后再次尝试");
}
} catch (InterruptedException e) {
reconnectFuture = SCTaskExecutor.getInstance().schedule(reconnectRunnable, RECONNECT_DELAY, TimeUnit.MILLISECONDS);
LogUtils.w(TAG, "重连过程异常,一段时间后再次尝试: " + e.getMessage(), e);
}
} }
}; };
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment