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); + } +}