package com.mogujie.tt.imlib;
import java.util.ArrayList;
import java.util.List;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.os.PowerManager;
import com.mogujie.tt.config.SysConstant;
import com.mogujie.tt.imlib.common.ErrorCode;
import com.mogujie.tt.log.Logger;
import com.mogujie.tt.ui.utils.IMServiceHelper;
import com.mogujie.tt.ui.utils.IMServiceHelper.OnIMServiceListner;
import com.mogujie.tt.utils.NetworkUtil;
public class IMReconnectManager extends IMManager implements OnIMServiceListner {
private static IMReconnectManager inst;
private Logger logger = Logger.getLogger(IMReconnectManager.class);
private IMServiceHelper imServiceHelper = new IMServiceHelper();
private boolean reconnecting = false;
private final int RECONNECT_TIME_BASE = 3;
private int reconnect_index = 0;
public static IMReconnectManager instance() {
synchronized (IMReconnectManager.class) {
if (inst == null) {
inst = new IMReconnectManager();
}
return inst;
}
}
private IMReconnectManager() {
}
public void register() {
logger.d("reconnect#regisgter");
List<String> actions = new ArrayList<String>();
actions.add(IMActions.ACTION_LOGIN_RESULT);
actions.add(IMActions.ACTION_SERVER_DISCONNECTED);
actions.add(ConnectivityManager.CONNECTIVITY_ACTION);
imServiceHelper.registerActions(ctx, actions, IMServiceHelper.INTENT_NO_PRIORITY, this);
}
private void scheduleReconnect(int seconds) {
logger.d("reconnect#scheduleReconnect after %d seconds", seconds);
Intent intent = new Intent(IMActions.ACTION_RECONNECT);
PendingIntent pi = PendingIntent.getBroadcast(ctx, 0, intent, 0);
if (pi == null) {
logger.e("reconnect#pi is null");
return;
}
AlarmManager am = (AlarmManager) ctx.getSystemService(Context.ALARM_SERVICE);
am.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + seconds
* 1000, pi);
}
private void resetReconnectTime() {
logger.d("reconnect#resetReconnectTime");
reconnect_index = 0;
}
private void reconnect() {
logger.d("reconnect#reconnect the server");
if (!IMLoginManager.instance().isEverLoginned()) {
logger.d("reconnect#not everlogined before, no need to do reconnect");
return;
}
// so reconnect will use the initial reconnecting time
resetReconnectTime();
if (IMLoginManager.instance().relogin()) {
reconnecting = true;
logger.d("reconnect#start reconnecting");
}
}
private void onLoginSuccess() {
logger.d("reconnect#onLogin Successful");
reconnecting = false;
}
private void onLoginFailed() {
logger.d("reconnect#onLoginFailed");
if (reconnecting) {
logger.d("reconnect#in reconnecting procedure");
// Exponential backoff strategy
scheduleReconnect(RECONNECT_TIME_BASE * (2 << reconnect_index++));
}
}
private void handleLoginResultAction(Intent intent) {
logger.d("reconnect#handleLoginResultAction");
int errorCode = intent.getIntExtra(SysConstant.lOGIN_ERROR_CODE_KEY, -1);
if (errorCode == ErrorCode.S_OK) {
onLoginSuccess();
} else {
onLoginFailed();
}
}
private void handleDisconnectServerAction() {
logger.d("reconnect#handleDisconnectServerAction");
if (NetworkUtil.isNetWorkAvalible(ctx)) {
logger.d("reconnect#disconnect with the server, network is available, reconnect");
reconnect();
} else {
logger.d("reconnect#network is unavailable, no need to reconnect");
}
}
private void handleNetworkActivityChangedAction() {
logger.d("reconnect#handleNetworkActivityChangedAction");
if (NetworkUtil.isNetWorkAvalible(ctx)) {
logger.d("reconnect#network is available");
reconnect();
} else {
logger.d("reconnect#network is unavailable");
}
}
private void handleReconnectServer() {
logger.d("reconnect#handleReconnectServer");
PowerManager pm = (PowerManager) ctx.getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "teamtalk_reconnecting_wakelock");
wl.acquire();
try {
IMLoginManager.instance().relogin();
} finally {
wl.release();
}
}
@Override
public void onAction(String action, Intent intent,
BroadcastReceiver broadcastReceiver) {
logger.d("reconnect#onAction action:%s", action);
if (action.equals(IMActions.ACTION_LOGIN_RESULT)) {
handleLoginResultAction(intent);
} else if (action.equals(IMActions.ACTION_SERVER_DISCONNECTED)) {
handleDisconnectServerAction();
} else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
handleNetworkActivityChangedAction();
} else if (action.equals(IMActions.ACTION_RECONNECT)) {
handleReconnectServer();
}
}
@Override
public void onIMServiceConnected() {
// TODO Auto-generated method stub
}
}