¿Cómo mantener estable una conexión XMPP en Android con(a) smack?
connection (6)
Aquí está mi código funciona bien para ReconnectionManager
1) Agregar addConnectionListener
en la conexión xmpp
XMPPConnectionListener mConnectionListener = new XMPPConnectionListener(username);
connection.addConnectionListener(mConnectionListener);
2) si la conexión está cerrada, vuelva a conectarse automáticamente utilizando la clase ReconnectionManager
ReconnectionManager reconnectionManager = ReconnectionManager.getInstanceFor(connection);
reconnectionManager.enableAutomaticReconnection();
reconnectionManager.setEnabledPerDefault(true);
3) ConnectionListener
para reconectarse, conectarse y autenticarse en el servidor. Si la conexión se autenticó correctamente con el servidor, también registre la clase PingManager
y 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();
}
}
Yo uso la biblioteca asmack-android-7-beem para Android. Tengo un servicio en segundo plano en ejecución, como mi aplicación se mantiene viva. Pero tarde o temprano la conexión XMPP muere sin previo aviso. El servidor dice que el cliente todavía está en línea pero no se envían ni reciben paquetes.
Por ejemplo, el cliente no recibe ningún paquete de presencia cuando otros clientes tienen una nueva presencia. Tengo XMPPConnection como un atributo de mi clase de aplicación principal.
Establecí ConnectionConfiguration config.setReconnectionAllowed(true)
antes de que se hiciera la conexión.
Pero la reconexión no ocurre. XMPPConnection connection.isConnected()
devuelve true.
Así que el cliente no es consciente de que la conexión está realmente perdida.
¿Hay alguna manera de mantener viva la conexión?
Cuando use asmack, coloque un código como este en su aplicación para hacer que Dalvik cargue la clase ReconnectionManager y ejecute su bloque de inicialización estática:
static {
try {
Class.forName("org.jivesoftware.smack.ReconnectionManager");
} catch (ClassNotFoundException ex) {
// problem loading reconnection manager
}
}
En Smack 4.1, uso ServerPingWithAlarmManager
. Puede encontrar más detalles sobre cómo mantener la conexión el blog ramzandroid vivo aquí .
En realidad no hay ningún problema con el administrador de reconexión. Primero debe agregar la escucha de conexión a su administrador de conexión.
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 se produce algún error, connectionClosedOnError (Exception arg0) se llamará automáticamente cuando se cierre la conexión
public void connectionClosed() {
Log.i("","XMPP connection was closed.");
//You can manually call reconnection code if you want to reconnect on any connection close
}
luego, verifique que se llame al método reconnectingin () e intente reconectarse.
Espero que esto te ayude.
use el siguiente código para verificar la conexión PingManager pingManager = PingManager.getInstanceFor(connection); pingManager.setPingInterval(5000);
PingManager pingManager = PingManager.getInstanceFor(connection); pingManager.setPingInterval(5000);
agregar listner para que el manejo de fallos de ping para manejar la conexión esté conectado o no porque el método isConnected no es confiable para verificar el estado de conexión.
pingManager.registerPingFailedListener(PingFailedListener);
Para la conectividad de la red móvil, el problema es muy grande, por lo que debe verificar la conectividad de la red con el receptor de difusión y en la reconexión de datos, puede usar el método pingMyServer para verificar si la conexión está activa o no. Si obtiene una respuesta de ping desde el servidor, significa que la conexión está activa. de lo contrario, en ping fall puede volver a conectar la conexión manualmente.
Para estos casos, necesita manejar la desconexión manualmente, me refiero a que debe interceptar cualquier desconexión, se le notifica al oyente de la conexión cuando tiene una desconexión.
public void connectionClosedOnError (excepción de excepción)
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();
}
}
}
Tengo el mismo problema, excepto que Mi programa se ejecuta en la JVM del lado del servidor.
Usé Smack 4.0 en primer lugar. Luego actualicé a la versión 4.1, pero el problema seguía ocurriendo. Finalmente encontré un módulo de configuración: PingManager
Después de usar esto, la ocurrencia de esta situación fue desplegable.
connection = new XMPPTCPConnection(config);
PingManager pingManager = PingManager.getInstanceFor(connection);
pingManager.setPingInterval(300); // seconds