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:
parent
31085128eb
commit
1081f57580
@ -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>
|
||||||
|
|
||||||
|
@ -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"
|
||||||
|
@ -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)
|
||||||
{
|
{
|
||||||
|
@ -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...
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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()
|
||||||
|
@ -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())
|
||||||
|
@ -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();
|
||||||
|
@ -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));
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
24
src/org/envaya/sms/receiver/ConnectivityChangeReceiver.java
Executable file
24
src/org/envaya/sms/receiver/ConnectivityChangeReceiver.java
Executable 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();
|
||||||
|
}
|
||||||
|
}
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
29
src/org/envaya/sms/receiver/ReenableWifiReceiver.java
Executable file
29
src/org/envaya/sms/receiver/ReenableWifiReceiver.java
Executable 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
|
Loading…
Reference in New Issue
Block a user