5
0
mirror of https://github.com/cwinfo/envayasms.git synced 2024-11-09 10:20:25 +00:00

automatic failover between wifi/mobile if server cannot be reached; send timestamp of incoming message to server

This commit is contained in:
Jesse Young 2011-09-29 16:02:37 -07:00
parent 31085128eb
commit 1081f57580
16 changed files with 350 additions and 39 deletions

View File

@ -1,11 +1,15 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.envaya.sms" package="org.envaya.sms"
android:versionCode="11" android:versionCode="12"
android:versionName="2.0-rc1"> android:versionName="2.0-rc2">
<uses-sdk android:minSdkVersion="4" /> <uses-sdk android:minSdkVersion="4" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.RECEIVE_SMS" /> <uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.RECEIVE_MMS" /> <uses-permission android:name="android.permission.RECEIVE_MMS" />
<uses-permission android:name="android.permission.SEND_SMS" /> <uses-permission android:name="android.permission.SEND_SMS" />
@ -80,6 +84,9 @@
<receiver android:name=".receiver.IncomingMessageRetry"> <receiver android:name=".receiver.IncomingMessageRetry">
</receiver> </receiver>
<receiver android:name=".receiver.ReenableWifiReceiver">
</receiver>
<receiver android:name=".receiver.BootReceiver"> <receiver android:name=".receiver.BootReceiver">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" /> <action android:name="android.intent.action.BOOT_COMPLETED" />
@ -95,6 +102,12 @@
</intent-filter> </intent-filter>
</receiver> </receiver>
<receiver android:name=".receiver.ConnectivityChangeReceiver" >
<intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
</intent-filter>
</receiver>
<service android:name=".CheckMmsInboxService"> <service android:name=".CheckMmsInboxService">
</service> </service>

View File

@ -54,6 +54,13 @@
> >
</ListPreference> </ListPreference>
<CheckBoxPreference
android:key="network_failover"
android:title="Network Failover"
android:summaryOff="Do nothing if phone can't connect to server via Wi-Fi"
android:summaryOn="Automatically switch to mobile data if phone can't connect to server via Wi-Fi"
></CheckBoxPreference>
<CheckBoxPreference <CheckBoxPreference
android:key="test_mode" android:key="test_mode"
android:title="Test mode" android:title="Test mode"

View File

@ -183,6 +183,7 @@ class EnvayaSMS_Action_Incoming extends EnvayaSMS_Action
public $message; // The message body of the SMS, or the content of the text/plain part of the MMS. public $message; // The message body of the SMS, or the content of the text/plain part of the MMS.
public $message_type; // EnvayaSMS::MESSAGE_TYPE_MMS or EnvayaSMS::MESSAGE_TYPE_SMS public $message_type; // EnvayaSMS::MESSAGE_TYPE_MMS or EnvayaSMS::MESSAGE_TYPE_SMS
public $mms_parts; // array of EnvayaSMS_MMS_Part instances public $mms_parts; // array of EnvayaSMS_MMS_Part instances
public $timestamp; // timestamp of incoming message (added in version 12)
function __construct($request) function __construct($request)
{ {
@ -191,6 +192,7 @@ class EnvayaSMS_Action_Incoming extends EnvayaSMS_Action
$this->from = $_POST['from']; $this->from = $_POST['from'];
$this->message = $_POST['message']; $this->message = $_POST['message'];
$this->message_type = $_POST['message_type']; $this->message_type = $_POST['message_type'];
$this->timestamp = @$_POST['timestamp'];
if ($this->message_type == EnvayaSMS::MESSAGE_TYPE_MMS) if ($this->message_type == EnvayaSMS::MESSAGE_TYPE_MMS)
{ {

View File

@ -10,7 +10,10 @@ import android.content.Intent;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.content.pm.PackageInfo; import android.content.pm.PackageInfo;
import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.PackageManager.NameNotFoundException;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.Uri; import android.net.Uri;
import android.net.wifi.WifiManager;
import android.os.Bundle; import android.os.Bundle;
import android.os.SystemClock; import android.os.SystemClock;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
@ -18,6 +21,8 @@ import android.telephony.SmsManager;
import android.text.Html; import android.text.Html;
import android.text.SpannableStringBuilder; import android.text.SpannableStringBuilder;
import android.util.Log; import android.util.Log;
import java.io.IOException;
import java.net.InetAddress;
import java.text.DateFormat; import java.text.DateFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Comparator; import java.util.Comparator;
@ -40,6 +45,7 @@ import org.apache.http.params.HttpParams;
import org.apache.http.params.HttpProtocolParams; import org.apache.http.params.HttpProtocolParams;
import org.envaya.sms.receiver.DequeueOutgoingMessageReceiver; import org.envaya.sms.receiver.DequeueOutgoingMessageReceiver;
import org.envaya.sms.receiver.OutgoingMessagePoller; import org.envaya.sms.receiver.OutgoingMessagePoller;
import org.envaya.sms.receiver.ReenableWifiReceiver;
import org.envaya.sms.task.HttpTask; import org.envaya.sms.task.HttpTask;
import org.envaya.sms.task.PollerTask; import org.envaya.sms.task.PollerTask;
import org.json.JSONArray; import org.json.JSONArray;
@ -94,11 +100,18 @@ public final class App extends Application {
public static final Uri INCOMING_URI = Uri.withAppendedPath(CONTENT_URI, "incoming"); public static final Uri INCOMING_URI = Uri.withAppendedPath(CONTENT_URI, "incoming");
public static final Uri OUTGOING_URI = Uri.withAppendedPath(CONTENT_URI, "outgoing"); public static final Uri OUTGOING_URI = Uri.withAppendedPath(CONTENT_URI, "outgoing");
// how long we disable wifi when there is no connection to the server
// (should be longer than CONNECTIVITY_FAILOVER_INTERVAL)
public static final int DISABLE_WIFI_INTERVAL = 3600000;
// how often we can automatically failover between wifi/mobile connection
public static final int CONNECTIVITY_FAILOVER_INTERVAL = 1800000;
// max per-app outgoing SMS rate used by com.android.internal.telephony.SMSDispatcher // max per-app outgoing SMS rate used by com.android.internal.telephony.SMSDispatcher
// with a slightly longer check period to account for variance in the time difference // with a slightly longer check period to account for variance in the time difference
// between when we prepare messages and when SMSDispatcher receives them // between when we prepare messages and when SMSDispatcher receives them
public static int OUTGOING_SMS_CHECK_PERIOD = 3605000; // one hour plus 5 sec (in ms) public static final int OUTGOING_SMS_CHECK_PERIOD = 3605000; // one hour plus 5 sec (in ms)
public static int OUTGOING_SMS_MAX_COUNT = 100; public static final int OUTGOING_SMS_MAX_COUNT = 100;
private Map<Uri, IncomingMessage> incomingMessages = new HashMap<Uri, IncomingMessage>(); private Map<Uri, IncomingMessage> incomingMessages = new HashMap<Uri, IncomingMessage>();
private Map<Uri, OutgoingMessage> outgoingMessages = new HashMap<Uri, OutgoingMessage>(); private Map<Uri, OutgoingMessage> outgoingMessages = new HashMap<Uri, OutgoingMessage>();
@ -417,6 +430,11 @@ public final class App extends Application {
return settings.getBoolean("enabled", false); return settings.getBoolean("enabled", false);
} }
public boolean isNetworkFailoverEnabled()
{
return settings.getBoolean("network_failover", false);
}
public boolean isTestMode() public boolean isTestMode()
{ {
return settings.getBoolean("test_mode", false); return settings.getBoolean("test_mode", false);
@ -713,14 +731,16 @@ public final class App extends Application {
public synchronized void retryIncomingMessage(Uri uri) { public synchronized void retryIncomingMessage(Uri uri) {
IncomingMessage message = incomingMessages.get(uri); IncomingMessage message = incomingMessages.get(uri);
if (message != null) { if (message != null
&& message.getProcessingState() == IncomingMessage.ProcessingState.Scheduled) {
enqueueIncomingMessage(message); enqueueIncomingMessage(message);
} }
} }
public synchronized void retryOutgoingMessage(Uri uri) { public synchronized void retryOutgoingMessage(Uri uri) {
OutgoingMessage sms = outgoingMessages.get(uri); OutgoingMessage sms = outgoingMessages.get(uri);
if (sms != null) { if (sms != null
&& sms.getProcessingState() == OutgoingMessage.ProcessingState.Scheduled) {
enqueueOutgoingMessage(sms); enqueueOutgoingMessage(sms);
} }
} }
@ -898,4 +918,189 @@ public final class App extends Application {
} }
return httpClient; return httpClient;
} }
private class ConnectivityCheckState
{
//private int networkType;
private long lastCheckTime; // when we checked connectivity on this network
public ConnectivityCheckState(int networkType)
{
//this.networkType = networkType;
}
public synchronized boolean canCheck()
{
long time = SystemClock.elapsedRealtime();
return (time - lastCheckTime >= App.CONNECTIVITY_FAILOVER_INTERVAL);
}
public void setChecked()
{
lastCheckTime = SystemClock.elapsedRealtime();
}
}
private Map<Integer,ConnectivityCheckState> connectivityCheckStates
= new HashMap<Integer, ConnectivityCheckState>();
private Thread connectivityThread;
/*
* Normally we rely on Android to automatically switch between
* mobile data and Wi-Fi, but if the phone is connected to a Wi-Fi router
* that doesn't have a connection to the internet, Android won't know
* the difference. So we if we can't actually reach the remote host via
* the current connection, we toggle the Wi-Fi radio so that Android
* will switch to the other connection.
*
* If the host is unreachable on both connections, we don't want to
* keep toggling the radio forever, so there is a timeout before we can
* recheck connectivity on a particular connection.
*
* When we disable the Wi-Fi radio, we set a timeout to reenable it after
* a while in hopes that connectivity will be restored.
*/
public synchronized void asyncCheckConnectivity()
{
ConnectivityManager cm =
(ConnectivityManager)getSystemService(CONNECTIVITY_SERVICE);
NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
if (activeNetwork == null || !activeNetwork.isConnected())
{
WifiManager wmgr = (WifiManager)getSystemService(Context.WIFI_SERVICE);
if (!wmgr.isWifiEnabled() && isNetworkFailoverEnabled())
{
wmgr.setWifiEnabled(true);
}
return;
}
final int networkType = activeNetwork.getType();
ConnectivityCheckState state =
connectivityCheckStates.get(networkType);
if (state == null)
{
state = new ConnectivityCheckState(networkType);
connectivityCheckStates.put(networkType, state);
}
if (!state.canCheck()
|| (connectivityThread != null && connectivityThread.isAlive()))
{
return;
}
state.setChecked();
connectivityThread = new Thread() {
@Override
public void run()
{
Uri serverUrl = Uri.parse(getServerUrl());
String hostName = serverUrl.getHost();
log("Checking connectivity to "+hostName+"...");
try
{
InetAddress addr = InetAddress.getByName(hostName);
if (addr.isReachable(App.HTTP_CONNECTION_TIMEOUT))
{
log("OK");
onConnectivityRestored();
return;
}
}
catch (IOException ex)
{
// just what we suspected...
// server not reachable on this interface
}
log("Can't connect to "+hostName+".");
WifiManager wmgr = (WifiManager)getSystemService(Context.WIFI_SERVICE);
if (!isNetworkFailoverEnabled())
{
log("Network failover disabled.");
}
else if (networkType == ConnectivityManager.TYPE_WIFI)
{
log("Switching from WIFI to MOBILE");
PendingIntent pendingIntent = PendingIntent.getBroadcast(App.this,
0,
new Intent(App.this, ReenableWifiReceiver.class),
0);
// set an alarm to try restoring Wi-Fi in a little while
AlarmManager alarm =
(AlarmManager)getSystemService(Context.ALARM_SERVICE);
alarm.set(
AlarmManager.ELAPSED_REALTIME_WAKEUP,
SystemClock.elapsedRealtime() + App.DISABLE_WIFI_INTERVAL,
pendingIntent);
wmgr.setWifiEnabled(false);
}
else if (networkType == ConnectivityManager.TYPE_MOBILE
&& !wmgr.isWifiEnabled())
{
log("Switching from MOBILE to WIFI");
wmgr.setWifiEnabled(true);
}
else
{
log("Can't automatically fix connectivity.");
}
}
};
connectivityThread.start();
}
private int activeNetworkType = -1;
public synchronized void onConnectivityChanged()
{
ConnectivityManager cm =
(ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = cm.getActiveNetworkInfo();
if (networkInfo == null || !networkInfo.isConnected())
{
return;
}
int networkType = networkInfo.getType();
if (networkType == activeNetworkType)
{
return;
}
activeNetworkType = networkType;
log("Connected to " + networkInfo.getTypeName());
asyncCheckConnectivity();
}
public void onConnectivityRestored()
{
retryStuckIncomingMessages();
if (getOutgoingPollSeconds() > 0)
{
checkOutgoingMessages();
}
// failed outgoing message status notifications are dropped...
}
} }

View File

@ -1,12 +1,12 @@
package org.envaya.sms; package org.envaya.sms;
import android.content.Intent; import android.content.Intent;
import android.net.Uri;
import org.envaya.sms.receiver.IncomingMessageRetry; import org.envaya.sms.receiver.IncomingMessageRetry;
public abstract class IncomingMessage extends QueuedMessage { public abstract class IncomingMessage extends QueuedMessage {
protected String from; protected String from;
protected long timestamp; // unix timestamp in milliseconds
private ProcessingState state = ProcessingState.None; private ProcessingState state = ProcessingState.None;
@ -17,10 +17,16 @@ public abstract class IncomingMessage extends QueuedMessage {
Scheduled // waiting for a while before retrying after failure forwarding Scheduled // waiting for a while before retrying after failure forwarding
} }
public IncomingMessage(App app, String from) public IncomingMessage(App app, String from, long timestamp)
{ {
super(app); super(app);
this.from = from; this.from = from;
this.timestamp = timestamp;
}
public long getTimestamp()
{
return timestamp;
} }
public ProcessingState getProcessingState() public ProcessingState getProcessingState()

View File

@ -19,9 +19,9 @@ public class IncomingMms extends IncomingMessage {
long id; long id;
String contentLocation; String contentLocation;
public IncomingMms(App app, String from, long id) public IncomingMms(App app, String from, long timestamp, long id)
{ {
super(app, from); super(app, from, timestamp);
this.parts = new ArrayList<MmsPart>(); this.parts = new ArrayList<MmsPart>();
this.id = id; this.id = id;
} }
@ -155,7 +155,6 @@ public class IncomingMms extends IncomingMessage {
} }
ForwarderTask task = new ForwarderTask(this, ForwarderTask task = new ForwarderTask(this,
new BasicNameValuePair("from", getFrom()),
new BasicNameValuePair("message", message), new BasicNameValuePair("message", message),
new BasicNameValuePair("message_type", App.MESSAGE_TYPE_MMS), new BasicNameValuePair("message_type", App.MESSAGE_TYPE_MMS),
new BasicNameValuePair("mms_parts", partsMetadata.toString()) new BasicNameValuePair("mms_parts", partsMetadata.toString())

View File

@ -12,11 +12,13 @@ import org.envaya.sms.task.ForwarderTask;
public class IncomingSms extends IncomingMessage { public class IncomingSms extends IncomingMessage {
protected String message; protected String message;
protected long timestampMillis;
// constructor for SMS retrieved from android.provider.Telephony.SMS_RECEIVED intent // constructor for SMS retrieved from android.provider.Telephony.SMS_RECEIVED intent
public IncomingSms(App app, List<SmsMessage> smsParts) throws InvalidParameterException { public IncomingSms(App app, List<SmsMessage> smsParts) throws InvalidParameterException {
super(app, smsParts.get(0).getOriginatingAddress()); super(app,
smsParts.get(0).getOriginatingAddress(),
smsParts.get(0).getTimestampMillis()
);
this.message = smsParts.get(0).getMessageBody(); this.message = smsParts.get(0).getMessageBody();
@ -34,15 +36,12 @@ public class IncomingSms extends IncomingMessage {
message = message + smsPart.getMessageBody(); message = message + smsPart.getMessageBody();
} }
this.timestampMillis = smsParts.get(0).getTimestampMillis();
} }
// constructor for SMS retrieved from Messaging inbox // constructor for SMS retrieved from Messaging inbox
public IncomingSms(App app, String from, String message, long timestampMillis) { public IncomingSms(App app, String from, String message, long timestampMillis) {
super(app, from); super(app, from, timestampMillis);
this.message = message; this.message = message;
this.timestampMillis = timestampMillis;
} }
public String getMessageBody() public String getMessageBody()
@ -60,7 +59,7 @@ public class IncomingSms extends IncomingMessage {
return Uri.withAppendedPath(App.INCOMING_URI, return Uri.withAppendedPath(App.INCOMING_URI,
"sms/" + "sms/" +
Uri.encode(from) + "/" Uri.encode(from) + "/"
+ timestampMillis + "/" + + timestamp + "/" +
Uri.encode(message)); Uri.encode(message));
} }
@ -72,7 +71,6 @@ public class IncomingSms extends IncomingMessage {
} }
new ForwarderTask(this, new ForwarderTask(this,
new BasicNameValuePair("from", getFrom()),
new BasicNameValuePair("message_type", App.MESSAGE_TYPE_SMS), new BasicNameValuePair("message_type", App.MESSAGE_TYPE_SMS),
new BasicNameValuePair("message", getMessageBody()) new BasicNameValuePair("message", getMessageBody())
).execute(); ).execute();

View File

@ -107,7 +107,7 @@ public class MmsUtils
String m_type = "" + MESSAGE_TYPE_RETRIEVE_CONF; String m_type = "" + MESSAGE_TYPE_RETRIEVE_CONF;
Cursor c = contentResolver.query(INBOX_URI, Cursor c = contentResolver.query(INBOX_URI,
new String[] {"_id", "ct_l"}, new String[] {"_id", "ct_l", "date"},
"m_type = ? ", new String[] { m_type }, null); "m_type = ? ", new String[] { m_type }, null);
List<IncomingMms> messages = new ArrayList<IncomingMms>(); List<IncomingMms> messages = new ArrayList<IncomingMms>();
@ -115,8 +115,13 @@ public class MmsUtils
while (c.moveToNext()) while (c.moveToNext())
{ {
long id = c.getLong(0); long id = c.getLong(0);
long date = c.getLong(2);
IncomingMms mms = new IncomingMms(app, getSenderNumber(id), id); IncomingMms mms = new IncomingMms(app,
getSenderNumber(id),
date * 1000, // MMS timestamp is in seconds for some reason,
// while everything else is in ms
id);
mms.setContentLocation(c.getString(1)); mms.setContentLocation(c.getString(1));

View File

@ -36,11 +36,11 @@ public abstract class QueuedMessage
int minute = second * 60; int minute = second * 60;
if (numRetries == 1) { if (numRetries == 1) {
app.log("1st failure; retry in 1 minute"); app.log("1st failure; retry in 20 seconds");
nextRetryTime = now + 1 * minute; nextRetryTime = now + 20 * second;
} else if (numRetries == 2) { } else if (numRetries == 2) {
app.log("2nd failure; retry in 10 minutes"); app.log("2nd failure; retry in 5 minutes");
nextRetryTime = now + 10 * minute; nextRetryTime = now + 5 * minute;
} else if (numRetries == 3) { } else if (numRetries == 3) {
app.log("3rd failure; retry in 1 hour"); app.log("3rd failure; retry in 1 hour");
nextRetryTime = now + 60 * minute; nextRetryTime = now + 60 * minute;

View File

@ -0,0 +1,24 @@
package org.envaya.sms.receiver;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import org.envaya.sms.App;
public class ConnectivityChangeReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
final App app = (App) context.getApplicationContext();
if (!app.isEnabled())
{
return;
}
app.onConnectivityChanged();
}
}

View File

@ -10,6 +10,12 @@ public class DequeueOutgoingMessageReceiver extends BroadcastReceiver {
@Override @Override
public void onReceive(Context context, Intent intent) { public void onReceive(Context context, Intent intent) {
App app = (App) context.getApplicationContext(); App app = (App) context.getApplicationContext();
if (!app.isEnabled())
{
return;
}
app.maybeDequeueOutgoingMessage(); app.maybeDequeueOutgoingMessage();
} }
} }

View File

@ -12,6 +12,11 @@ public class IncomingMessageRetry extends BroadcastReceiver
public void onReceive(Context context, Intent intent) public void onReceive(Context context, Intent intent)
{ {
App app = (App) context.getApplicationContext(); App app = (App) context.getApplicationContext();
if (!app.isEnabled())
{
return;
}
app.retryIncomingMessage(intent.getData()); app.retryIncomingMessage(intent.getData());
} }
} }

View File

@ -12,6 +12,10 @@ public class OutgoingMessageRetry extends BroadcastReceiver
public void onReceive(Context context, Intent intent) public void onReceive(Context context, Intent intent)
{ {
App app = (App) context.getApplicationContext(); App app = (App) context.getApplicationContext();
if (!app.isEnabled())
{
return;
}
app.retryOutgoingMessage(intent.getData()); app.retryOutgoingMessage(intent.getData());
} }
} }

View File

@ -0,0 +1,29 @@
package org.envaya.sms.receiver;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.net.wifi.WifiManager;
import org.envaya.sms.App;
public class ReenableWifiReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
App app = (App) context.getApplicationContext();
if (!app.isEnabled())
{
return;
}
WifiManager wmgr =
(WifiManager)app.getSystemService(Context.WIFI_SERVICE);
if (!wmgr.isWifiEnabled())
{
app.log("Reenabling Wi-Fi");
wmgr.setWifiEnabled(true);
}
}
}

View File

@ -8,18 +8,20 @@ import org.envaya.sms.OutgoingMessage;
public class ForwarderTask extends HttpTask { public class ForwarderTask extends HttpTask {
private IncomingMessage originalSms; private IncomingMessage message;
public ForwarderTask(IncomingMessage originalSms, BasicNameValuePair... paramsArr) { public ForwarderTask(IncomingMessage message, BasicNameValuePair... paramsArr) {
super(originalSms.app, paramsArr); super(message.app, paramsArr);
this.originalSms = originalSms; this.message = message;
params.add(new BasicNameValuePair("action", App.ACTION_INCOMING)); params.add(new BasicNameValuePair("action", App.ACTION_INCOMING));
params.add(new BasicNameValuePair("from", message.getFrom()));
params.add(new BasicNameValuePair("timestamp", "" + message.getTimestamp()));
} }
@Override @Override
protected String getDefaultToAddress() { protected String getDefaultToAddress() {
return originalSms.getFrom(); return message.getFrom();
} }
@Override @Override
@ -29,11 +31,11 @@ public class ForwarderTask extends HttpTask {
app.sendOutgoingMessage(reply); app.sendOutgoingMessage(reply);
} }
app.setIncomingMessageStatus(originalSms, true); app.setIncomingMessageStatus(message, true);
} }
@Override @Override
protected void handleFailure() { protected void handleFailure() {
app.setIncomingMessageStatus(originalSms, false); app.setIncomingMessageStatus(message, false);
} }
} }

View File

@ -8,6 +8,8 @@ import android.os.AsyncTask;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import java.security.MessageDigest; import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
@ -32,7 +34,6 @@ import org.envaya.sms.Base64Coder;
import org.envaya.sms.OutgoingMessage; import org.envaya.sms.OutgoingMessage;
import org.w3c.dom.Document; import org.w3c.dom.Document;
import org.w3c.dom.Element; import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList; import org.w3c.dom.NodeList;
import org.xml.sax.SAXException; import org.xml.sax.SAXException;
@ -159,6 +160,11 @@ public class HttpTask extends AsyncTask<String, Void, HttpResponse> {
{ {
post.abort(); post.abort();
app.logError("Error while contacting server", ex); app.logError("Error while contacting server", ex);
if (ex instanceof UnknownHostException || ex instanceof SocketTimeoutException)
{
app.asyncCheckConnectivity();
}
return null; return null;
} }
catch (Throwable ex) catch (Throwable ex)