mirror of
https://gitee.com/farsunset/cim.git
synced 2025-07-27 02:20:32 +08:00
修复android sdk 一处bug
频发切换wifi和移动网络,概率出现无法重连的问题
This commit is contained in:
parent
35ab7cc72c
commit
e89a3918c5
@ -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>
|
||||
|
@ -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";
|
||||
|
||||
|
@ -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);
|
||||
|
||||
}
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -35,4 +35,6 @@ public interface BundleKey {
|
||||
|
||||
String KEY_NOTIFICATION_ICON = "KEY_NOTIFICATION_ICON";
|
||||
|
||||
String KEY_RECONNECT_AFTER = "KEY_RECONNECT_AFTER";
|
||||
|
||||
}
|
||||
|
@ -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后为消息长度
|
||||
|
@ -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'
|
||||
|
Loading…
x
Reference in New Issue
Block a user