ReconnectionManager.java 4.27 KB
Newer Older
Alexander Ivanov's avatar
Alexander Ivanov committed
1 2
/**
 * Copyright (c) 2013, Redsolution LTD. All rights reserved.
3
 *
Alexander Ivanov's avatar
Alexander Ivanov committed
4 5
 * This file is part of Xabber project; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License, Version 3.
6
 *
Alexander Ivanov's avatar
Alexander Ivanov committed
7 8 9 10
 * Xabber is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU General Public License for more details.
11
 *
Alexander Ivanov's avatar
Alexander Ivanov committed
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
 * You should have received a copy of the GNU General Public License,
 * along with this program. If not, see http://www.gnu.org/licenses/.
 */
package com.xabber.android.data.connection;

import java.util.HashMap;
import java.util.Map.Entry;

import com.xabber.android.data.Application;
import com.xabber.android.data.OnTimerListener;
import com.xabber.android.data.account.AccountItem;
import com.xabber.android.data.account.AccountManager;
import com.xabber.android.data.account.OnAccountRemovedListener;

public class ReconnectionManager implements OnConnectionListener,
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124
        OnConnectedListener, OnAccountRemovedListener, OnTimerListener {

    /**
     * Intervals in seconds to be used for attempt to reconnect. First value
     * will be used on first attempt. Next value will be used if reconnection
     * fails. Last value will be used if there is no more values in array.
     */
    private final static int RECONNECT_AFTER[] = new int[]{2, 10, 30, 60};

    /**
     * Managed connections.
     */
    private final HashMap<ConnectionItem, ReconnectionInfo> connections;

    private final static ReconnectionManager instance;

    static {
        instance = new ReconnectionManager(Application.getInstance());
        Application.getInstance().addManager(instance);
    }

    public static ReconnectionManager getInstance() {
        return instance;
    }

    private ReconnectionManager(Application application) {
        connections = new HashMap<ConnectionItem, ReconnectionInfo>();
    }

    @Override
    public void onTimer() {
        for (Entry<ConnectionItem, ReconnectionInfo> entry : connections
                .entrySet()) {
            ReconnectionInfo reconnectionInfo = entry.getValue();
            ConnectionItem connectionItem = entry.getKey();
            if (connectionItem.getState() == ConnectionState.waiting) {
                int reconnectAfter;
                if (reconnectionInfo.reconnectAttempts < RECONNECT_AFTER.length)
                    reconnectAfter = RECONNECT_AFTER[reconnectionInfo.reconnectAttempts];
                else
                    reconnectAfter = RECONNECT_AFTER[RECONNECT_AFTER.length - 1];
                if (reconnectionInfo.reconnectCounter >= reconnectAfter) {
                    reconnectionInfo.reconnectCounter = 0;
                    reconnectionInfo.reconnectAttempts += 1;
                    connectionItem.updateConnection(false);
                    if (connectionItem instanceof AccountItem)
                        AccountManager.getInstance().onAccountChanged(
                                ((AccountItem) connectionItem).getAccount());
                } else {
                    reconnectionInfo.reconnectCounter += 1;
                }
            } else {
                reconnectionInfo.reconnectCounter = 0;
            }
        }
    }

    @Override
    public void onConnection(ConnectionItem connection) {
        ReconnectionInfo info = connections.get(connection);
        if (info == null) {
            info = new ReconnectionInfo();
            connections.put(connection, info);
        }
        info.reconnectAttempts += 1;
        info.reconnectCounter = 0;
    }

    @Override
    public void onConnected(ConnectionItem connection) {
        ReconnectionInfo info = connections.get(connection);
        info.reconnectAttempts = 0;
        info.reconnectCounter = 0;
    }

    @Override
    public void onAccountRemoved(AccountItem accountItem) {
        connections.remove(accountItem);
    }

    /**
     * Information about reconnection attempts.
     *
     * @author alexander.ivanov
     */
    private static class ReconnectionInfo {

        /**
         * Number of attempts to reconnect without success.
         */
        int reconnectAttempts = 0;

        /**
         * Number of seconds passed from last reconnection.
         */
        int reconnectCounter = 0;

    }
Alexander Ivanov's avatar
Alexander Ivanov committed
125 126

}