单独线程中的 XMPP 连接 - 仍然被 Android 操作系统关闭?
Posted
技术标签:
【中文标题】单独线程中的 XMPP 连接 - 仍然被 Android 操作系统关闭?【英文标题】:XMPP Connection in seperate thread - Still gets closed by Android OS? 【发布时间】:2014-03-18 10:36:57 【问题描述】:我有一个包含许多服务的应用程序(企业的交付应用程序),它连接到 XMPP 服务器以发布报告。它主要是出色地工作。但是,在通过(1/3G)连接时,连接时间过长并且操作系统会终止应用程序。让我烦恼的是,连接是由警报管理器启动的服务产生的,我正在使用 androidConnectionConfiguration (aSmack lib),它显然产生了一个单独的线程来连接以摆脱 NetworkOnMainUIException。然而,每隔一段时间,我的应用程序仍然会收到一个 sigabrt 信号 6。为什么会发生这种情况?我没有在 UI 上或附近做任何事情,并认为无论时间如何,Android 都会让它不理会,直到它完成或自行超时?还是我错了?
我还能做些什么来阻止这种情况发生吗?我不在乎 XMPP 是否已连接,因为它总是会在有能力时重试并发送,但我不能让应用程序崩溃。
编辑 我应该说我使用的是 aSmack 0.8.10 - 和 Openfire 3.9.1。但它们不是问题并且工作得非常好。只有在奇怪的情况下,连接时间过长而被 Android 杀死。
编辑 2 一些代码:
package com.goosesys.dta_pta_test.Singletons;
import org.jivesoftware.smack.AndroidConnectionConfiguration;
import org.jivesoftware.smack.ChatManagerListener;
import org.jivesoftware.smack.ConnectionConfiguration.SecurityMode;
import org.jivesoftware.smack.Chat;
import org.jivesoftware.smack.ConnectionListener;
import org.jivesoftware.smack.SmackAndroid;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.packet.Message;
import android.content.Context;
import com.google.gson.Gson;
import com.goosesys.dta_pta_test.MessageListenerService;
import com.goosesys.gooselib.Logging;
import com.goosesys.gooselib.Utilities.AppSettings;
import com.goosesys.gooselib.Utilities.Utility;
public class XmppConnector
private static XmppConnector instance;
private static boolean isConnected = false;
private static AndroidConnectionConfiguration acc;
private static XMPPConnection xConnection;
private static Context context;
public static void init(Context contxt)
if(instance == null)
instance = new XmppConnector();
context = contxt;
public static XmppConnector getInstance()
return instance;
public static boolean connect() throws XMPPException
if(isConnected)
return true;
SmackAndroid.init(context);
acc = new AndroidConnectionConfiguration(AppSettings.XMPP_SERVER_HOST,
AppSettings.XMPP_SERVER_PORT, "Smack");
acc.setSecurityMode(SecurityMode.disabled);
xConnection = new XMPPConnection(acc);
xConnection.addConnectionListener(new ConnectionListener()
@Override
public void reconnectionSuccessful()
Logging.Debug("XmppConnector", "...reconnected to XMPP Server");
@Override
public void reconnectionFailed(Exception e)
Logging.Debug("XmppConnector", "...reconnection failed: " + e);
@Override
public void reconnectingIn(int seconds)
Logging.Debug("XmppConnector", "...reconnecting in: " + seconds);
@Override
public void connectionClosedOnError(Exception e)
Logging.Debug("XmppConnector", "...connection closed on error: " + e);
@Override
public void connectionClosed()
Logging.Debug("XmppConnector", "...connection closed");
);
xConnection.connect();
if(xConnection.isConnected())
isConnected = true;
// LOGIN ONCE CONNECTED TO THE SERVER //
xConnection.login(Utility.getAndroidID(context),
AppSettings.XMPP_KEYSTORE_PASSWORD);
// CREATE CHAT MANAGER //
xConnection.getChatManager().addChatListener(new ChatManagerListener()
@Override
public void chatCreated(final Chat chat, boolean createdLocally)
if(!createdLocally)
chat.addMessageListener(new MessageListenerService(context));
);
else
isConnected = false;
return isConnected;
public static boolean sendMessage(String jsonObj)
Message m = new Gson().fromJson(jsonObj, Message.class);
if(m == null)
Logging.Error("XmppConnector", "Message object is null.. Aborting");
return false;
if(isConnected)
xConnection.sendPacket(m);
return true;
else
return false;
以及启动它的小服务:
公共类 BGCollectorProc 扩展 IntentService 私有DatabaseHelper dbHelper;
public BGCollectorProc()
super("BGCollectorProc");
@Override
public int onStartCommand(Intent intent, int flags, int startId)
Logging.Debug("BGCollectorProc", "Spinning...");
//dbHelper = DatabaseHelper.getHelper(getApplicationContext());
try
// initialise the connection
XmppConnector.init(this);
// get the static reference
XmppConnector.getInstance();
// connect to the server
if(XmppConnector.connect())
Logging.Info("BGCollectorProc", "CONNECTED TO XMPP SERVER");
catch(XMPPException e)
e.printStackTrace();
/*
// Worker thread area //
try
postDeliveries();
catch (FileNotFoundException e)
// TODO Auto-generated catch block
e.printStackTrace();
postGeoLogs();
*/
return Service.START_NOT_STICKY;
干杯。
【问题讨论】:
这里真正有趣的是从 Android 日志中截取的相关内容。 Android 在需要时杀死进程。但是粘性服务会重新启动。 感谢我没有提供任何 logcat,但我之前得到的唯一输出是:libc - Fatal signal 6 (SIGABRT) at 0x000000149 (code=0), thread 24939 (ys. dta_pta_test) - 真的不认为这是相关的,因为它并没有太大的帮助。我的服务并不意味着一直旋转,所以它们设置为不粘,并通过 AlarmManager 每分钟重新启动一次。我现在想知道的是,我是否可以指定一个超时时间(略低于 Android 的 sigabrt 信号)来阻止应用程序被杀死? 【参考方案1】:SIGABRT
通常意味着 dalvik 内部发生了致命的事情。杀死您的进程的不是 Android ActivityManager。由于 VM 故障,VM 会自行终止。通常会有更多关于故障的信息。也许您没有识别出与SIGABRT
相关的日志。至少我希望在日志中找到有关SIGABRT
原因的更多信息。
顺便说一句:拥有活动 XMPPConnection 的服务是粘性 Android 服务的理想候选者,只要 XMPPConnection 处于活动状态,该服务就应该运行。
【讨论】:
以上是关于单独线程中的 XMPP 连接 - 仍然被 Android 操作系统关闭?的主要内容,如果未能解决你的问题,请参考以下文章