У меня есть приложение Android, где я подключаюсь к серверу XMPP.Я создал связанную и запущенную службу, которая работает в своем собственном потоке и выполняет все подключения, отключения и т. Д.
Вот скелет службы:
public class XMPPConnectionService extends Service {
@Override
public void onCreate() {
super.onCreate();
...
}
public class XMPPConnectionServiceBinder extends Binder {
...
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
...
return START_STICKY;
}
private void initializeXMPPConnection() {
if (xmppConnection != null && isConnected && isAuthenticated)
return;
if(xmppConnection == null) {
System.out.println(TAG + " First time connnection to xmpp ");
try {
configurationBuilder = BOSHConfiguration.builder()
.setUsernameAndPassword(jabberId, proxyToken)
.setCustomSSLContext(getCustomSSLContext())
.setXmppDomain("mydomain")
.setFile("/http-bind/")
.setHost(Utility.getHostForChat())
.setPort(ServerConstants.PORT_FOR_CHAT)
.setResource("Smack")
.setSecurityMode(ConnectionConfiguration.SecurityMode.disabled)
.setUseHttps(true)
.setSendPresence(true)
.build();
} catch (XmppStringprepException xse) {
xse.printStackTrace();
Logger.logException(xse.getMessage(), xse);
}
xmppConnection = new XMPPBOSHConnection(configurationBuilder);
}
try {
System.out.println(TAG + " connecting to XMPP");
xmppConnection.connect();
xmppConnection.login();
} catch (SmackException | IOException | XMPPException | InterruptedException sixi) {
sixi.printStackTrace();
Logger.logException(sixi.getMessage(), sixi);
}
if(reconnectionManager== null)
reconnectionManager = ReconnectionManager.getInstanceFor(xmppConnection);
reconnectionManager.enableAutomaticReconnection();
if(offlineMessageManager == null)
offlineMessageManager = new OfflineMessageManager(xmppConnection);
isConnected = true;
isAuthenticated = true;
}
@Override
public void onDestroy() {
super.onDestroy();
Logger.logDebug(TAG, "Closing and destroying XMPP connection");
System.out.println("Closing xmpp connection.");
if(xmppConnection!=null){
reconnectionManager.disableAutomaticReconnection();
xmppConnection.disconnect();
isConnected = false;
isAuthenticated = false;
}
}
}
Услуга запускается через звонок на startService
и заканчивается при выходе из активности через звонок на stopService
.Все отлично работает, когда я вхожу в приложение в первый раз.Я могу общаться, проверять автономные сообщения и т. Д. Затем я перехожу к выходу из приложения, и это тоже работает, как и ожидалось.Код выхода вызывает stopService
, как показано ниже:
protected void logout() {
Intent stopXMPPConnectionService = new Intent(MyApplication.getAppContext(), XMPPConnectionService.class);
stopXMPPConnectionService.setAction(XMPPConnectionService.ACTION_XMPP_DISCONNECT);
stopService(stopXMPPConnectionService);
...
}
Это тоже хорошо работает.Я вижу из журналов метод onDestroy
вызываемой службы и сообщение XMPP
, отправляемое на сервер для установки статуса unavailable
.Я вижу следующие сообщения трассировки в logcat, когда пользователь выходит из приложения:
10-27 13:07:21.772 6922-6922/io.xxxxx.user I/System.out: Closing xmpp connection.
10-27 13:07:21.773 6922-6922/io.xxxxx.user D/SMACK: XMPPConnection closed (XMPPBOSHConnection[alphauser1\40xxxxx.io@inuka/Smack] (0))
10-27 13:07:21.951 6922-7269/io.inuka.user W/Roster: Roster not loaded while processing Presence Stanza [to=alphauser1\40xxxxx.io@inuka/Smack,from=alphauser1\40xxxxx.io@xxxxx/Smack,id=9V2W6-8,type=unavailable,]
Проблема возникает, когда я снова пытаюсь войти в приложение.Когда служба XMPP запускается снова посредством вызова метода startService
, я вижу следующую ошибку в logcat:
<code>10-27 13:10:54.881 6922-7349/io.xxxx.user I/System.out: io.xxxx.user.service.XMPPConnectionService First time connnection to xmpp
10-27 13:10:54.884 6922-7349/io.xxxx.user I/System.out: io.xxxx.user.service.XMPPConnectionService connecting to XMPP
10-27 13:10:54.887 6922-7349/io.xxxx.user I/BOSHClient: Starting with 1 request processors
10-27 13:10:55.555 6922-7352/io.xxxx.user D/SMACK: RECV (1): <body xmlns="http://jabber.org/protocol/httpbind" xmlns:stream="http://etherx.jabber.org/streams" from="xxxx" authid="5fpgkrm94h" sid="5fpgkrm94h" secure="true" requests="200" inactivity="600" polling="300" wait="60" hold="1" ack="4678127962453164" maxpause="300" ver="1.6"><stream:features><mechanisms xmlns="urn:ietf:params:xml:ns:xmpp-sasl"><mechanism>PLAIN</mechanism><mechanism>EXTERNAL</mechanism></mechanisms><register xmlns="http://jabber.org/features/iq-register"/><bind xmlns="urn:ietf:params:xml:ns:xmpp-bind"/><session xmlns="urn:ietf:params:xml:ns:xmpp-session"><optional/></session></stream:features></body>
10-27 13:10:56.357 6922-7352/io.xxxx.user D/SMACK: RECV (1): <body xmlns='http://jabber.org/protocol/httpbind' ack='4678127962453165'><success xmlns="urn:ietf:params:xml:ns:xmpp-sasl"/></body>
10-27 13:10:56.526 6922-7352/io.xxxx.user D/SMACK: RECV (1): <body xmlns="http://jabber.org/protocol/httpbind" xmlns:stream="http://etherx.jabber.org/streams"><stream:features><register xmlns="http://jabber.org/features/iq-register"/><bind xmlns="urn:ietf:params:xml:ns:xmpp-bind"/><session xmlns="urn:ietf:params:xml:ns:xmpp-session"><optional/></session></stream:features></body>
10-27 13:10:57.049 6922-7349/io.xxxx.user D/SMACK: User logged (1): alphauser1\40xxxx.io@xxxx:0/Smack
10-27 13:10:57.049 6922-7352/io.xxxx.user D/SMACK: RECV (1): <body xmlns='http://jabber.org/protocol/httpbind' ack='4678127962453167'><iq type="result" id="9V2W6-12" to="xxxx/5fpgkrm94h" xmlns="jabber:client"><bind xmlns="urn:ietf:params:xml:ns:xmpp-bind"><jid>alphauser1\40xxxx.io@xxxx/Smack</jid></bind></iq></body>
10-27 13:10:57.050 6922-7349/io.xxxx.user D/SMACK: XMPPConnection authenticated (XMPPBOSHConnection[alphauser1\40xxxx.io@xxxx/Smack] (1))
10-27 13:10:57.225 6922-7352/io.xxxx.user D/SMACK: RECV (1): <body xmlns='http://jabber.org/protocol/httpbind' ack='4678127962453168'><iq type="result" id="9V2W6-14" to="alphauser1\40xxxx.io@xxxx/Smack" xmlns="jabber:client"><query xmlns="jabber:iq:roster"/></iq></body>
10-27 13:10:57.326 6922-7076/io.xxxx.user W/AbstractXMPPConnection: Connection XMPPBOSHConnection[alphauser1\40xxxx.io@xxxx/Smack] (0) closed with error
org.igniterealtime.jbosh.BOSHException: Could not parse body:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=ISO-8859-1"/>
<title>Error 404 </title>
</head>
<body>
<h2>HTTP ERROR: 404</h2>
<p>Problem accessing /http-bind/. Reason:
<pre> Invalid SID value.
Работает на Jetty: // в org.igniterealtime.jbosh.BodyParserXmlPull.parse (BodyParserXmlPull.java:132) в org.igniterealtime.jbosh.StaticBody.fromString (StaticBody..processExchange (BOSHClient.java:1114) в org.igniterealtime.jbosh.BOSHClient.processMessages (BOSHClient.java:990) в org.igniterealtime.jbosh.BOSHClient.access $ 300 (BOSHClient.java:100realtimetime org).BOSHClient $ RequestProcessor.run (BOSHClient.java:1719) в java.lang.Thread.run (Thread.java:818) Причина: java.lang.IllegalStateException: корневой элемент не был 'body' в '
http://jabber.org/protocol/httpbind'Пространство имен.(Был 'html' в '') в org.igniterealtime.jbosh.BodyParserXmlPull.parse (BodyParserXmlPull.java:98) в org.igniterealtime.jbosh.StaticBody.fromString (StaticBody.java:114) в org.igniterealtime.jbosh.ApacheHTTPResponse.awaitResponse (ApacheHTTPResponse.java:241) в org.igniterealtime.jbosh.ApacheHTTPResponse.getBody (ApacheHTTPResponse.java:187) в org.igniterealtime.jbosh.BOS.Exj..BOSHClient.processMessages (BOSHClient.java:990) в org.igniterealtime.jbosh.BOSHClient.access $ 300 (BOSHClient.java:100) в org.igniterealtime.jbosh.BOSHClient $ RequestProcessor.run (BOSH: клиент) 19.lang.Thread.run (Thread.java:818) 10-27 13: 10: 57.326 6922-7076 / io.xxxx.user D / SMACK: XMPPConnection закрыто из-за исключения (XMPPBOSHConnection [alphauser1 \ 40xxxx.io@xxxx)/ Smack] (0)) org.igniterealtime.jbosh.BOSHException: Не удалось проанализировать тело: Ошибка 404
ОШИБКА HTTP: 404
Ошибка доступа к / http-bind /.Причина:
Invalid SID value.
Работает на Jetty: // в org.igniterealtime.jbosh.BodyParserXmlPull.parse (BodyParserXmlPull.java:132) в org.igniterealtime.jbosh.StaticBody.fromString (StaticBody..processExchange (BOSHClient.java:1114) в org.igniterealtime.jbosh.BOSHClient.processMessages (BOSHClient.java:990) в org.igniterealtime.jbosh.BOSHClient.access $ 300 (BOSHClient.java:100)в org.igniterealtime.jbosh.BOSHClient $ RequestProcessor.run (BOSHClient.java:1719)
на java.lang.Thread.run (Thread.java:818)
Причина: java.lang.IllegalStateException: Корневой элемент не был 'body' в пространстве имен '
http://jabber.org/protocol/httpbind'. (Был 'html' в '')
в org.igniterealtime.jbosh.BodyParserXmlPull.parse (BodyParserXmlPull.java:98)
в org.igniterealtime.jbosh.StaticBody.fromString (StaticBody.java:114)
в org.igniterealtime.jbosh.ApacheHTTPResponse.awaitResponse (ApacheHTTPResponse.java:241)
в org.igniterealtime.jbosh.ApacheHTTPResponse.getBody (ApacheHTTPResponse.java:187)
в org.igniterealtime.jbosh.BOSHClient.processExchange (BOSHClient.java:1114)
в org.igniterealtime.jbosh.BOSHClient.processMessages (BOSHClient.java:990)
в org.igniterealtime.jbosh.BOSHClient.access $ 300 (BOSHClient.java:100)
в org.igniterealtime.jbosh.BOSHClient $ RequestProcessor.run (BOSHClient.java:1719)
на java.lang.Thread.run (Thread.java:818)
10-27 13: 10: 57.389 6922-7206 / io.xxxx.user W / art: Нет идентификатора потока для приостановки: 231
10-27 13: 10: 57.418 6922-7245 / io.xxxx.user W / art: Нет идентификатора потока для приостановки: 264
10-27 13: 10: 59,225 1259-1326 /? D / hwcomposer: hw_composer отправил 555 синхронизаций за 60 с
Когда выдается ошибка, соединение устанавливается автоматически, но это вызывает задержку инициализации приложения. Код прекрасно работает при самом первом подключении, то есть когда приложение запускается в первый раз, или я убиваю приложение, используя «fore stop» из настроек системы Android. Но когда я выхожу и снова захожу, я получаю вышеуказанную ошибку.
У меня есть подозрение, что каким-то образом соединение не закрывается чисто - не уверен, как это сделать правильно.
Будем весьма благодарны за любые подсказки, советы, указатели.