修复android sdk 一处bug

频发切换wifi和移动网络,概率出现无法重连的问题
This commit is contained in:
远方夕阳 2022-09-29 18:23:12 +08:00
parent 35ab7cc72c
commit e89a3918c5
8 changed files with 104 additions and 74 deletions

View File

@ -6,7 +6,7 @@
<groupId>com.farsunset</groupId>
<artifactId>cim-android-sdk</artifactId>
<version>4.2.7</version>
<version>4.2.8</version>
<packaging>jar</packaging>
<name>${project.groupId}:${project.artifactId}</name>

View File

@ -46,6 +46,10 @@ class CIMCacheManager {
public static final String KEY_NTC_CHANNEL_NAME = "KEY_NTC_CHANNEL_NAME";
public static final String KEY_NTC_CHANNEL_MESSAGE = "KEY_NTC_CHANNEL_MESSAGE";
public static final String KEY_NTC_CHANNEL_ICON = "KEY_NTC_CHANNEL_ICON";
public static final String CONTENT_URI = "content://%s.cim.provider";

View File

@ -26,6 +26,7 @@ import android.content.Intent;
import android.os.Handler;
import com.farsunset.cim.sdk.android.coder.ClientMessageDecoder;
import com.farsunset.cim.sdk.android.coder.ClientMessageEncoder;
import com.farsunset.cim.sdk.android.constant.BundleKey;
import com.farsunset.cim.sdk.android.constant.CIMConstant;
import com.farsunset.cim.sdk.android.constant.IntentAction;
import com.farsunset.cim.sdk.android.logger.CIMLogger;
@ -35,18 +36,18 @@ import java.io.IOException;
import java.net.ConnectException;
import java.net.InetSocketAddress;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicBoolean;
/*
* 连接服务端管理cim核心处理类管理连接以及消息处理
*/
class CIMConnectorManager {
private static CIMConnectorManager manager;
class CIMConnectManager {
private static final int READ_BUFFER_SIZE = 2048;
@ -76,20 +77,12 @@ class CIMConnectorManager {
private final Random random = new Random();
private CIMConnectorManager(Context context) {
private final AtomicBoolean connecting = new AtomicBoolean(false);
public CIMConnectManager(Context context) {
this.context = context;
}
public static synchronized CIMConnectorManager getManager(Context context) {
if (manager == null) {
manager = new CIMConnectorManager(context);
}
return manager;
}
public void connect(final String host, final int port) {
if (!CIMPushManager.isNetworkConnected(context)) {
@ -102,7 +95,7 @@ class CIMConnectorManager {
return;
}
if (isConnected()) {
if (isConnected() || connecting.get()) {
return;
}
@ -118,6 +111,8 @@ class CIMConnectorManager {
try {
connecting.set(true);
socketChannel = SocketChannel.open();
socketChannel.configureBlocking(true);
socketChannel.socket().setTcpNoDelay(true);
@ -129,6 +124,8 @@ class CIMConnectorManager {
handleConnectedEvent();
connecting.set(false);
/*
*开始读取来自服务端的消息先读取3个字节的消息头
*/
@ -141,10 +138,12 @@ class CIMConnectorManager {
*/
close();
} catch (ConnectException | SocketTimeoutException ignore) {
handleConnectAbortedEvent();
} catch (IOException ignore) {
} catch (ConnectException | SocketTimeoutException | UnknownHostException exception) {
handleConnectFailedEvent(exception);
} catch (IOException exception) {
handleDisconnectedEvent();
}finally {
connecting.set(false);
}
});
}
@ -155,12 +154,7 @@ class CIMConnectorManager {
return;
}
try {
socketChannel.close();
} catch (IOException ignore) {
} finally {
this.onSessionClosed();
}
this.closeForce();
}
public boolean isConnected() {
@ -200,6 +194,15 @@ class CIMConnectorManager {
}
private void closeForce(){
try {
socketChannel.close();
} catch (IOException ignore) {
} finally {
this.onSessionClosed();
}
}
private void onSessionCreated() {
LOGGER.sessionCreated(socketChannel);
@ -270,27 +273,36 @@ class CIMConnectorManager {
private final Handler idleHandler = new Handler() {
@Override
public void handleMessage(android.os.Message m) {
workerExecutor.execute(CIMConnectorManager.this::onSessionIdle);
workerExecutor.execute(CIMConnectManager.this::onSessionIdle);
}
};
private void handleDisconnectedEvent() {
close();
closeForce();
}
private void handleConnectAbortedEvent() {
private void handleConnectFailedEvent(Exception exception) {
/*
* 随机3-10秒后重连
*/
long interval = 3000L + random.nextInt(7001) ;
long retryAfter;
LOGGER.connectFailure(interval);
if (exception instanceof UnknownHostException){
/*
* 通常是网络由WIFI切换为移动网出现这个异常
*/
retryAfter = 3000L;
}else {
/*
* 随机3-10秒后重连
*/
retryAfter = 3000L + random.nextInt(7001) ;
}
LOGGER.connectFailure(retryAfter);
Intent intent = new Intent();
intent.setPackage(context.getPackageName());
intent.setAction(IntentAction.ACTION_CONNECT_FAILED);
intent.putExtra("interval", interval);
intent.putExtra(BundleKey.KEY_RECONNECT_AFTER, retryAfter);
context.sendBroadcast(intent);
}

View File

@ -77,7 +77,7 @@ public abstract class CIMEventBroadcastReceiver extends BroadcastReceiver {
* cim连接服务器失败事件
*/
if (IntentAction.ACTION_CONNECT_FAILED.equals(action)) {
long interval = intent.getLongExtra("interval", CIMConstant.RECONNECT_INTERVAL_TIME);
long interval = intent.getLongExtra(BundleKey.KEY_RECONNECT_AFTER, CIMConstant.RECONNECT_INTERVAL_TIME);
onInnerConnectFailed(interval);
}
@ -126,22 +126,16 @@ public abstract class CIMEventBroadcastReceiver extends BroadcastReceiver {
private void onInnerConnectionClosed() {
CIMCacheManager.putBoolean(context, CIMCacheManager.KEY_CIM_CONNECTION_STATE, false);
if (CIMPushManager.isNetworkConnected(context)) {
connect(0);
}
connect(0L);
onConnectionClosed();
}
private void onInnerConnectFailed(long interval) {
if (CIMPushManager.isNetworkConnected(context)) {
onConnectFailed();
onConnectFailed();
connect(interval);
connect(interval);
}
}
private void onInnerConnectFinished() {
@ -152,11 +146,6 @@ public abstract class CIMEventBroadcastReceiver extends BroadcastReceiver {
}
private void onDevicesNetworkChanged() {
if (CIMPushManager.isNetworkConnected(context)) {
connect(0);
}
onNetworkChanged();
}

View File

@ -53,7 +53,8 @@ public class CIMPushService extends Service {
private static final int NOTIFICATION_ID = Integer.MAX_VALUE;
private CIMConnectorManager connectorManager;
private CIMConnectManager connectManager;
private KeepAliveBroadcastReceiver keepAliveReceiver;
private ConnectivityManager connectivityManager;
private NotificationManager notificationManager;
@ -62,7 +63,7 @@ public class CIMPushService extends Service {
@Override
public void onCreate() {
connectorManager = CIMConnectorManager.getManager(this.getApplicationContext());
connectManager = new CIMConnectManager(this);
notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
@ -84,6 +85,7 @@ public class CIMPushService extends Service {
@Override
public void onAvailable(Network network) {
sendBroadcast(new Intent(IntentAction.ACTION_NETWORK_CHANGED));
handleKeepAlive();
}
@Override
@ -125,11 +127,11 @@ public class CIMPushService extends Service {
}
if (ServiceAction.ACTION_SEND_REQUEST_BODY.equals(action)) {
connectorManager.send((SentBody) newIntent.getSerializableExtra(BundleKey.KEY_SEND_BODY));
connectManager.send((SentBody) newIntent.getSerializableExtra(BundleKey.KEY_SEND_BODY));
}
if (ServiceAction.ACTION_CLOSE_CIM_CONNECTION.equals(action)) {
connectorManager.close();
connectManager.close();
}
if (ServiceAction.ACTION_ACTIVATE_PUSH_SERVICE.equals(action)) {
@ -137,12 +139,12 @@ public class CIMPushService extends Service {
}
if (ServiceAction.ACTION_DESTROY_CIM_SERVICE.equals(action)) {
connectorManager.close();
connectManager.close();
this.stopSelf();
}
if (ServiceAction.ACTION_CIM_CONNECTION_PONG.equals(action)) {
connectorManager.send(Pong.getInstance());
connectManager.send(Pong.getInstance());
}
if (ServiceAction.ACTION_SET_LOGGER_EATABLE.equals(action)) {
@ -195,7 +197,7 @@ public class CIMPushService extends Service {
return;
}
connectorManager.connect(host, port);
connectManager.connect(host, port);
}
@ -203,8 +205,8 @@ public class CIMPushService extends Service {
CIMLogger.getLogger().connectState(true, CIMPushManager.isStopped(this), CIMPushManager.isDestroyed(this));
if (connectorManager.isConnected()) {
connectorManager.pong();
if (connectManager.isConnected()) {
connectManager.pong();
return;
}
@ -252,9 +254,14 @@ public class CIMPushService extends Service {
if (notificationManager.getNotificationChannel(PERSIST_NTC_CHANNEL_ID) != null) {
startForeground(NOTIFICATION_ID, new Notification.Builder(this,PERSIST_NTC_CHANNEL_ID)
.setContentTitle(CIMCacheManager.getString(this,CIMCacheManager.KEY_NTC_CHANNEL_NAME))
.build());
int icon = CIMCacheManager.getInt(this,CIMCacheManager.KEY_NTC_CHANNEL_ICON);
String title = CIMCacheManager.getString(this,CIMCacheManager.KEY_NTC_CHANNEL_NAME);
String message = CIMCacheManager.getString(this,CIMCacheManager.KEY_NTC_CHANNEL_MESSAGE);
Notification notification = makeNotification(PERSIST_NTC_CHANNEL_ID,icon,title,message);
startForeground(NOTIFICATION_ID, notification);
return;
}
@ -267,9 +274,9 @@ public class CIMPushService extends Service {
notificationManager.createNotificationChannel(channel);
}
startForeground(NOTIFICATION_ID, new Notification.Builder(this,TRANSIENT_NTC_CHANNEL_ID)
.setContentTitle(CIMPushService.class.getSimpleName())
.build());
Notification notification = makeNotification(TRANSIENT_NTC_CHANNEL_ID,0,CIMPushService.class.getSimpleName(),null);
startForeground(NOTIFICATION_ID, notification);
}
@ -277,6 +284,8 @@ public class CIMPushService extends Service {
private void createPersistNotification(String channelName ,String message,int icon) {
CIMCacheManager.putString(this,CIMCacheManager.KEY_NTC_CHANNEL_NAME,channelName);
CIMCacheManager.putString(this,CIMCacheManager.KEY_NTC_CHANNEL_MESSAGE,message);
CIMCacheManager.putInt(this,CIMCacheManager.KEY_NTC_CHANNEL_ICON,icon);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && notificationManager.getNotificationChannel(PERSIST_NTC_CHANNEL_ID) == null) {
NotificationChannel channel = new NotificationChannel(PERSIST_NTC_CHANNEL_ID,channelName, NotificationManager.IMPORTANCE_DEFAULT);
@ -287,26 +296,40 @@ public class CIMPushService extends Service {
notificationManager.createNotificationChannel(channel);
}
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
intent.setPackage(getPackageName());
Notification notification = makeNotification(PERSIST_NTC_CHANNEL_ID,icon,channelName,message);
startForeground(NOTIFICATION_ID,notification);
}
private Notification makeNotification(String channel,int icon,String title,String message){
Notification.Builder builder;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
builder = new Notification.Builder(this,PERSIST_NTC_CHANNEL_ID);
builder = new Notification.Builder(this,channel);
}else {
builder = new Notification.Builder(this);
}
builder.setAutoCancel(false)
.setOngoing(false)
.setSmallIcon(icon)
.setWhen(System.currentTimeMillis())
.setContentIntent(PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_IMMUTABLE))
.setContentTitle(channelName)
.setContentIntent(getPendingIntent())
.setContentTitle(title)
.setContentText(message);
startForeground(NOTIFICATION_ID, builder.build());
if (icon > 0){
builder.setSmallIcon(icon);
}
return builder.build();
}
private PendingIntent getPendingIntent(){
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
intent.setPackage(getPackageName());
return PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_IMMUTABLE);
}
private class KeepAliveBroadcastReceiver extends BroadcastReceiver {

View File

@ -35,4 +35,6 @@ public interface BundleKey {
String KEY_NOTIFICATION_ICON = "KEY_NOTIFICATION_ICON";
String KEY_RECONNECT_AFTER = "KEY_RECONNECT_AFTER";
}

View File

@ -23,7 +23,7 @@ package com.farsunset.cim.sdk.android.constant;
public interface CIMConstant {
long RECONNECT_INTERVAL_TIME = 5 * 1000;
long RECONNECT_INTERVAL_TIME = 5000L;
/*
* 消息头长度为3个字节第一个字节为消息类型第二第三字节 转换int后为消息长度

View File

@ -34,7 +34,7 @@ android {
}
dependencies {
implementation "com.farsunset:cim-android-sdk:4.2.7"
implementation "com.farsunset:cim-android-sdk:4.2.8"
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'com.google.android.material:material:1.2.1'
implementation 'androidx.annotation:annotation:1.1.0'