mirror of
https://github.com/moparisthebest/Yaaic
synced 2024-11-25 10:22:16 -05:00
Fix auto-reconnect
The current auto-reconnection implementation will only try reconnecting once, immediately after the server is disconnected. This will of course almost always fail if the network is down or otherwise unavailable, so as it stands, enabling auto-reconnect isn't particularly useful. This patch implements multiple retries for auto-reconnect, with the frequency of retries controlled by a preference. The Android alarm infrastructure is used to schedule reconnection attempts; if the phone misses a scheduled attempt while it's asleep, the reconnection will be attempted the next time the phone wakes up.
This commit is contained in:
parent
e7651315df
commit
bce2523f98
@ -30,4 +30,20 @@
|
||||
<item>19</item>
|
||||
<item>20</item>
|
||||
</string-array>
|
||||
<string-array name="reconnect_interval_labels">
|
||||
<item>1 minute</item>
|
||||
<item>5 minutes</item>
|
||||
<item>10 minutes</item>
|
||||
<item>15 minutes</item>
|
||||
<item>20 minutes</item>
|
||||
<item>30 minutes</item>
|
||||
</string-array>
|
||||
<string-array name="reconnect_interval_values">
|
||||
<item>1</item>
|
||||
<item>5</item>
|
||||
<item>10</item>
|
||||
<item>15</item>
|
||||
<item>20</item>
|
||||
<item>30</item>
|
||||
</string-array>
|
||||
</resources>
|
||||
|
@ -18,6 +18,9 @@
|
||||
<string name="key_reconnect">reconnect</string>
|
||||
<string name="default_reconnect">false</string>
|
||||
|
||||
<string name="key_reconnect_interval">reconnect_interval</string>
|
||||
<string name="default_reconnect_interval">5</string>
|
||||
|
||||
<string name="key_quitmessage">quitmessage</string>
|
||||
<string name="default_quitmessage">Yaaic - Yet another Android IRC client - http://www.yaaic.org</string>
|
||||
|
||||
|
@ -176,6 +176,9 @@
|
||||
<string name="settings_connection">Connection</string>
|
||||
<string name="settings_reconnect_title">Reconnect</string>
|
||||
<string name="settings_reconnect_desc">Automatically reconnect on disconnect</string>
|
||||
<string name="settings_reconnect_interval_title">Reconnect interval</string>
|
||||
<string name="settings_reconnect_interval_desc">Number of minutes between reconnection tries</string>
|
||||
<string name="settings_reconnect_interval_dialog_title">Reconnect interval</string>
|
||||
|
||||
<string name="settings_chat">Chat</string>
|
||||
<string name="settings_icons_title">Show icons</string>
|
||||
|
@ -28,6 +28,15 @@ along with Yaaic. If not, see <http://www.gnu.org/licenses/>.
|
||||
android:summary="@string/settings_reconnect_desc"
|
||||
android:key="@string/key_reconnect"
|
||||
android:defaultValue="@string/default_reconnect" />
|
||||
<ListPreference
|
||||
android:title="@string/settings_reconnect_interval_title"
|
||||
android:summary="@string/settings_reconnect_interval_desc"
|
||||
android:dialogTitle="@string/settings_reconnect_interval_dialog_title"
|
||||
android:dependency="@string/key_reconnect"
|
||||
android:entries="@array/reconnect_interval_labels"
|
||||
android:entryValues="@array/reconnect_interval_values"
|
||||
android:key="@string/key_reconnect_interval"
|
||||
android:defaultValue="@string/default_reconnect_interval" />
|
||||
</PreferenceCategory>
|
||||
<PreferenceCategory
|
||||
android:title="@string/settings_chat">
|
||||
|
@ -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<Integer, PendingIntent> alarmIntents;
|
||||
private HashMap<Integer, ReconnectReceiver> 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<String>();
|
||||
this.mentions = new LinkedHashMap<String, Conversation>();
|
||||
this.alarmIntents = new HashMap<Integer, PendingIntent>();
|
||||
this.alarmReceivers = new HashMap<Integer, ReconnectReceiver>();
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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";
|
||||
|
@ -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
|
||||
*
|
||||
|
64
application/src/org/yaaic/receiver/ReconnectReceiver.java
Normal file
64
application/src/org/yaaic/receiver/ReconnectReceiver.java
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
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 <steven+android@steven676.net>
|
||||
*/
|
||||
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);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user