I use asmack-android-7-beem library for Android. I have a background service running, such as my app stays alive. But sooner or later XMPP connection dies without any notice
Here's my code work fine for ReconnectionManager
1) Add addConnectionListener
on xmpp connection
XMPPConnectionListener mConnectionListener = new XMPPConnectionListener(username);
connection.addConnectionListener(mConnectionListener);
2) if connection closed then reconnect automatically using ReconnectionManager
class
ReconnectionManager reconnectionManager = ReconnectionManager.getInstanceFor(connection);
reconnectionManager.enableAutomaticReconnection();
reconnectionManager.setEnabledPerDefault(true);
3) ConnectionListener
for reconnect, connect and authenticated on server. if connection authenticated successfully with server also register PingManager
and ServerPingWithAlarmManager
class.
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();
}
}
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:
static {
try {
Class.forName("org.jivesoftware.smack.ReconnectionManager");
} catch (ClassNotFoundException ex) {
// problem loading reconnection manager
}
}
In Smack 4.1, I use ServerPingWithAlarmManager
. You can find more details about keeping connection alive ramzandroid blog here.
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
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.
Hope so this will help you.
use below code for check connection
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.
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.
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)
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();
}
}
}
I have the same problem, except that My program run on server side JVM.
I used smack 4.0 in the first place. Then I updated to smack 4.1, but the problem still happened. Finally I found a configuration module: 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