Подтвердить что ты не робот

Как сохранить стабильное соединение XMPP на Android с (a) привкус?

Я использую библиотеку asmack-android-7-beem для Android. У меня работает фоновый сервис, например, мое приложение остается в живых. Но рано или поздно XMPP-соединение умирает без какого-либо уведомления. Сервер говорит, что клиент все еще подключен, но пакеты не отправляются и не принимаются.

Например, клиент не получает никаких пакетов присутствия, когда другие клиенты имеют новое присутствие. У меня XMPPConnection в качестве атрибута моего основного класса приложения.
Я установил ConnectionConfiguration config.setReconnectionAllowed(true) до того, как соединение было выполнено.
Но пересоединения не бывает. XMPPConnection connection.isConnected() возвращает true.

Таким образом, клиент не знает, что соединение действительно потеряно.

Есть ли способ сохранить соединение живым?

4b9b3361

Ответ 1

При использовании asmack добавьте такой код в ваше приложение, чтобы заставить Dalvik загрузить класс ReconnectionManager и запустить его статический блок инициализации:

static {
    try {
        Class.forName("org.jivesoftware.smack.ReconnectionManager");
    } catch (ClassNotFoundException ex) {
        // problem loading reconnection manager
    }
}

Ответ 2

На самом деле нет проблем с менеджером Reconnection. Сначала вам нужно добавить прослушиватель соединений к диспетчеру соединений.

connection.addConnectionListener(new ConnectionListener() {

                    @Override
                    public void reconnectionSuccessful() {
                        Log.i("","Successfully reconnected to the XMPP server.");

                    }

                    @Override
                    public void reconnectionFailed(Exception arg0) {
                        Log.i("","Failed to reconnect to the XMPP server.");
                    }

                    @Override
                    public void reconnectingIn(int seconds) {
                        Log.i("","Reconnecting in " + seconds + " seconds.");
                    }

                    @Override
                    public void connectionClosedOnError(Exception arg0) {
                        Log.i("","Connection to XMPP server was lost.");
                    }

                    @Override
                    public void connectionClosed() {
                        Log.i("","XMPP connection was closed.");

                    }
                }); 

если возникла какая-либо ошибка, автоматически вызовет connectionClosedOnError (Exception arg0) когда соединение закрыто

 public void connectionClosed() {
                        Log.i("","XMPP connection was closed.");
                        //You can manually call reconnection code if you                  want to reconnect on any connection close
                    }

затем проверьте, что это вызовет метод reconnectingin() и попытается снова подключиться.

Надеюсь, это поможет вам.

используйте код для проверки соединения PingManager pingManager = PingManager.getInstanceFor(connection); pingManager.setPingInterval(5000);

добавить listner для обработки ошибок ping для обработки соединения подключен или нет, потому что метод isConnected не является надежным для проверки состояния соединения.

pingManager.registerPingFailedListener(PingFailedListener);

Для подключения к мобильной сети очень большая проблема, поэтому вам необходимо проверить сетевое подключение для мобильных устройств с помощью широковещательного приемника и при повторном подключении данных, вы можете использовать метод pingMyServer для проверки соединения вживую или нет, если вы получаете ответ ping с сервера, значит соединение в противном случае происходит при ошибке ping, вы можете повторно подключить соединение вручную.

Ответ 3

У меня та же проблема, за исключением того, что моя программа запускается на стороне JVM на стороне сервера.
В первую очередь я использовал smack 4.0. Затем я обновился, чтобы взломать 4.1, но проблема все же произошла. Наконец, я нашел модуль конфигурации: PingManager
После этого возникла такая ситуация.

    connection = new XMPPTCPConnection(config);     
    PingManager pingManager = PingManager.getInstanceFor(connection);
    pingManager.setPingInterval(300); // seconds

Ответ 4

В Smack 4.1 я использую ServerPingWithAlarmManager. Вы можете найти более подробную информацию о сохранении связи ramzandroid blog здесь.

Ответ 5

Здесь мой код отлично работает для ReconnectionManager

1) Добавьте addConnectionListener в соединение xmpp

XMPPConnectionListener mConnectionListener = new XMPPConnectionListener(username);
connection.addConnectionListener(mConnectionListener);

2), если соединение закрыто, затем снова подключитесь с помощью ReconnectionManager class

 ReconnectionManager reconnectionManager = ReconnectionManager.getInstanceFor(connection);
 reconnectionManager.enableAutomaticReconnection();
 reconnectionManager.setEnabledPerDefault(true);

3) ConnectionListener для повторного подключения, подключения и аутентификации на сервере. если соединение успешно завершено с сервером, также зарегистрируйте класс PingManager и ServerPingWithAlarmManager.

public class XMPPConnectionListener implements ConnectionListener {
    String username="";
    public XMPPConnectionListener(String username){
        this.username=username;
    }
    @Override
    public void connected(final XMPPConnection connectionObeject) {

        sendPresenceAvailable();
        Log.d(TAG, "xmpp Connected()");
        connected = true;

    }

    @Override
    public void connectionClosed() {

        Log.d(TAG, "xmpp ConnectionCLosed()");

        isAuthenticatedPreviouly=false;
        connected = false;

        loggedin = false;

    }

    @Override
    public void connectionClosedOnError(Exception arg0) {
        Log.d(TAG, "xmpp ConnectionClosedOnError() :"+System.currentTimeMillis());

        isAuthenticatedPreviouly=false;
        connected = false;

        loggedin = false;
    }

    @Override
    public void reconnectingIn(int arg0) {
        Log.d(TAG, "xmpp reconnectingIn() :"+System.currentTimeMillis());

        loggedin = false;
    }

    @Override
    public void reconnectionFailed(Exception arg0) {
        Log.d(TAG, "xmpp ReconnectionFailed!");
        connected = false;

       // chat_created = false;
        loggedin = false;
        try {
            connection.connect();
        } catch (SmackException | IOException | XMPPException | InterruptedException exception) {
            exception.printStackTrace();
        }
    }

    @Override
    public void reconnectionSuccessful() {
        Log.d(TAG, "xmpp ReconnectionSuccessful");
        connected = true;
        sendPresenceAvailable();
        loggedin = false;
    }

    @Override
    public void authenticated(XMPPConnection connection2, boolean resumed) {

        Log.d(TAG, "xmpp Type Main Authenticated() :" + connection.isAuthenticated());

        if(connection.isAuthenticated()) {

            ServerPingWithAlarmManager.getInstanceFor(connection).setEnabled(true);

            PingManager pingManager = PingManager.getInstanceFor(connection);
            pingManager.setPingInterval(10);

            try {
                pingManager.pingMyServer();
                pingManager.pingMyServer(true,10);
                pingManager.pingServerIfNecessary();
                pingManager.registerPingFailedListener(new PingFailedListener() {
                    @Override
                    public void pingFailed() {
                        Log.d("Ping","pingFailed");
                        disconnect();
                        connect();
                    }
                });

            registerAllListener();
     }
}

Ответ 6

В этом случае вам необходимо вручную отключить разъединение, я имею в виду, что вы должны перехватывать любое отключение, уведомление о подключении, уведомленное, когда вы отключились.

public void connectionClosedOnError (исключение исключения)

    import android.util.Log;

    import com.dagm8.core.protocols.ConnectionState;
    import com.dagm8.core.service.XMPPService;
    import com.dagm8.events.ConnectionStateEvent;

    import org.greenrobot.eventbus.EventBus;
    import org.jivesoftware.smack.ConnectionListener;
    import org.jivesoftware.smack.SmackException;
    import org.jivesoftware.smack.XMPPConnection;
    import org.jivesoftware.smack.XMPPException;
    import org.jivesoftware.smack.tcp.XMPPTCPConnection;

    import java.io.IOException;

    import static com.dagm8.core.protocols.ConnectionState.CONNECTED;
    import static com.dagm8.core.protocols.ConnectionState.DISCONNECTED;
    import static com.dagm8.core.protocols.ConnectionState.RECONNECTING;

    /**
     * dagm8-android
     * Created by Bedoy on 8/28/17.
     */

    public class ConnectionController implements ConnectionListener {

        private String TAG = getClass().getCanonicalName();

        private XMPPTCPConnection mConnection;

        public void setConnection(XMPPTCPConnection connection) {
            mConnection = connection;
        }

        public void init(XMPPTCPConnection connection) throws InterruptedException, XMPPException, SmackException, IOException {

            setConnection(connection);

            mConnection.setPacketReplyTimeout(10000);
            mConnection.addConnectionListener(this);
            mConnection.connect();
        }

        @Override
        public void connected(XMPPConnection connection) {
            XMPPService.connectionState = RECONNECTING;

            notifyConnectionState(RECONNECTING);

            try {
                mConnection.login();
            } catch (XMPPException | SmackException | IOException | InterruptedException e) {
                e.printStackTrace();
            }

            Log.i(TAG, "connected()");
        }


        @Override
        public void authenticated(XMPPConnection connection, boolean resumed) {
            XMPPService.connectionState = CONNECTED;

            notifyConnectionState(CONNECTED);

            Log.i(TAG, "authenticated()");
        }

        @Override
        public void connectionClosed() {
            XMPPService.connectionState = DISCONNECTED;

            notifyConnectionState(DISCONNECTED);

            Log.i(TAG, "connectionClosed()");
        }

        @Override
        public void connectionClosedOnError(Exception e) {
            XMPPService.connectionState = DISCONNECTED;

            notifyConnectionState(DISCONNECTED);


            try {
                mConnection.connect();
            } catch (SmackException | IOException | XMPPException | InterruptedException exception) {
                exception.printStackTrace();
            }
            Log.i(TAG, "connectionClosedOnError()");
        }

        @Override
        public void reconnectingIn(int seconds) {
            XMPPService.connectionState = RECONNECTING;

            notifyConnectionState(RECONNECTING);

            Log.i(TAG, "reconnectingIn()");
        }

        @Override
        public void reconnectionSuccessful() {
            XMPPService.connectionState = CONNECTED;

            notifyConnectionState(CONNECTED);

            Log.i(TAG, "reconnectionSuccessful()");
        }

        @Override
        public void reconnectionFailed(Exception e) {
            XMPPService.connectionState = DISCONNECTED;

            notifyConnectionState(DISCONNECTED);

            Log.i(TAG, "reconnectionFailed()");
        }


        private void notifyConnectionState(ConnectionState state) {
            EventBus.getDefault().post((ConnectionStateEvent) () -> state);
        }

        public boolean isAuthenticated()
        {
            return mConnection.isAuthenticated();
        }

        public void login() {
            try {
                mConnection.login();
            } catch (XMPPException | SmackException | IOException | InterruptedException e) {
                e.printStackTrace();
            }
        }
    }