web-dev-qa-db-fra.com

Comment garder une connexion XMPP stable sur Android avec (a) smack?

J'utilise la bibliothèque asmack-Android-7-Beem pour Android. J'ai un fonctionement de fond, comme mon application reste en vie. Mais tôt ou tard la connexion XMPP meurt sans préavis. Le serveur dit que le client est toujours en ligne, mais aucun paquet sont envoyés ou reçus.

Par exemple, le client ne reçoit pas de paquets de présence alors que d'autres clients ont une nouvelle présence. Je XMPPConnection comme attibute de ma classe principale de l'application.
Je mis ConnectionConfiguration config.setReconnectionAllowed(true) avant que la connexion a été faite.
Mais la reconnexion ne se produit pas. XMPPConnection connection.isConnected() retourne vrai.

Le client ne sait donc pas que la connexion est réellement perdue.

Y at-il un moyen de garder la connexion en vie?

25
Max

Lorsque vous utilisez asmack, mettez du code comme celui-ci dans votre application pour que Dalvik charge la classe ReconnectionManager et exécute son bloc d'initialisation statique:

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

En fait, il n’ya aucun problème avec Reconnection Manager. Vous devez d’abord ajouter un écouteur de connexion à votre gestionnaire de connexion.

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.");

                    }
                }); 

si une erreur survient, connectionClosedOnError (Exception arg0) sera automatiquement appelé à la fermeture de la connexion. 

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

puis cochez-la pour appeler la méthode reconnectingin () et essayer de vous reconnecter.

J'espère que cela vous aidera. 

utilisez le code ci-dessous pour vérifier la connexion PingManager pingManager = PingManager.getInstanceFor(connection); pingManager.setPingInterval(5000);

add listner pour ping La gestion des échecs pour gérer la connexion est connectée ou non car la méthode isConnected n'est pas fiable pour vérifier l'état de la connexion.

pingManager.registerPingFailedListener(PingFailedListener);

Pour la connectivité réseau mobile est un très gros problème, donc vous devez vérifier la connectivité réseau pour mobile en utilisant le récepteur de diffusion et sur la reconnexion des données, vous pouvez utiliser la méthode pingMyServer pour vérifier si la connexion est active ou non, si vous obtenez une réponse ping du serveur, signifie que la connexion est active sinon, en cas d'échec du ping, vous pouvez vous reconnecter manuellement.

8
Mandeep

Voici mon code fonctionne bien pour ReconnectionManager

1) Ajoutez addConnectionListener sur la connexion xmpp

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

2) si la connexion est fermée, reconnectez-vous automatiquement à l'aide de ReconnectionManager class

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

3) ConnectionListener pour se reconnecter, se connecter et s'authentifier sur le serveur. Si la connexion est authentifiée avec succès avec le serveur, enregistrez également les classes PingManager et 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();
     }
}
3
Sagar Jethva

J'ai le même problème, sauf que mon programme est exécuté sur la machine virtuelle Java côté serveur.
J'ai utilisé smack 4.0 en premier lieu. Ensuite, j'ai mis à jour pour smack 4.1, mais le problème est toujours arrivé. Enfin, j'ai trouvé un module de configuration: PingManager
Après avoir utilisé cela, l’occurrence de cette situation a été réduite.

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

Dans Smack 4.1, j'utilise ServerPingWithAlarmManager. Vous pouvez trouver plus de détails sur le maintien de la connexion en vie blog ramzandroid ici .

1
taynguyen

Dans ce cas, vous devez gérer la déconnexion manuellement, ce qui signifie que vous devez intercepter toute déconnexion, écouteur de connexion averti lorsque vous obtenez une déconnexion.

public void connectionClosedOnError (Exception exception)

    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();
            }
        }
    }
0
Carlos Bedoy