27

我为 Android 使用 asmack-android-7-beem 库。我有一个后台服务正在运行,例如我的应用程序保持活动状态。但是 XMPP 连接迟早会在没有任何通知的情况下死掉。服务器说客户端仍然在线,但没有发送或接收数据包。

例如,当其他客户端有新的状态时,客户端不会收到任何状态数据包。我将 XMPPConnection 作为我的主要应用程序类的属性。
ConnectionConfiguration config.setReconnectionAllowed(true)在建立连接之前进行了设置。
但重新连接不会发生。XMPPConnection connection.isConnected()返回真。

所以客户端不知道连接实际上已经丢失。

有什么办法可以保持连接活跃吗?

4

6 回答 6

12

使用 asmack 时,在您的应用程序中添加一些类似这样的代码,以使 Dalvik 加载 ReconnectionManager 类并运行它的静态初始化块:

static {
    try {
        Class.forName("org.jivesoftware.smack.ReconnectionManager");
    } catch (ClassNotFoundException ex) {
        // problem loading reconnection manager
    }
}
于 2012-12-24T13:37:14.223 回答
8

实际上重新连接管理器没有任何问题。首先,您需要将连接侦听器添加到连接管理器。

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

添加用于 ping 失败处理的侦听器以处理连接是否连接,因为 isConnected 方法对于检查连接状态不可靠。

pingManager.registerPingFailedListener(PingFailedListener);

对于移动网络连接是非常大的问题,因此您需要使用广播接收器检查移动设备的网络连接,并且在数据重新连接时,您可以使用 pingMyServer 方法检查连接是否处于活动状态,如果您从服务器收到 ping 回复,则表示连接处于活动状态否则在 ping 失败时,您可以手动重新连接。

于 2014-04-26T06:10:28.517 回答
3

这是我的代码适用于 ReconnectionManager

1)添加addConnectionListenerxmpp连接

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

2)如果连接关闭,则使用ReconnectionManager类自动重新连接

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

3)ConnectionListener用于重新连接、连接并在服务器上进行身份验证。如果与服务器成功连接身份验证,则还要注册PingManagerServerPingWithAlarmManager分类。

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();
     }
}
于 2017-12-02T07:51:48.557 回答
2

我有同样的问题,除了我的程序在服务器端 JVM 上运行。
我首先使用了 smack 4.0。然后我更新到 smack 4.1,但问题仍然存在。终于找到了一个配置模块:PingManager
使用这个后,出现这种情况的就是下拉。

    connection = new XMPPTCPConnection(config);     
    PingManager pingManager = PingManager.getInstanceFor(connection);
    pingManager.setPingInterval(300); // seconds
于 2015-07-20T06:41:18.870 回答
1

在 Smack 4.1 中,我使用ServerPingWithAlarmManager. 您可以在此处找到有关保持连接活跃ramzandroid 博客的更多详细信息。

于 2016-05-20T18:15:26.563 回答
0

对于这些情况,您需要手动处理断开连接,我的意思是您应该拦截任何断开连接,当您断开连接时通知连接侦听器。

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();
            }
        }
    }
于 2017-09-14T23:26:02.110 回答