【发布时间】:2014-10-09 20:08:38
【问题描述】:
我有一个连接到 XMPP 的应用程序。每 5 分钟我断开连接并重新连接(不要问,老板想要它......) - 到目前为止,我有一个 AsyncTask 在后台执行此操作,并且运行良好。然而,今天是一个不同的故事(请记住,代码已经有一段时间没有更改了!并且是通过 SVN 进行的 SC'd,我已经检查过自上次发布以来没有发生任何更改)。
今天它将在 5 分钟后断开连接并开始连接,但仅在重新启动后。任何后续尝试甚至都懒得尝试。
重新连接的runnable:
private final Runnable killConnection = new Runnable()
{
@Override
public void run()
{
synchronized(checkLock)
{
Log.d("BXC", "Killing connection and restarting");
// Manually disconnect and restart the connection every 5 minutes
destroyConnectionAndRestart();
new LoginTask().execute();
mHandler.postDelayed(this, mInterval5m);
}
}
};
还有 AsynTask 本身:
private class LoginTask extends AsyncTask<Void, Void, Void>
{
@Override
protected Void doInBackground(Void... params)
{
android.os.Debug.waitForDebugger();
String deviceUsername = Utility.getAndroidID(GaggleApplication.getInstance());
try
{
//bConnecting = true;
Log.d("BXC", "Beginning connection");
synchronized(connectLock)
{
// First ensure we've got a connection to work with first
if(Utility.hasActiveInternetConnection(getApplicationContext()) &&
((!bConnecting) && (!Globals.backgroundXmppConnectorRunning)))
{
String randomResource = Utility.randomString();
setupConnection();
if(xConnection != null)
{
xConnection.connect();
}
else
{
bConnecting = false;
Globals.backgroundXmppConnectorRunning = false;
setupConnection();
xConnection.connect();
}
/*
I know, I know... Don't specify a resource, but more often than not, OpenFire, doesn't
specify a unique resource, so at least this way, if we disconnect and then reconnect,
we're at least promised a resource that isn't being used already and leave OpenFire to
remove it's own idle connections, after X minutes.
*/
if(accountManager.supportsAccountCreation() && (!SystemProperties.getBoolean("accountCreated")))
{
Log.d("BXC", "Server supports registering custom user accounts");
accountManager.createAccount(deviceUsername, AppSettings.XMPP_KEYSTORE_PASSWORD);
SystemProperties.setBoolean("accountCreated", true);
}
xConnection.login(deviceUsername, AppSettings.XMPP_KEYSTORE_PASSWORD, randomResource);
ChatManager.getInstanceFor(xConnection).addChatListener(new ChatManagerListener(){
@Override
public void chatCreated(final Chat chat, boolean createdLocally)
{
if(!createdLocally)
{
// add chat listener //
chat.addMessageListener(new BackgroundMessageListener(BackgroundXmppConnector.this));
}
}
});
Presence p = new Presence(Presence.Type.subscribe);
p.setStatus("Out and About");
xConnection.sendPacket(p);
mBuilder.setSmallIcon(android.R.drawable.presence_online)
.setContentTitle("Connected")
.setContentText("Connected to XMPP server");
mNotificationManager.notify(mNotificationId, mBuilder.build());
Roster r = xConnection.getRoster();
r.setSubscriptionMode(SubscriptionMode.accept_all);
r.createEntry(AppSettings.BOT_NAME, "AbleBot", null);
r.addRosterListener(new RosterListener(){
@Override
public void entriesAdded(Collection<String> addresses)
{
for(String s : addresses)
{
Log.d("BXC", "Entries Added: " + s);
}
}
@Override
public void entriesDeleted(Collection<String> addresses)
{
for(String s : addresses)
{
Log.d("BXC", "Entries Deleted: " + s);
}
}
@Override
public void entriesUpdated(Collection<String> addresses)
{
for(String s : addresses)
{
Log.d("BXC", "Entries updated: " + s);
}
}
@Override
public void presenceChanged(Presence presence)
{
Log.d("BXC", "PresenceChanged: " + presence.getFrom());
}
});
}
else{
Log.i("BXC", "Already connected or in process of connecting. ");
}
}
}
catch(IllegalStateException ex)
{
Log.e("BXC", "IllegalStateException -->");
if(ex.getMessage().contains("Already logged in to server"))
{
Globals.backgroundXmppConnectorRunning = true;
}
else
{
Globals.backgroundXmppConnectorRunning = false;
Utility.writeExceptionToLog(getApplicationContext(), ex);
ex.printStackTrace();
}
}
catch(XMPPException ex)
{
Log.e("BXC", "XMPPException -->");
Globals.backgroundXmppConnectorRunning = false;
Utility.writeExceptionToLog(getApplicationContext(), ex);
ex.printStackTrace();
}
catch(NullPointerException ex)
{
Log.e("BXC", "NullPointerException -->");
Globals.backgroundXmppConnectorRunning = false;
Utility.writeExceptionToLog(getApplicationContext(), ex);
ex.printStackTrace();
}
catch(Exception ex)
{
Log.e("BXC", "Exception -->");
Globals.backgroundXmppConnectorRunning = false;
Utility.writeToLog(getApplicationContext(), ex.toString());
ex.printStackTrace();
}
return null;
}
@Override
protected void onPostExecute(Void ignored)
{
if(xConnection != null)
{
if(xConnection.isConnected() && (!xConnection.isSocketClosed()))
{
Log.i("BXC", "Logged in to XMPP Server");
Globals.backgroundXmppConnectorRunning = true;
ConnectionState cs = new ConnectionState(true);
GaggleApplication.getBusInstance().post(cs);
cs = null;
// SEND A WHOAMI TO UPDATE DEVICE FRIENDLY NAME //
WhoAmI wai = new WhoAmI();
Intent intent = new Intent(GaggleApplication.getInstance(), BackgroundXmppConnector.class);
intent.putExtra("MESSAGEDATA", new Gson().toJson(
Utility.makeTransaction(GaggleApplication.getInstance(), MessageType.Type.WHOAMI, wai)));
sendMessage(intent);
Log.i("MAIN", "Sent WHOAMI transaction");
mHandler.postDelayed(checkConnection, mInterval1m);
}
else
{
Log.e("BXC", "Unable to log into XMPP Server.");
Globals.backgroundXmppConnectorRunning = false;
destroyConnectionAndRestart();
}
}
else
{
Log.e("BXC", "Xmpp Connection object is null");
Globals.backgroundXmppConnectorRunning = false;
ConnectionState cs = new ConnectionState(false);
GaggleApplication.getBusInstance().post(cs);
cs = null;
}
}
}
我已经尝试在此 SO 帖子的帮助下进行调试:How do I use the Eclipse debugger in an AsyncTask when developing for Android? - 如上所述,任何后续尝试都不会触发 doInBackground - LogCat 也没有任何相关性,我有点失落。
如果有人以前遇到过这种情况,非常感谢任何帮助?
【问题讨论】:
-
需要一步步调试,确定挂在哪一行。最重要的是,您在某处有同步死锁,但不确定。
-
已经做到了。进入 AsyncTask 后,它立即离开。甚至不触及 doInBackground 和 onPostExecute。不过我会检查同步冲突。
-
默认情况下 AsyncTask 使用 SerialExecutor。如果之前的 AsyncTask.doInBackground 没有完成,它将不会开始第二次执行。你需要找出为什么第一次通话永远不会结束
-
我对 doInBackground 方法的调试也没有任何问题。不需要使用 android.os.Debug.waitForDebugger()
-
检查您最近是否添加了另一个 AsyncTasks,它在 doInBackground 中有长时间运行的操作。
标签: android eclipse android-asynctask