diff --git a/AndroidManifest.xml b/AndroidManifest.xml index eca7b0a..961ac86 100755 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -5,6 +5,8 @@ android:versionName="1.0"> + + @@ -12,7 +14,8 @@ - + @@ -27,12 +30,19 @@ - + + + + + + + + diff --git a/src/org/envaya/kalsms/App.java b/src/org/envaya/kalsms/App.java index 23a3932..8b93f99 100755 --- a/src/org/envaya/kalsms/App.java +++ b/src/org/envaya/kalsms/App.java @@ -2,6 +2,7 @@ package org.envaya.kalsms; import android.app.Activity; import android.app.AlarmManager; +import android.app.Application; import android.app.PendingIntent; import android.content.Context; import android.content.Intent; @@ -9,13 +10,16 @@ import android.content.SharedPreferences; import android.os.SystemClock; import android.preference.PreferenceManager; import android.telephony.SmsManager; +import android.text.SpannableStringBuilder; import android.util.Log; +import java.text.DateFormat; +import java.util.Date; import java.util.HashMap; import java.util.Map; import org.apache.http.message.BasicNameValuePair; -public class App { - +public final class App extends Application { + public static final String ACTION_OUTGOING = "outgoing"; public static final String ACTION_INCOMING = "incoming"; public static final String ACTION_SEND_STATUS = "send_status"; @@ -24,24 +28,18 @@ public class App { public static final String STATUS_SENT = "sent"; public static final String LOG_NAME = "KALSMS"; public static final String LOG_INTENT = "org.envaya.kalsms.LOG"; - private static App app; + public static final int MAX_DISPLAYED_LOG = 15000; + public static final int LOG_TIMESTAMP_INTERVAL = 60000; + + private long lastLogTime = 0; + private SpannableStringBuilder displayedLog = new SpannableStringBuilder(); private Map incomingSmsMap = new HashMap(); private Map outgoingSmsMap = new HashMap(); - public Context context; - public SharedPreferences settings; - - protected App(Context context) { - this.context = context; - this.settings = PreferenceManager.getDefaultSharedPreferences(context); - } - - public static App getInstance(Context context) { - if (app == null) { - app = new App(context); - } - return app; + public SharedPreferences getSettings() + { + return PreferenceManager.getDefaultSharedPreferences(this); } public void checkOutgoingMessages() @@ -56,11 +54,11 @@ public class App { } public void setOutgoingMessageAlarm() { - AlarmManager alarm = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); + AlarmManager alarm = (AlarmManager) getSystemService(Context.ALARM_SERVICE); - PendingIntent pendingIntent = PendingIntent.getBroadcast(context, + PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, - new Intent(context, OutgoingMessagePoller.class), + new Intent(this, OutgoingMessagePoller.class), 0); alarm.cancel(pendingIntent); @@ -91,33 +89,33 @@ public class App { } public String getServerUrl() { - return settings.getString("server_url", ""); + return getSettings().getString("server_url", ""); } public String getPhoneNumber() { - return settings.getString("phone_number", ""); + return getSettings().getString("phone_number", ""); } public int getOutgoingPollSeconds() { - return Integer.parseInt(settings.getString("outgoing_interval", "0")); + return Integer.parseInt(getSettings().getString("outgoing_interval", "0")); } public boolean getLaunchOnBoot() { - return settings.getBoolean("launch_on_boot", false); + return getSettings().getBoolean("launch_on_boot", false); } public boolean isEnabled() { - return settings.getBoolean("enabled", false); + return getSettings().getBoolean("enabled", false); } public boolean getKeepInInbox() { - return settings.getBoolean("keep_in_inbox", false); + return getSettings().getBoolean("keep_in_inbox", false); } public String getPassword() { - return settings.getString("password", ""); + return getSettings().getString("password", ""); } private void notifyStatus(OutgoingMessage sms, String status, String errorMessage) { @@ -134,16 +132,16 @@ public class App { String smsDesc = sms.getLogName(); if (serverId != null) { - app.log("Notifying server " + smsDesc + " " + logMessage); + log("Notifying server " + smsDesc + " " + logMessage); - new HttpTask(app, + new HttpTask(this, new BasicNameValuePair("id", serverId), new BasicNameValuePair("status", status), new BasicNameValuePair("error", errorMessage), new BasicNameValuePair("action", App.ACTION_SEND_STATUS) ).execute(); } else { - app.log(smsDesc + " " + logMessage); + log(smsDesc + " " + logMessage); } } @@ -245,7 +243,7 @@ public class App { incomingSmsMap.put(id, sms); - app.log("Received SMS from " + sms.getFrom()); + log("Received SMS from " + sms.getFrom()); sms.tryForwardToServer(); } @@ -264,16 +262,51 @@ public class App { } } - public void debug(String msg) { + public void debug(String msg) { Log.d(LOG_NAME, msg); } - public void log(String msg) { - Log.d(LOG_NAME, msg); + public void log(CharSequence msg) + { + Log.d(LOG_NAME, msg.toString()); + + // prevent displayed log from growing too big + int length = displayedLog.length(); + if (length > MAX_DISPLAYED_LOG) + { + int startPos = length - MAX_DISPLAYED_LOG * 3 / 4; + + for (int cur = startPos; cur < startPos + 100 && cur < length; cur++) + { + if (displayedLog.charAt(cur) == '\n') + { + startPos = cur; + break; + } + } + displayedLog.replace(0, startPos, "[Older log messages not shown]\n"); + } + + // display a timestamp in the log occasionally + long logTime = SystemClock.elapsedRealtime(); + if (logTime - lastLogTime > LOG_TIMESTAMP_INTERVAL) + { + Date date = new Date(); + displayedLog.append("[" + DateFormat.getTimeInstance().format(date) + "]\n"); + lastLogTime = logTime; + } + + displayedLog.append(msg); + displayedLog.append("\n"); + Intent broadcast = new Intent(App.LOG_INTENT); - broadcast.putExtra("message", msg); - context.sendBroadcast(broadcast); + sendBroadcast(broadcast); + } + + public CharSequence getDisplayedLog() + { + return displayedLog; } public void logError(Throwable ex) { diff --git a/src/org/envaya/kalsms/BootReceiver.java b/src/org/envaya/kalsms/BootReceiver.java index bacf187..632f433 100755 --- a/src/org/envaya/kalsms/BootReceiver.java +++ b/src/org/envaya/kalsms/BootReceiver.java @@ -10,7 +10,7 @@ public class BootReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { - App app = App.getInstance(context.getApplicationContext()); + App app = (App)context.getApplicationContext(); if (!app.isEnabled()) { return; diff --git a/src/org/envaya/kalsms/ForwardInbox.java b/src/org/envaya/kalsms/ForwardInbox.java index 3167d16..83f2906 100755 --- a/src/org/envaya/kalsms/ForwardInbox.java +++ b/src/org/envaya/kalsms/ForwardInbox.java @@ -22,7 +22,7 @@ public class ForwardInbox extends ListActivity { public void onCreate(Bundle icicle) { super.onCreate(icicle); - app = App.getInstance(getApplicationContext()); + app = (App) getApplication(); setContentView(R.layout.inbox); diff --git a/src/org/envaya/kalsms/IncomingMessage.java b/src/org/envaya/kalsms/IncomingMessage.java index cb0c672..30ddf75 100755 --- a/src/org/envaya/kalsms/IncomingMessage.java +++ b/src/org/envaya/kalsms/IncomingMessage.java @@ -25,6 +25,15 @@ public class IncomingMessage extends QueuedMessage { this.timestampMillis = timestampMillis; } + public boolean isForwardable() + { + /* + * don't forward messages from shortcodes + * because they're likely to be spam or messages from network + */ + return from.length() > 5; + } + public String getMessageBody() { return message; @@ -54,7 +63,7 @@ public class IncomingMessage extends QueuedMessage { protected Intent getRetryIntent() { - Intent intent = new Intent(app.context, IncomingMessageRetry.class); + Intent intent = new Intent(app, IncomingMessageRetry.class); intent.setData(Uri.parse("kalsms://incoming/" + this.getId())); return intent; } diff --git a/src/org/envaya/kalsms/IncomingMessageRetry.java b/src/org/envaya/kalsms/IncomingMessageRetry.java index ac2f283..e6999a3 100755 --- a/src/org/envaya/kalsms/IncomingMessageRetry.java +++ b/src/org/envaya/kalsms/IncomingMessageRetry.java @@ -10,7 +10,7 @@ public class IncomingMessageRetry extends BroadcastReceiver @Override public void onReceive(Context context, Intent intent) { - App app = App.getInstance(context.getApplicationContext()); + App app = (App) context.getApplicationContext(); app.retryIncomingMessage(intent.getData().getLastPathSegment()); } } diff --git a/src/org/envaya/kalsms/MMSReceiver.java b/src/org/envaya/kalsms/MMSReceiver.java new file mode 100755 index 0000000..5069046 --- /dev/null +++ b/src/org/envaya/kalsms/MMSReceiver.java @@ -0,0 +1,22 @@ +package org.envaya.kalsms; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; + +public class MMSReceiver extends BroadcastReceiver { + + private App app; + + @Override + public void onReceive(Context context, Intent intent) { + app = (App) context.getApplicationContext(); + + if (!app.isEnabled()) + { + return; + } + + app.log("WAP Push received"); + } +} \ No newline at end of file diff --git a/src/org/envaya/kalsms/Main.java b/src/org/envaya/kalsms/Main.java index fc447b1..e7dc6a1 100755 --- a/src/org/envaya/kalsms/Main.java +++ b/src/org/envaya/kalsms/Main.java @@ -15,8 +15,6 @@ import android.view.MenuItem; import android.view.View; import android.widget.ScrollView; import android.widget.TextView; -import java.text.DateFormat; -import java.util.Date; import org.apache.http.HttpResponse; import org.apache.http.message.BasicNameValuePair; @@ -27,7 +25,7 @@ public class Main extends Activity { private BroadcastReceiver logReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { - showLogMessage(intent.getExtras().getString("message")); + updateLogView(); } }; @@ -47,49 +45,16 @@ public class Main extends Activity { private long lastLogTime = 0; - public void showLogMessage(String message) - { - TextView info = (TextView) Main.this.findViewById(R.id.info); - if (message != null) - { - int length = info.length(); - int maxLength = 20000; - if (length > maxLength) - { - CharSequence text = info.getText(); - - int startPos = length - maxLength / 2; - - for (int cur = startPos; cur < startPos + 100 && cur < length; cur++) - { - if (text.charAt(cur) == '\n') - { - startPos = cur; - break; - } - } - - CharSequence endSequence = text.subSequence(startPos, length); - - info.setText("[Older log messages not shown]"); - info.append(endSequence); - } - - long logTime = System.currentTimeMillis(); - if (logTime - lastLogTime > 60000) - { - Date date = new Date(logTime); - info.append("[" + DateFormat.getTimeInstance().format(date) + "]\n"); - lastLogTime = logTime; - } - - info.append(message + "\n"); - - final ScrollView scrollView = (ScrollView) this.findViewById(R.id.info_scroll); - scrollView.post(new Runnable() { public void run() { - scrollView.fullScroll(View.FOCUS_DOWN); - } }); - } + public void updateLogView() + { + final ScrollView scrollView = (ScrollView) this.findViewById(R.id.info_scroll); + TextView info = (TextView) this.findViewById(R.id.info); + + info.setText(app.getDisplayedLog()); + + scrollView.post(new Runnable() { public void run() { + scrollView.fullScroll(View.FOCUS_DOWN); + } }); } /** Called when the activity is first created. */ @@ -97,28 +62,32 @@ public class Main extends Activity { public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - this.app = App.getInstance(getApplicationContext()); + app = (App) getApplication(); setContentView(R.layout.main); PreferenceManager.setDefaultValues(this, R.xml.prefs, false); - - TextView info = (TextView) this.findViewById(R.id.info); - + + TextView info = (TextView) this.findViewById(R.id.info); info.setMovementMethod(new ScrollingMovementMethod()); + updateLogView(); + IntentFilter logReceiverFilter = new IntentFilter(); logReceiverFilter.addAction(App.LOG_INTENT); - registerReceiver(logReceiver, logReceiverFilter); + registerReceiver(logReceiver, logReceiverFilter); - info.append(Html.fromHtml( - app.isEnabled() ? "SMS gateway running.
" : "SMS gateway disabled.
")); - - info.append("Server URL is: " + app.getDisplayString(app.getServerUrl()) + "\n"); - info.append("Your phone number is: " + app.getDisplayString(app.getPhoneNumber()) + "\n"); - info.append(Html.fromHtml("Press Menu to edit settings.
")); + if (savedInstanceState == null) + { + app.log(Html.fromHtml( + app.isEnabled() ? "SMS gateway running." : "SMS gateway disabled.")); - app.setOutgoingMessageAlarm(); - } + app.log("Server URL is: " + app.getDisplayString(app.getServerUrl())); + app.log("Your phone number is: " + app.getDisplayString(app.getPhoneNumber()) ); + app.log(Html.fromHtml("Press Menu to edit settings.")); + + app.setOutgoingMessageAlarm(); + } + } @Override public boolean onOptionsItemSelected(MenuItem item) { @@ -165,11 +134,5 @@ public class Main extends Activity { item.setTitle("Retry Fwd (" + stuckMessages + ")"); return true; } - - @Override - protected void onStop(){ - // dont do much with this, atm.. - super.onStop(); - } } \ No newline at end of file diff --git a/src/org/envaya/kalsms/MessageStatusNotifier.java b/src/org/envaya/kalsms/MessageStatusNotifier.java index bc83101..3f67703 100755 --- a/src/org/envaya/kalsms/MessageStatusNotifier.java +++ b/src/org/envaya/kalsms/MessageStatusNotifier.java @@ -13,8 +13,7 @@ public class MessageStatusNotifier extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { - App app = App.getInstance(context.getApplicationContext()); - + App app = (App) context.getApplicationContext(); String id = intent.getData().getLastPathSegment(); int resultCode = getResultCode(); diff --git a/src/org/envaya/kalsms/OutgoingMessage.java b/src/org/envaya/kalsms/OutgoingMessage.java index 335eb95..092431a 100755 --- a/src/org/envaya/kalsms/OutgoingMessage.java +++ b/src/org/envaya/kalsms/OutgoingMessage.java @@ -87,11 +87,11 @@ public class OutgoingMessage extends QueuedMessage { { SmsManager smgr = SmsManager.getDefault(); - Intent intent = new Intent(app.context, MessageStatusNotifier.class); + Intent intent = new Intent(app, MessageStatusNotifier.class); intent.setData(Uri.parse("kalsms://outgoing/" + getId())); PendingIntent sentIntent = PendingIntent.getBroadcast( - app.context, + app, 0, intent, PendingIntent.FLAG_ONE_SHOT); @@ -100,7 +100,7 @@ public class OutgoingMessage extends QueuedMessage { } protected Intent getRetryIntent() { - Intent intent = new Intent(app.context, OutgoingMessageRetry.class); + Intent intent = new Intent(app, OutgoingMessageRetry.class); intent.setData(Uri.parse("kalsms://outgoing/" + getId())); return intent; } diff --git a/src/org/envaya/kalsms/OutgoingMessagePoller.java b/src/org/envaya/kalsms/OutgoingMessagePoller.java index 97af50e..9bdfcd0 100755 --- a/src/org/envaya/kalsms/OutgoingMessagePoller.java +++ b/src/org/envaya/kalsms/OutgoingMessagePoller.java @@ -8,7 +8,7 @@ public class OutgoingMessagePoller extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { - App app = App.getInstance(context.getApplicationContext()); + App app = (App) context.getApplicationContext(); app.checkOutgoingMessages(); } } diff --git a/src/org/envaya/kalsms/OutgoingMessageRetry.java b/src/org/envaya/kalsms/OutgoingMessageRetry.java index 8ed703b..388f2dc 100755 --- a/src/org/envaya/kalsms/OutgoingMessageRetry.java +++ b/src/org/envaya/kalsms/OutgoingMessageRetry.java @@ -10,7 +10,7 @@ public class OutgoingMessageRetry extends BroadcastReceiver @Override public void onReceive(Context context, Intent intent) { - App app = App.getInstance(context.getApplicationContext()); + App app = (App) context.getApplicationContext(); app.retryOutgoingMessage(intent.getData().getLastPathSegment()); } } diff --git a/src/org/envaya/kalsms/Prefs.java b/src/org/envaya/kalsms/Prefs.java index b46ff71..130c175 100755 --- a/src/org/envaya/kalsms/Prefs.java +++ b/src/org/envaya/kalsms/Prefs.java @@ -43,7 +43,8 @@ public class Prefs extends PreferenceActivity implements OnSharedPreferenceChang public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { - App app = App.getInstance(this.getApplicationContext()); + App app = (App) getApplication(); + if (key.equals("outgoing_interval")) { app.setOutgoingMessageAlarm(); diff --git a/src/org/envaya/kalsms/QueuedMessage.java b/src/org/envaya/kalsms/QueuedMessage.java index 7d887e8..1f02c96 100755 --- a/src/org/envaya/kalsms/QueuedMessage.java +++ b/src/org/envaya/kalsms/QueuedMessage.java @@ -48,9 +48,9 @@ public abstract class QueuedMessage nextRetryTime = now + 24 * 60 * minute; } - AlarmManager alarm = (AlarmManager) app.context.getSystemService(Context.ALARM_SERVICE); + AlarmManager alarm = (AlarmManager) app.getSystemService(Context.ALARM_SERVICE); - PendingIntent pendingIntent = PendingIntent.getBroadcast(app.context, + PendingIntent pendingIntent = PendingIntent.getBroadcast(app, 0, getRetryIntent(), 0); diff --git a/src/org/envaya/kalsms/IncomingMessageForwarder.java b/src/org/envaya/kalsms/SMSReceiver.java similarity index 74% rename from src/org/envaya/kalsms/IncomingMessageForwarder.java rename to src/org/envaya/kalsms/SMSReceiver.java index 85a44b0..9257fe6 100755 --- a/src/org/envaya/kalsms/IncomingMessageForwarder.java +++ b/src/org/envaya/kalsms/SMSReceiver.java @@ -9,14 +9,14 @@ import java.util.ArrayList; import java.util.List; -public class IncomingMessageForwarder extends BroadcastReceiver { +public class SMSReceiver extends BroadcastReceiver { private App app; @Override // source: http://www.devx.com/wireless/Article/39495/1954 public void onReceive(Context context, Intent intent) { - app = App.getInstance(context.getApplicationContext()); + app = (App) context.getApplicationContext(); if (!app.isEnabled()) { @@ -28,11 +28,21 @@ public class IncomingMessageForwarder extends BroadcastReceiver { if (action.equals("android.provider.Telephony.SMS_RECEIVED")) { + boolean hasUnhandledMessage = false; + for (IncomingMessage sms : getMessagesFromIntent(intent)) { - app.forwardToServer(sms); + + if (sms.isForwardable()) + { + app.forwardToServer(sms); + } + else + { + hasUnhandledMessage = true; + } } - if (!app.getKeepInInbox()) + if (!hasUnhandledMessage && !app.getKeepInInbox()) { this.abortBroadcast(); } @@ -48,7 +58,7 @@ public class IncomingMessageForwarder extends BroadcastReceiver { { Bundle bundle = intent.getExtras(); List messages = new ArrayList(); - + for (Object pdu : (Object[]) bundle.get("pdus")) { SmsMessage sms = SmsMessage.createFromPdu((byte[]) pdu);