我使用Android的asmack-android-7-beem库。我有一个后台服务正在运行,例如我的应用程序保持活动状态。但是,XMPP连接迟早会在没有任何通知的情况下死亡。服务器说客户端仍在线,但没有发送或接收数据包。
例如,当其他客户端有新的状态时,客户端不会收到任何状态数据包。我有XMPPConnection作为我的主要Application类的一个属性
在建立连接之前我设置了ConnectionConfiguration config.setReconnectionAllowed(true)
但重新连接不会发生。 XMPPConnection connection.isConnected()
返回true。
因此客户端不知道连接实际上已丢失。
有没有办法保持连接活着?
答案 0 :(得分:12)
当使用asmack时,在你的应用程序中添加这样的代码,使Dalvik加载ReconnectionManager类并运行它的静态初始化块:
static {
try {
Class.forName("org.jivesoftware.smack.ReconnectionManager");
} catch (ClassNotFoundException ex) {
// problem loading reconnection manager
}
}
答案 1 :(得分: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失败,您可以手动重新连接连接。
答案 2 :(得分:3)
这是我的代码适用于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 :(得分:2)
我有同样的问题,除了我的程序在服务器端JVM上运行
我首先使用了smack 4.0。然后我更新了1.4,但问题仍然发生。最后我找到了一个配置模块:PingManager
使用它之后,这种情况的发生就下降了。
connection = new XMPPTCPConnection(config);
PingManager pingManager = PingManager.getInstanceFor(connection);
pingManager.setPingInterval(300); // seconds
答案 4 :(得分:1)
在Smack 4.1中,我使用ServerPingWithAlarmManager
。您可以找到有关保持连接活动的更多详细信息ramzandroid blog here。
答案 5 :(得分: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();
}
}
}