Commit 0f266e4a by pye52

修复SCWebSocketClient的重连异常

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