diff --git a/application/res/values/arrays.xml b/application/res/values/arrays.xml
index 1b81fcd..21db3e3 100644
--- a/application/res/values/arrays.xml
+++ b/application/res/values/arrays.xml
@@ -30,4 +30,20 @@
- 19
- 20
+
+ - 1 minute
+ - 5 minutes
+ - 10 minutes
+ - 15 minutes
+ - 20 minutes
+ - 30 minutes
+
+
+ - 1
+ - 5
+ - 10
+ - 15
+ - 20
+ - 30
+
diff --git a/application/res/values/settings.xml b/application/res/values/settings.xml
index 4bc3bb5..3c8ce33 100644
--- a/application/res/values/settings.xml
+++ b/application/res/values/settings.xml
@@ -18,6 +18,9 @@
reconnect
false
+ reconnect_interval
+ 5
+
quitmessage
Yaaic - Yet another Android IRC client - http://www.yaaic.org
diff --git a/application/res/values/strings.xml b/application/res/values/strings.xml
index 080c39a..74c3bb8 100644
--- a/application/res/values/strings.xml
+++ b/application/res/values/strings.xml
@@ -176,6 +176,9 @@
Connection
Reconnect
Automatically reconnect on disconnect
+ Reconnect interval
+ Number of minutes between reconnection tries
+ Reconnect interval
Chat
Show icons
diff --git a/application/res/xml/preferences.xml b/application/res/xml/preferences.xml
index 7101259..4adaf09 100644
--- a/application/res/xml/preferences.xml
+++ b/application/res/xml/preferences.xml
@@ -28,6 +28,15 @@ along with Yaaic. If not, see .
android:summary="@string/settings_reconnect_desc"
android:key="@string/key_reconnect"
android:defaultValue="@string/default_reconnect" />
+
diff --git a/application/src/org/yaaic/irc/IRCService.java b/application/src/org/yaaic/irc/IRCService.java
index ea0892c..e0c20ce 100644
--- a/application/src/org/yaaic/irc/IRCService.java
+++ b/application/src/org/yaaic/irc/IRCService.java
@@ -39,12 +39,16 @@ import org.yaaic.model.Server;
import org.yaaic.model.ServerInfo;
import org.yaaic.model.Settings;
import org.yaaic.model.Status;
+import org.yaaic.receiver.ReconnectReceiver;
+import android.app.AlarmManager;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.SystemClock;
/**
* The background service for managing the irc connections
@@ -81,6 +85,10 @@ public class IRCService extends Service
private Notification notification;
private Settings settings;
+ private HashMap alarmIntents;
+ private HashMap alarmReceivers;
+ private Object alarmIntentsLock;
+
/**
* Create new service
*/
@@ -92,6 +100,9 @@ public class IRCService extends Service
this.binder = new IRCBinder(this);
this.connectedServerTitles = new ArrayList();
this.mentions = new LinkedHashMap();
+ this.alarmIntents = new HashMap();
+ this.alarmReceivers = new HashMap();
+ this.alarmIntentsLock = new Object();
}
/**
@@ -383,11 +394,31 @@ public class IRCService extends Service
*/
public void connect(final Server server)
{
- new Thread() {
+ final int serverId = server.getId();
+ final int reconnectInterval = settings.getReconnectInterval()*60000;
+ final IRCService service = this;
+
+ if (settings.isReconnectEnabled()) {
+ server.setMayReconnect(true);
+ }
+
+ new Thread("Connect thread for " + server.getTitle()) {
@Override
public void run() {
+ synchronized(alarmIntentsLock) {
+ alarmIntents.remove(serverId);
+ ReconnectReceiver lastReceiver = alarmReceivers.remove(serverId);
+ if (lastReceiver != null) {
+ unregisterReceiver(lastReceiver);
+ }
+ }
+
+ if (settings.isReconnectEnabled() && !server.mayReconnect()) {
+ return;
+ }
+
try {
- IRCConnection connection = getConnection(server.getId());
+ IRCConnection connection = getConnection(serverId);
connection.setNickname(server.getIdentity().getNickname());
connection.setAliases(server.getIdentity().getAliases());
@@ -415,19 +446,33 @@ public class IRCService extends Service
catch (Exception e) {
server.setStatus(Status.DISCONNECTED);
- Intent sIntent = Broadcast.createServerIntent(Broadcast.SERVER_UPDATE, server.getId());
+ Intent sIntent = Broadcast.createServerIntent(Broadcast.SERVER_UPDATE, serverId);
sendBroadcast(sIntent);
- IRCConnection connection = getConnection(server.getId());
+ IRCConnection connection = getConnection(serverId);
Message message;
if (e instanceof NickAlreadyInUseException) {
message = new Message(getString(R.string.nickname_in_use, connection.getNick()));
+ server.setMayReconnect(false);
} else if (e instanceof IrcException) {
message = new Message(getString(R.string.irc_login_error, server.getHost(), server.getPort()));
+ server.setMayReconnect(false);
} else {
message = new Message(getString(R.string.could_not_connect, server.getHost(), server.getPort()));
+ if (settings.isReconnectEnabled()) {
+ Intent rIntent = new Intent(Broadcast.SERVER_RECONNECT + serverId);
+ PendingIntent pendingRIntent = PendingIntent.getBroadcast(service, 0, rIntent, 0);
+ AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);
+ ReconnectReceiver receiver = new ReconnectReceiver(service, server);
+ synchronized(alarmIntentsLock) {
+ alarmReceivers.put(serverId, receiver);
+ registerReceiver(receiver, new IntentFilter(Broadcast.SERVER_RECONNECT + serverId));
+ am.set(AlarmManager.ELAPSED_REALTIME, SystemClock.elapsedRealtime() + reconnectInterval, pendingRIntent);
+ alarmIntents.put(serverId, pendingRIntent);
+ }
+ }
}
message.setColor(Message.COLOR_RED);
@@ -436,7 +481,7 @@ public class IRCService extends Service
Intent cIntent = Broadcast.createConversationIntent(
Broadcast.CONVERSATION_MESSAGE,
- server.getId(),
+ serverId,
ServerInfo.DEFAULT_NAME
);
sendBroadcast(cIntent);
@@ -494,6 +539,20 @@ public class IRCService extends Service
}
connections.remove(serverId);
}
+
+ synchronized(alarmIntentsLock) {
+ PendingIntent pendingRIntent = alarmIntents.get(serverId);
+ if (pendingRIntent != null) {
+ AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);
+ am.cancel(pendingRIntent);
+ alarmIntents.remove(serverId);
+ }
+ ReconnectReceiver receiver = alarmReceivers.get(serverId);
+ if (receiver != null) {
+ unregisterReceiver(receiver);
+ alarmReceivers.remove(serverId);
+ }
+ }
} else {
shutDown = false;
}
@@ -516,6 +575,20 @@ public class IRCService extends Service
if (foreground) {
stopForegroundCompat(R.string.app_name);
}
+
+ AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);
+ synchronized(alarmIntentsLock) {
+ for (PendingIntent pendingRIntent : alarmIntents.values()) {
+ am.cancel(pendingRIntent);
+ }
+ for (ReconnectReceiver receiver : alarmReceivers.values()) {
+ unregisterReceiver(receiver);
+ }
+ alarmIntents.clear();
+ alarmIntents = null;
+ alarmReceivers.clear();
+ alarmReceivers = null;
+ }
}
/**
diff --git a/application/src/org/yaaic/model/Broadcast.java b/application/src/org/yaaic/model/Broadcast.java
index 97ca0fe..6049362 100644
--- a/application/src/org/yaaic/model/Broadcast.java
+++ b/application/src/org/yaaic/model/Broadcast.java
@@ -30,6 +30,7 @@ import android.content.Intent;
public abstract class Broadcast
{
public static final String SERVER_UPDATE = "org.yaaic.server.status";
+ public static final String SERVER_RECONNECT = "org.yaaic.server.reconnect.";
public static final String CONVERSATION_MESSAGE = "org.yaaic.conversation.message";
public static final String CONVERSATION_NEW = "org.yaaic.conversation.new";
diff --git a/application/src/org/yaaic/model/Settings.java b/application/src/org/yaaic/model/Settings.java
index 349d631..7cd3a1f 100644
--- a/application/src/org/yaaic/model/Settings.java
+++ b/application/src/org/yaaic/model/Settings.java
@@ -131,6 +131,19 @@ public class Settings
);
}
+ /**
+ * Get the reconnect interval
+ *
+ * @return The reconnect interval in minutes
+ */
+ public int getReconnectInterval()
+ {
+ return Integer.parseInt(preferences.getString(
+ resources.getString(R.string.key_reconnect_interval),
+ resources.getString(R.string.default_reconnect_interval)
+ ));
+ }
+
/**
* Get the quit message
*
diff --git a/application/src/org/yaaic/receiver/ReconnectReceiver.java b/application/src/org/yaaic/receiver/ReconnectReceiver.java
new file mode 100644
index 0000000..64b3c96
--- /dev/null
+++ b/application/src/org/yaaic/receiver/ReconnectReceiver.java
@@ -0,0 +1,64 @@
+/*
+Yaaic - Yet Another Android IRC Client
+
+Copyright 2009-2011 Sebastian Kaspari
+Copyright 2011 Steven Luo
+
+This file is part of Yaaic.
+
+Yaaic is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+Yaaic is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Yaaic. If not, see .
+ */
+package org.yaaic.receiver;
+
+import org.yaaic.irc.IRCService;
+import org.yaaic.model.Broadcast;
+import org.yaaic.model.Server;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+
+/**
+ * A receiver to listen for alarms and start a reconnect attempt
+ *
+ * @author Steven Luo
+ */
+public class ReconnectReceiver extends BroadcastReceiver
+{
+ private IRCService service;
+ private Server server;
+
+ /**
+ * Create a new reconnect receiver
+ *
+ * @param server The server to reconnect to
+ */
+ public ReconnectReceiver(IRCService service, Server server)
+ {
+ this.service = service;
+ this.server = server;
+ }
+
+ /**
+ * On receive broadcast
+ */
+ @Override
+ public void onReceive(Context context, Intent intent)
+ {
+ if (!intent.getAction().equals(Broadcast.SERVER_RECONNECT + server.getId())) {
+ return;
+ }
+ service.connect(server);
+ }
+}