| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391 |
- package com.xzjmyk.pm.activity.xmpp;
- import android.content.Context;
- import android.text.TextUtils;
- import android.util.Log;
- import com.alibaba.fastjson.JSON;
- import com.alibaba.fastjson.JSONObject;
- import com.xzjmyk.pm.activity.MyApplication;
- import com.xzjmyk.pm.activity.bean.LoginAuto;
- import com.xzjmyk.pm.activity.helper.LoginHelper;
- import com.xzjmyk.pm.activity.sp.UserSp;
- import com.xzjmyk.pm.activity.ui.erp.util.LogUtil;
- import com.xzjmyk.pm.activity.util.DeviceInfoUtil;
- import com.xzjmyk.pm.activity.volley.Result;
- import org.jivesoftware.smack.AbstractConnectionListener;
- import org.jivesoftware.smack.XMPPConnection;
- import org.jivesoftware.smack.XMPPException.StreamErrorException;
- import org.jivesoftware.smack.packet.StreamError;
- import org.jivesoftware.smack.tcp.XMPPTCPConnection;
- import org.jivesoftware.smack.util.StringUtils;
- import java.io.DataOutputStream;
- import java.io.IOException;
- import java.io.InputStream;
- import java.net.HttpURLConnection;
- import java.net.URL;
- import java.util.Random;
- public class XReconnectionManager extends AbstractConnectionListener {
- // Holds the connection to the server
- private XMPPConnection mConnection;
- private boolean isReconnectionAllowed = false;
- private Thread mReconnectionThread;
- boolean mIsNetWorkActive;
- // Holds the state of the reconnection
- boolean doReconnecting = false;
- Context mContext;
- public XReconnectionManager(Context context, XMPPConnection connection, boolean reconnectionAllowed, boolean isNetWorkActive) {
- mContext = context;
- mConnection = connection;
- mConnection.addConnectionListener(this);
- isReconnectionAllowed = reconnectionAllowed;
- mIsNetWorkActive = isNetWorkActive;
- }
- /**
- * Returns true if the reconnection mechanism is enabled.
- *
- * @return true if automatic reconnections are allowed.
- */
- private boolean isReconnectionAllowed() {
- return doReconnecting && mIsNetWorkActive && !mConnection.isConnected() && isReconnectionAllowed;
- }
- public void setNetWorkState(boolean isNetWorkActive) {
- mIsNetWorkActive = isNetWorkActive;
- if (mIsNetWorkActive) {// 网络状态变为可用
- LogUtil.d("Xmpp","isReconnectionAllowed:"+isReconnectionAllowed()
- +" user:"+mConnection.getUser());
- if (isReconnectionAllowed()) {
- reconnect();
- }
- } else {
- if (mReconnectionThread != null && mReconnectionThread.isAlive()) {
- mReconnectionThread.interrupt();
- }
- }
- }
- /**
- * Starts a reconnection mechanism if it was configured to do that. The algorithm is been executed when the first connection error is detected.
- * <p/>
- * The reconnection mechanism will try to reconnect periodically in this way:
- * <ol>
- * <li>First it will try 6 times every 10 seconds.
- * <li>Then it will try 10 times every 1 minute.
- * <li>Finally it will try indefinitely every 5 minutes.
- * </ol>
- */
- private synchronized void reconnect() {
- if (this.isReconnectionAllowed()) {
- // Since there is no thread running, creates a new one to attempt
- // the reconnection.
- // avoid to run duplicated reconnectionThread -- fd: 16/09/2010
- if (mReconnectionThread != null && mReconnectionThread.isAlive()){
- LogUtil.d("Xmpp","mReconnectionThread 线程已存在");
- return;
- }else{
- LogUtil.d("Xmpp","mReconnectionThread 新线程:"+mConnection.getUser());
-
- }
-
- mReconnectionThread = new Thread() {
- private int mRandomBase = new Random().nextInt(11) + 5; // between 5 and 15 seconds
- /**
- * Holds the current number of reconnection attempts
- */
- private int attempts = 0;
- /**
- * Returns the number of seconds until the next reconnection attempt.
- *
- * @return the number of seconds until the next reconnection attempt.
- */
- private int timeDelay() {
- attempts++;
- if (attempts > 13) {
- return mRandomBase * 6 * 5; // between 2.5 and 7.5
- // minutes (~5 minutes)
- }
- if (attempts > 7) {
- return mRandomBase * 6; // between 30 and 90 seconds (~1
- // minutes)
- }
- return mRandomBase; // 10 seconds
- }
- /**
- * The process will try the reconnection until the connection succeed or the user cancel it
- */
- public void run() {
- // 重新连接之前,先检查Token状态
- int checkTokenStatus = 0;
- while (isReconnectionAllowed() && checkTokenStatus == 0) {
- checkTokenStatus = syncCheckToken();
- if (checkTokenStatus == 0) {// 表示检查失败,继续循环检查
- LogUtil.d("Token","0:表示检查失败,继续循环检查");
- try {
- Thread.sleep(5000);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- } else if (checkTokenStatus == 1) {// 表示检查成功Token过期(或出现不能继续请求Token状态的异常),停止重新登陆
- doReconnecting = false;
- LogUtil.d("Token","1:表示检查成功Token过期");
- //TODO 关闭自动登录 可能出现账号异常情况
- //mConnection.login();
- // conflict();
- } else if (checkTokenStatus == 2) {// 2、表示检查成功,Token没有改变,可以继续下面的重新登陆
- LogUtil.d("Token","2:表示检查成功,Token没有改变,可以继续下面的重新登陆");
- break;
- }
- }
- while (isReconnectionAllowed()) {
- // Makes a reconnection attempt
- try {
- if (isReconnectionAllowed()) {
- mConnection.connect();
- }
- } catch (Exception e) {
- notifyReconnectionFailed(e);// Fires the failed reconnection notification
- }
- int remainingSeconds = timeDelay();
- while (isReconnectionAllowed() && remainingSeconds > 0) {
- try {
- Thread.sleep(1000);
- remainingSeconds--;
- notifyAttemptToReconnectIn(remainingSeconds);
- } catch (InterruptedException e1) {
- // Notify the reconnection has failed
- notifyReconnectionFailed(e1);
- }
- }
- }
- }
- };
- mReconnectionThread.setName("Smack XReconnectionManager");
- mReconnectionThread.setDaemon(true);
- mReconnectionThread.start();
- }
- }
- /**
- * 在检查Token的时候,发现冲突了
- */
- private void conflict() {
- ((CoreService) mContext).logout();
- LoginHelper.broadcastConflict(mContext);
- }
- /**
- * 检查Token状态,并返回int值<br/>
- * 0、表示检查失败,继续循环检查 <br/>
- * 1、表示检查成功Token过期(或出现不能继续请求Token状态的异常),停止重新登陆<br/>
- * 2、表示检查成功,Token没有改变,可以继续下面的重新登陆<br/>
- *
- * @return
- */
- private int syncCheckToken() {// 同步网络请求Token
- if (CoreService.DEBUG) {
- Log.d(CoreService.TAG, "开始重新登陆前的 Token 状态检查");
- String requestUrl = MyApplication.getInstance().getConfig().USER_LOGIN_AUTO;
- if (requestUrl == null) {
- return 1;
- }
- HttpURLConnection httpConn = null;
- DataOutputStream out = null;
- InputStream is = null;
- try {
- URL url = new URL(requestUrl);
- httpConn = (HttpURLConnection) url.openConnection();
- httpConn.setDoOutput(true);
- httpConn.setDoInput(true);
- httpConn.setConnectTimeout(5 * 1000);
- httpConn.setReadTimeout(5 * 1000);
- httpConn.setRequestMethod("POST");
- httpConn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8");
- out = new DataOutputStream(httpConn.getOutputStream());
- // 参数
- String access_token = MyApplication.getInstance().mAccessToken;
- if (TextUtils.isEmpty(access_token)) {
- access_token = UserSp.getInstance(mContext).getAccessToken(null);
- }
- if (TextUtils.isEmpty(access_token)) {
- return 1;
- }
- String serial = DeviceInfoUtil.getDeviceId(mContext);
- if (TextUtils.isEmpty(serial)) {
- return 1;
- }
- if (CoreService.DEBUG) {
- Log.d(CoreService.TAG, "requestUrl:" + requestUrl);
- Log.d(CoreService.TAG, "access_token:" + access_token);
- Log.d(CoreService.TAG, "serial:" + serial);
- }
- StringBuilder sb = new StringBuilder();
- sb.append("access_token=" + access_token + "&");
- //String user = ((XMPPTCPConnection) mConnection).getDirectUser();
- LogUtil.d("wang",JSON.toJSONString(mConnection));
- String user =mConnection.getUser();
- Log.d("wang", "user..." + user);
- if (user == null) {
- return 1;
- }
- sb.append("userId=" + StringUtils.parseName(user) + "&");
- sb.append("serial=" + serial);
- out.write(sb.toString().getBytes("UTF-8"));
- out.flush();
- int statusCode = httpConn.getResponseCode();
- if (statusCode != 200) {
- return 0;
- }
- is = httpConn.getInputStream();
- if (is == null) {
- return 0;
- }
- StringBuffer buffer = new StringBuffer();
- int len = -1;
- byte[] data = new byte[1024];
- try {
- while ((len = is.read(data)) != -1) {
- buffer.append(new String(data, 0, len));
- }
- } catch (IOException e) {
- e.printStackTrace();
- }
- String result = buffer.toString();
- if (CoreService.DEBUG) {
- Log.d(CoreService.TAG, "检查状态result:" + result);
- }
- if (TextUtils.isEmpty(result)) {
- Log.d("wang", "result==null");
- return 0;
- }
- try {
- JSONObject jsonObject = JSON.parseObject(result);
- int resultCode = jsonObject.getIntValue(Result.RESULT_CODE);
- if (resultCode != 1) {
- return 0;
- }
- LoginAuto loginAuto = JSON.parseObject(jsonObject.getString(Result.DATA), LoginAuto.class);
- LogUtil.d("Token","loginAuto:"+JSON.toJSONString(loginAuto));
- if (loginAuto != null) {// 判断时候要继续重新登陆
- int tokenExists = loginAuto.getTokenExists();// 1=令牌存在、0=令牌不存在
- int serialStatus = loginAuto.getSerialStatus();// 1=没有设备号、2=设备号一致、3=设备号不一致
- if (serialStatus == 2) {// 设备号一致,说明没有切换过设备
- if (tokenExists == 1) {// Token存在,
- return 2;
- } else {// Token 不存在
- return 1;
- }
- } else {// 设备号不一致,那么就是切换过手机
- return 1;
- }
- } else {
- return 0;
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- } catch (Exception e) {
- e.printStackTrace();
- } finally {
- try {
- if (out != null) {
- out.close();
- }
- if (is != null) {
- is.close();
- }
- } catch (IOException e) {
- e.printStackTrace();
- }
- if (httpConn != null) {
- httpConn.disconnect();
- }
- }
- }
- return 0;
- }
- private void notifyReconnectionFailed(Exception exception) {
- if (isReconnectionAllowed()) {
- LogUtil.d("xmppLogs","notifyReconnectionFailed");
- // for (ConnectionListener listener : mConnection.getConnectionListeners()) {
- // listener.reconnectionFailed(exception);
- // }
- }
- }
- private void notifyAttemptToReconnectIn(int seconds) {
- if (isReconnectionAllowed()) {
- LogUtil.d("xmppLogs","notifyAttemptToReconnectIn");
- // for (ConnectionListener listener : mConnection.getConnectionListeners()) {
- // listener.reconnectingIn(seconds);
- // }
- }
- }
- void release() {
- doReconnecting = false;
- if (mReconnectionThread != null && mReconnectionThread.isAlive()) {
- mReconnectionThread.interrupt();
- }
- }
- @Override
- public void connectionClosed() {
- doReconnecting = false;
- }
- @Override
- public void connectionClosedOnError(Exception e) {
- LogUtil.d("reconnect","<<connectionClosedOnError>> mConnection:"+((XMPPTCPConnection)mConnection).getUser()
- +" isAuthenticated():"+mConnection.isAuthenticated());
- doReconnecting = true;
- if (e instanceof StreamErrorException) {// 有人重复登陆
- StreamErrorException xmppEx = (StreamErrorException) e;
- StreamError error = xmppEx.getStreamError();
- String reason = error.getCode();
- if ("conflict".equals(reason)) {// 发出下线通知
- if (CoreService.DEBUG)
- Log.d(CoreService.TAG, "异常断开,有另外设备登陆啦");
- conflict();
- doReconnecting = false;
- return;
- }
- }
- // 因为其他原因导致下线,那么就开始重连
- if (this.isReconnectionAllowed()) {
- if (CoreService.DEBUG)
- Log.d(CoreService.TAG, "异常断开,开始重连");
- this.reconnect();
- }
- }
- public XMPPConnection getmConnection() {
- return mConnection;
- }
- }
|