5
0
mirror of https://github.com/cwinfo/envayasms.git synced 2024-09-19 13:59:35 +00:00

refactor App to subclass Application; retain log messages in App class so they can be shown even if Main activity is inactive or gets reset

This commit is contained in:
Jesse Young 2011-09-15 15:45:44 -07:00
parent 0071efd297
commit e78598c919
15 changed files with 168 additions and 121 deletions

View File

@ -5,6 +5,8 @@
android:versionName="1.0"> android:versionName="1.0">
<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_WAP_PUSH" />
<uses-permission android:name="android.permission.SEND_SMS" /> <uses-permission android:name="android.permission.SEND_SMS" />
<uses-permission android:name="android.permission.READ_SMS" /> <uses-permission android:name="android.permission.READ_SMS" />
<uses-permission android:name="android.permission.WRITE_SMS" /> <uses-permission android:name="android.permission.WRITE_SMS" />
@ -12,7 +14,8 @@
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.INTERNET" />
<application android:icon="@drawable/icon" android:label="@string/app_name"> <application android:name="org.envaya.kalsms.App"
android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name=".Main" android:label="@string/app_name"> <activity android:name=".Main" android:label="@string/app_name">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN" /> <action android:name="android.intent.action.MAIN" />
@ -27,12 +30,19 @@
</activity> </activity>
<receiver android:name=".IncomingMessageForwarder"> <receiver android:name=".SMSReceiver">
<intent-filter android:priority="101"> <intent-filter android:priority="101">
<action android:name="android.provider.Telephony.SMS_RECEIVED" /> <action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter> </intent-filter>
</receiver> </receiver>
<receiver android:name=".MMSReceiver">
<intent-filter android:priority="101">
<action android:name="android.provider.Telephony.WAP_PUSH_RECEIVED" />
<data android:mimeType="application/vnd.wap.mms-message" />
</intent-filter>
</receiver>
<receiver android:name=".MessageStatusNotifier"> <receiver android:name=".MessageStatusNotifier">
</receiver> </receiver>

View File

@ -2,6 +2,7 @@ package org.envaya.kalsms;
import android.app.Activity; import android.app.Activity;
import android.app.AlarmManager; import android.app.AlarmManager;
import android.app.Application;
import android.app.PendingIntent; import android.app.PendingIntent;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
@ -9,12 +10,15 @@ import android.content.SharedPreferences;
import android.os.SystemClock; import android.os.SystemClock;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import android.telephony.SmsManager; import android.telephony.SmsManager;
import android.text.SpannableStringBuilder;
import android.util.Log; import android.util.Log;
import java.text.DateFormat;
import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import org.apache.http.message.BasicNameValuePair; 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_OUTGOING = "outgoing";
public static final String ACTION_INCOMING = "incoming"; public static final String ACTION_INCOMING = "incoming";
@ -24,24 +28,18 @@ public class App {
public static final String STATUS_SENT = "sent"; public static final String STATUS_SENT = "sent";
public static final String LOG_NAME = "KALSMS"; public static final String LOG_NAME = "KALSMS";
public static final String LOG_INTENT = "org.envaya.kalsms.LOG"; 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<String, IncomingMessage> incomingSmsMap = new HashMap<String, IncomingMessage>(); private Map<String, IncomingMessage> incomingSmsMap = new HashMap<String, IncomingMessage>();
private Map<String, OutgoingMessage> outgoingSmsMap = new HashMap<String, OutgoingMessage>(); private Map<String, OutgoingMessage> outgoingSmsMap = new HashMap<String, OutgoingMessage>();
public Context context; public SharedPreferences getSettings()
public SharedPreferences settings; {
return PreferenceManager.getDefaultSharedPreferences(this);
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 void checkOutgoingMessages() public void checkOutgoingMessages()
@ -56,11 +54,11 @@ public class App {
} }
public void setOutgoingMessageAlarm() { 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, 0,
new Intent(context, OutgoingMessagePoller.class), new Intent(this, OutgoingMessagePoller.class),
0); 0);
alarm.cancel(pendingIntent); alarm.cancel(pendingIntent);
@ -91,33 +89,33 @@ public class App {
} }
public String getServerUrl() { public String getServerUrl() {
return settings.getString("server_url", ""); return getSettings().getString("server_url", "");
} }
public String getPhoneNumber() { public String getPhoneNumber() {
return settings.getString("phone_number", ""); return getSettings().getString("phone_number", "");
} }
public int getOutgoingPollSeconds() { public int getOutgoingPollSeconds() {
return Integer.parseInt(settings.getString("outgoing_interval", "0")); return Integer.parseInt(getSettings().getString("outgoing_interval", "0"));
} }
public boolean getLaunchOnBoot() { public boolean getLaunchOnBoot() {
return settings.getBoolean("launch_on_boot", false); return getSettings().getBoolean("launch_on_boot", false);
} }
public boolean isEnabled() public boolean isEnabled()
{ {
return settings.getBoolean("enabled", false); return getSettings().getBoolean("enabled", false);
} }
public boolean getKeepInInbox() public boolean getKeepInInbox()
{ {
return settings.getBoolean("keep_in_inbox", false); return getSettings().getBoolean("keep_in_inbox", false);
} }
public String getPassword() { public String getPassword() {
return settings.getString("password", ""); return getSettings().getString("password", "");
} }
private void notifyStatus(OutgoingMessage sms, String status, String errorMessage) { private void notifyStatus(OutgoingMessage sms, String status, String errorMessage) {
@ -134,16 +132,16 @@ public class App {
String smsDesc = sms.getLogName(); String smsDesc = sms.getLogName();
if (serverId != null) { 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("id", serverId),
new BasicNameValuePair("status", status), new BasicNameValuePair("status", status),
new BasicNameValuePair("error", errorMessage), new BasicNameValuePair("error", errorMessage),
new BasicNameValuePair("action", App.ACTION_SEND_STATUS) new BasicNameValuePair("action", App.ACTION_SEND_STATUS)
).execute(); ).execute();
} else { } else {
app.log(smsDesc + " " + logMessage); log(smsDesc + " " + logMessage);
} }
} }
@ -245,7 +243,7 @@ public class App {
incomingSmsMap.put(id, sms); incomingSmsMap.put(id, sms);
app.log("Received SMS from " + sms.getFrom()); log("Received SMS from " + sms.getFrom());
sms.tryForwardToServer(); sms.tryForwardToServer();
} }
@ -264,16 +262,51 @@ public class App {
} }
} }
public void debug(String msg) { public void debug(String msg) {
Log.d(LOG_NAME, msg); Log.d(LOG_NAME, msg);
} }
public void log(String msg) { public void log(CharSequence msg)
Log.d(LOG_NAME, 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); Intent broadcast = new Intent(App.LOG_INTENT);
broadcast.putExtra("message", msg); sendBroadcast(broadcast);
context.sendBroadcast(broadcast); }
public CharSequence getDisplayedLog()
{
return displayedLog;
} }
public void logError(Throwable ex) { public void logError(Throwable ex) {

View File

@ -10,7 +10,7 @@ public class BootReceiver extends BroadcastReceiver {
@Override @Override
public void onReceive(Context context, Intent intent) public void onReceive(Context context, Intent intent)
{ {
App app = App.getInstance(context.getApplicationContext()); App app = (App)context.getApplicationContext();
if (!app.isEnabled()) if (!app.isEnabled())
{ {
return; return;

View File

@ -22,7 +22,7 @@ public class ForwardInbox extends ListActivity {
public void onCreate(Bundle icicle) { public void onCreate(Bundle icicle) {
super.onCreate(icicle); super.onCreate(icicle);
app = App.getInstance(getApplicationContext()); app = (App) getApplication();
setContentView(R.layout.inbox); setContentView(R.layout.inbox);

View File

@ -25,6 +25,15 @@ public class IncomingMessage extends QueuedMessage {
this.timestampMillis = timestampMillis; 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() public String getMessageBody()
{ {
return message; return message;
@ -54,7 +63,7 @@ public class IncomingMessage extends QueuedMessage {
protected Intent getRetryIntent() { 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())); intent.setData(Uri.parse("kalsms://incoming/" + this.getId()));
return intent; return intent;
} }

View File

@ -10,7 +10,7 @@ public class IncomingMessageRetry extends BroadcastReceiver
@Override @Override
public void onReceive(Context context, Intent intent) public void onReceive(Context context, Intent intent)
{ {
App app = App.getInstance(context.getApplicationContext()); App app = (App) context.getApplicationContext();
app.retryIncomingMessage(intent.getData().getLastPathSegment()); app.retryIncomingMessage(intent.getData().getLastPathSegment());
} }
} }

View File

@ -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");
}
}

View File

@ -15,8 +15,6 @@ import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.widget.ScrollView; import android.widget.ScrollView;
import android.widget.TextView; import android.widget.TextView;
import java.text.DateFormat;
import java.util.Date;
import org.apache.http.HttpResponse; import org.apache.http.HttpResponse;
import org.apache.http.message.BasicNameValuePair; import org.apache.http.message.BasicNameValuePair;
@ -27,7 +25,7 @@ public class Main extends Activity {
private BroadcastReceiver logReceiver = new BroadcastReceiver() { private BroadcastReceiver logReceiver = new BroadcastReceiver() {
@Override @Override
public void onReceive(Context context, Intent intent) { 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; private long lastLogTime = 0;
public void showLogMessage(String message) public void updateLogView()
{ {
TextView info = (TextView) Main.this.findViewById(R.id.info); final ScrollView scrollView = (ScrollView) this.findViewById(R.id.info_scroll);
if (message != null) TextView info = (TextView) this.findViewById(R.id.info);
{
int length = info.length();
int maxLength = 20000;
if (length > maxLength)
{
CharSequence text = info.getText();
int startPos = length - maxLength / 2; info.setText(app.getDisplayedLog());
for (int cur = startPos; cur < startPos + 100 && cur < length; cur++) scrollView.post(new Runnable() { public void run() {
{ scrollView.fullScroll(View.FOCUS_DOWN);
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);
} });
}
} }
/** Called when the activity is first created. */ /** Called when the activity is first created. */
@ -97,27 +62,31 @@ public class Main extends Activity {
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
this.app = App.getInstance(getApplicationContext()); app = (App) getApplication();
setContentView(R.layout.main); setContentView(R.layout.main);
PreferenceManager.setDefaultValues(this, R.xml.prefs, false); 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()); info.setMovementMethod(new ScrollingMovementMethod());
updateLogView();
IntentFilter logReceiverFilter = new IntentFilter(); IntentFilter logReceiverFilter = new IntentFilter();
logReceiverFilter.addAction(App.LOG_INTENT); logReceiverFilter.addAction(App.LOG_INTENT);
registerReceiver(logReceiver, logReceiverFilter); registerReceiver(logReceiver, logReceiverFilter);
info.append(Html.fromHtml( if (savedInstanceState == null)
app.isEnabled() ? "<b>SMS gateway running.</b><br />" : "<b>SMS gateway disabled.</b><br />")); {
app.log(Html.fromHtml(
app.isEnabled() ? "<b>SMS gateway running.</b>" : "<b>SMS gateway disabled.</b>"));
info.append("Server URL is: " + app.getDisplayString(app.getServerUrl()) + "\n"); app.log("Server URL is: " + app.getDisplayString(app.getServerUrl()));
info.append("Your phone number is: " + app.getDisplayString(app.getPhoneNumber()) + "\n"); app.log("Your phone number is: " + app.getDisplayString(app.getPhoneNumber()) );
info.append(Html.fromHtml("<b>Press Menu to edit settings.</b><br />")); app.log(Html.fromHtml("<b>Press Menu to edit settings.</b>"));
app.setOutgoingMessageAlarm(); app.setOutgoingMessageAlarm();
}
} }
@Override @Override
@ -166,10 +135,4 @@ public class Main extends Activity {
return true; return true;
} }
@Override
protected void onStop(){
// dont do much with this, atm..
super.onStop();
}
} }

View File

@ -13,8 +13,7 @@ public class MessageStatusNotifier extends BroadcastReceiver {
@Override @Override
public void onReceive(Context context, Intent intent) { public void onReceive(Context context, Intent intent) {
App app = App.getInstance(context.getApplicationContext()); App app = (App) context.getApplicationContext();
String id = intent.getData().getLastPathSegment(); String id = intent.getData().getLastPathSegment();
int resultCode = getResultCode(); int resultCode = getResultCode();

View File

@ -87,11 +87,11 @@ public class OutgoingMessage extends QueuedMessage {
{ {
SmsManager smgr = SmsManager.getDefault(); 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())); intent.setData(Uri.parse("kalsms://outgoing/" + getId()));
PendingIntent sentIntent = PendingIntent.getBroadcast( PendingIntent sentIntent = PendingIntent.getBroadcast(
app.context, app,
0, 0,
intent, intent,
PendingIntent.FLAG_ONE_SHOT); PendingIntent.FLAG_ONE_SHOT);
@ -100,7 +100,7 @@ public class OutgoingMessage extends QueuedMessage {
} }
protected Intent getRetryIntent() { 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())); intent.setData(Uri.parse("kalsms://outgoing/" + getId()));
return intent; return intent;
} }

View File

@ -8,7 +8,7 @@ public class OutgoingMessagePoller extends BroadcastReceiver {
@Override @Override
public void onReceive(Context context, Intent intent) { public void onReceive(Context context, Intent intent) {
App app = App.getInstance(context.getApplicationContext()); App app = (App) context.getApplicationContext();
app.checkOutgoingMessages(); app.checkOutgoingMessages();
} }
} }

View File

@ -10,7 +10,7 @@ public class OutgoingMessageRetry extends BroadcastReceiver
@Override @Override
public void onReceive(Context context, Intent intent) public void onReceive(Context context, Intent intent)
{ {
App app = App.getInstance(context.getApplicationContext()); App app = (App) context.getApplicationContext();
app.retryOutgoingMessage(intent.getData().getLastPathSegment()); app.retryOutgoingMessage(intent.getData().getLastPathSegment());
} }
} }

View File

@ -43,7 +43,8 @@ public class Prefs extends PreferenceActivity implements OnSharedPreferenceChang
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
App app = App.getInstance(this.getApplicationContext()); App app = (App) getApplication();
if (key.equals("outgoing_interval")) if (key.equals("outgoing_interval"))
{ {
app.setOutgoingMessageAlarm(); app.setOutgoingMessageAlarm();

View File

@ -48,9 +48,9 @@ public abstract class QueuedMessage
nextRetryTime = now + 24 * 60 * minute; 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, 0,
getRetryIntent(), getRetryIntent(),
0); 0);

View File

@ -9,14 +9,14 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
public class IncomingMessageForwarder extends BroadcastReceiver { public class SMSReceiver extends BroadcastReceiver {
private App app; private App app;
@Override @Override
// source: http://www.devx.com/wireless/Article/39495/1954 // source: http://www.devx.com/wireless/Article/39495/1954
public void onReceive(Context context, Intent intent) { public void onReceive(Context context, Intent intent) {
app = App.getInstance(context.getApplicationContext()); app = (App) context.getApplicationContext();
if (!app.isEnabled()) if (!app.isEnabled())
{ {
@ -28,11 +28,21 @@ public class IncomingMessageForwarder extends BroadcastReceiver {
if (action.equals("android.provider.Telephony.SMS_RECEIVED")) { if (action.equals("android.provider.Telephony.SMS_RECEIVED")) {
boolean hasUnhandledMessage = false;
for (IncomingMessage sms : getMessagesFromIntent(intent)) { 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(); this.abortBroadcast();
} }