web-dev-qa-db-ja.com

XMPP接続をAndroid(a)smackで)安定させる方法

私は、Android用のasmack-Android-7-beemライブラリを使用しています。アプリが動作し続けるなど、バックグラウンドサービスを実行しています。しかし、遅かれ早かれ、XMPP接続は予告なしに終了します。サーバーは、クライアントはまだオンラインですが、パケットの送受信は行われないと言います。

たとえば、他のクライアントに新しいプレゼンスがある場合、クライアントはプレゼンスパケットを受信しません。メインのApplicationクラスの属性としてXMPPConnectionを持っています。
接続が確立される前にConnectionConfiguration config.setReconnectionAllowed(true)を設定しました。
しかし、再接続は行われません。 XMPPConnection connection.isConnected()はtrueを返します。

そのため、クライアントは接続が実際に失われたことを認識していません。

接続を維持する方法はありますか?

26
Max

Asmackを使用する場合、DalvikにReconnectionManagerクラスをロードさせ、静的初期化ブロックを実行させるには、次のようなコードをアプリに追加します。

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

実はリコネクションマネージャーに問題はありません。まず、接続マネージャーに接続リスナーを追加する必要があります。

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

isConnectedメソッドは接続の状態をチェックするための信頼性がないため、接続が処理されたかどうかのping失敗処理用のリスナーを追加します。

pingManager.registerPingFailedListener(PingFailedListener);

モバイルネットワーク接続は非常に大きな問題であるため、ブロードキャストレシーバーを使用してモバイルのネットワーク接続を確認する必要があります。データの再接続時にpingMyServerメソッドを使用して、接続が有効かどうかを確認できます。サーバーからping応答を取得している場合は、接続が有効であることを意味しますそれ以外の場合、pingが失敗すると、接続を手動で再接続できます。

8
Mandeep

ReconnectionManagerでうまく機能する私のコードは次のとおりです

1)xmpp接続にaddConnectionListenerを追加します

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

2)接続が閉じられた場合、ReconnectionManagerクラスを使用して自動的に再接続します

 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();
     }
}
3
Sagar Jethva

私のプログラムがサーバー側のJVMで実行されることを除いて、同じ問題があります。
そもそもsmack 4.0を使用しました。その後、smack 4.1にアップデートしましたが、問題はまだ発生していました。最後に、構成モジュールを見つけました: PingManager
これを使用した後、この状況の発生はドロップダウンされました。

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

Smack 4.1ではServerPingWithAlarmManagerを使用しています。接続を維持する方法の詳細については ramzandroidブログはこちら をご覧ください。

1
taynguyen

これらの場合、切断を手動で処理する必要があります。つまり、切断をインターセプトする必要があります。切断が発生したときに接続リスナーに通知されます。

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