简体   繁体   English

如何在Android上保持XMPP连接稳定(a)smack?

[英]How to keep a XMPP connection stable on Android with (a)smack?

I use asmack-android-7-beem library for Android. 我使用Android的asmack-android-7-beem库。 I have a background service running, such as my app stays alive. 我有一个后台服务正在运行,例如我的应用程序保持活动状态。 But sooner or later XMPP connection dies without any notice. 但是,XMPP连接迟早会在没有任何通知的情况下死亡。 The server says that the client is still online but no packets are sent or received. 服务器说客户端仍然在线,但没有发送或接收数据包。

For example the client doesn't receive any presence packets when other clients have a new presence. 例如,当其他客户端具有新的存在时,客户端不接收任何存在分组。 I have XMPPConnection as an attibute of my main Application class. 我有XMPPConnection作为我的主要Application类的一个属性。
I set ConnectionConfiguration config.setReconnectionAllowed(true) before the connection was made. 我在建立ConnectionConfiguration config.setReconnectionAllowed(true)之前设置了ConnectionConfiguration config.setReconnectionAllowed(true)
But reconnection doesn't happen. 但重新连接不会发生。 XMPPConnection connection.isConnected() returns true. XMPPConnection connection.isConnected()返回true。

So the client is not aware that connection is actually lost. 因此客户端不知道连接实际上已丢失。

Is there any way to keep the connection alive? 有没有办法保持连接活着?

When using asmack put some code like this in your app to make Dalvik load the ReconnectionManager class and run it's static initialization block: 当使用asmack时,在你的应用程序中添加这样的代码,使Dalvik加载ReconnectionManager类并运行它的静态初始化块:

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

Actually There is not any problem with Reconnection manager. 实际上重新连接管理器没有任何问题。 First you need to add connection listener to your connection manager. 首先,您需要将连接侦听器添加到连接管理器。

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

                    }
                }); 

if any error occurred the connectionClosedOnError(Exception arg0) will automatically called when connection is 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
                    }

then check it this will call reconnectingin() method and try to reconnect. 然后检查它会调用reconnectingin()方法并尝试重新连接。

Hope so this will help you. 希望这对你有所帮助。

use below code for check connection PingManager pingManager = PingManager.getInstanceFor(connection); pingManager.setPingInterval(5000); 使用下面的代码进行检查连接PingManager pingManager = PingManager.getInstanceFor(connection); pingManager.setPingInterval(5000); PingManager pingManager = PingManager.getInstanceFor(connection); pingManager.setPingInterval(5000);

add listner for ping fail handling to handle connection is connected or not because isConnected method is not reliable for check state of connection. 添加用于ping失败处理的列表器来处理连接是否已连接,因为isConnected方法对于检查连接状态是不可靠的。

pingManager.registerPingFailedListener(PingFailedListener);

For mobile network connectivity is very big problem so you need to check network connectivity for mobile using broadcast receiver and on data reconnection you can use pingMyServer method to check connection is alive or not, if you are getting ping reply from server, means connection is alive otherwise on ping fail you can reconnect connection manually. 对于移动网络连接是一个非常大的问题,因此您需要使用广播接收器检查移动设备的网络连接,并且在数据重新连接时您可以使用pingMyServer方法检查连接是否存在,如果您从服务器获得ping回复,则表示连接处于活动状态否则在ping失败时您可以手动重新连接连接。

Here's my code work fine for ReconnectionManager 这是我的代码适用于ReconnectionManager

1) Add addConnectionListener on xmpp connection 1)在xmpp连接上添加addConnectionListener

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

2) if connection closed then reconnect automatically using ReconnectionManager class 2)如果连接关闭,则使用ReconnectionManager类自动ReconnectionManager

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

3) ConnectionListener for reconnect, connect and authenticated on server. 3) ConnectionListener用于在服务器上重新连接,连接和验证。 if connection authenticated successfully with server also register PingManager and ServerPingWithAlarmManager class. 如果连接已成功通过服务器验证,则还会注册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();
     }
}

I have the same problem, except that My program run on server side JVM. 我有同样的问题,除了我的程序在服务器端JVM上运行。
I used smack 4.0 in the first place. 我首先使用了smack 4.0。 Then I updated to smack 4.1, but the problem still happened. 然后我更新了1.4,但问题仍然发生。 Finally I found a configuration module: PingManager 最后我找到了一个配置模块: PingManager
After using this, the occurrence of this situation was drop down. 使用它之后,这种情况的发生就下降了。

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

In Smack 4.1, I use ServerPingWithAlarmManager . 在Smack 4.1中,我使用ServerPingWithAlarmManager You can find more details about keeping connection alive ramzandroid blog here . 您可以在此处找到有关保持连接ramzandroid博客的更多详细信息。

For these case you need to handle the disconnection manually I mean you should intercept any disconnection, connection listener notified when you got a disconnection over. 对于这些情况,您需要手动处理断开连接我的意思是您应该拦截任何断开连接,断开连接时通知连接侦听器。

public void connectionClosedOnError(Exception exception) 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();
            }
        }
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM