diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 7a1d88a..31cc376 100755
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -25,14 +25,16 @@
-
-
-
-
+
-
+
+
+
+
+
+
+
diff --git a/res/layout/add_test_phone_number.xml b/res/layout/add_test_phone_number.xml
new file mode 100755
index 0000000..8c2c8f8
--- /dev/null
+++ b/res/layout/add_test_phone_number.xml
@@ -0,0 +1,7 @@
+
+
+
\ No newline at end of file
diff --git a/res/layout/test_phone_number.xml b/res/layout/test_phone_number.xml
new file mode 100755
index 0000000..05e82c0
--- /dev/null
+++ b/res/layout/test_phone_number.xml
@@ -0,0 +1,9 @@
+
+
+
\ No newline at end of file
diff --git a/res/layout/test_phone_numbers.xml b/res/layout/test_phone_numbers.xml
new file mode 100755
index 0000000..2130614
--- /dev/null
+++ b/res/layout/test_phone_numbers.xml
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 3165203..b95d4d7 100755
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -1,10 +1,14 @@
- KalSMS 2
+ KalSMSSettingsTest ConnectionCheck MessagesHelpRetryFwd Inbox...
+ When running KalSMS in Test Mode,
+KalSMS will only forward SMS messages from the phone numbers
+listed below. (Incoming SMS messages from other phone numbers will be saved
+in the normal Messaging inbox, and outgoing messages will be ignored.)
diff --git a/res/xml/prefs.xml b/res/xml/prefs.xml
index dfa1ce6..c9da583 100755
--- a/res/xml/prefs.xml
+++ b/res/xml/prefs.xml
@@ -4,7 +4,7 @@
@@ -38,7 +40,7 @@
@@ -50,6 +52,25 @@
android:entries="@array/wifi_sleep_policies"
android:entryValues="@array/wifi_sleep_policies_values"
>
-
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/org/envaya/kalsms/App.java b/src/org/envaya/kalsms/App.java
index d3dfa2a..dbdebd8 100755
--- a/src/org/envaya/kalsms/App.java
+++ b/src/org/envaya/kalsms/App.java
@@ -18,6 +18,7 @@ import android.text.SpannableStringBuilder;
import android.util.Log;
import java.text.DateFormat;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
@@ -26,6 +27,8 @@ import org.apache.http.message.BasicNameValuePair;
import org.envaya.kalsms.receiver.OutgoingMessagePoller;
import org.envaya.kalsms.task.HttpTask;
import org.envaya.kalsms.task.PollerTask;
+import org.json.JSONArray;
+import org.json.JSONException;
public final class App extends Application {
@@ -107,6 +110,17 @@ public final class App extends Application {
log("Server URL is: " + getDisplayString(getServerUrl()));
log("Your phone number is: " + getDisplayString(getPhoneNumber()));
+ if (isTestMode())
+ {
+ log("Test mode is ON");
+ log("Test phone numbers:");
+
+ for (String sender : getTestPhoneNumbers())
+ {
+ log(" " + sender);
+ }
+ }
+
mmsObserver = new MmsObserver(this);
mmsObserver.register();
@@ -270,6 +284,11 @@ public final class App extends Application {
return settings.getBoolean("enabled", false);
}
+ public boolean isTestMode()
+ {
+ return settings.getBoolean("test_mode", false);
+ }
+
public boolean getKeepInInbox()
{
return settings.getBoolean("keep_in_inbox", false);
@@ -392,6 +411,16 @@ public final class App extends Application {
}
public synchronized void sendOutgoingMessage(OutgoingMessage sms) {
+
+ if (isTestMode() && !isTestPhoneNumber(sms.getTo()))
+ {
+ // this is mostly to prevent accidentally sending real messages to
+ // random people while testing...
+
+ log("Ignoring outgoing SMS to " + sms.getTo());
+ return;
+ }
+
Uri uri = sms.getUri();
if (outgoingMessages.containsKey(uri)) {
log("Duplicate outgoing " + sms.getLogName() + ", skipping");
@@ -506,4 +535,69 @@ public final class App extends Application {
{
return mmsUtils;
}
+
+ private List testPhoneNumbers;
+
+ public List getTestPhoneNumbers()
+ {
+ if (testPhoneNumbers == null)
+ {
+ testPhoneNumbers = new ArrayList();
+ String phoneNumbersJson = settings.getString("test_phone_numbers", "");
+
+ if (phoneNumbersJson.length() > 0)
+ {
+ try
+ {
+ JSONArray arr = new JSONArray(phoneNumbersJson);
+ int numSenders = arr.length();
+ for (int i = 0; i < numSenders; i++)
+ {
+ testPhoneNumbers.add(arr.getString(i));
+ }
+ }
+ catch (JSONException ex)
+ {
+ logError("Error parsing test phone numbers", ex);
+ }
+ }
+ }
+ return testPhoneNumbers;
+ }
+
+ public void addTestPhoneNumber(String phoneNumber)
+ {
+ List phoneNumbers = getTestPhoneNumbers();
+ log("Added test phone number: " + phoneNumber);
+ phoneNumbers.add(phoneNumber);
+ saveTestPhoneNumbers(phoneNumbers);
+ }
+
+ public void removeTestPhoneNumber(String phoneNumber)
+ {
+ List phoneNumbers = getTestPhoneNumbers();
+ phoneNumbers.remove(phoneNumber);
+ log("Removed test phone number: " + phoneNumber);
+ saveTestPhoneNumbers(phoneNumbers);
+ }
+
+ private void saveTestPhoneNumbers(List phoneNumbers)
+ {
+ settings.edit().putString("test_phone_numbers",
+ new JSONArray(phoneNumbers).toString()
+ ).commit();
+ }
+
+ public boolean isTestPhoneNumber(String phoneNumber)
+ {
+ for (String testNumber : getTestPhoneNumbers())
+ {
+ // handle inexactness due to various different ways of formatting numbers
+ if (testNumber.contains(phoneNumber) || phoneNumber.contains(testNumber))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
}
diff --git a/src/org/envaya/kalsms/IncomingMessage.java b/src/org/envaya/kalsms/IncomingMessage.java
index 85815c5..022a856 100755
--- a/src/org/envaya/kalsms/IncomingMessage.java
+++ b/src/org/envaya/kalsms/IncomingMessage.java
@@ -18,6 +18,11 @@ public abstract class IncomingMessage extends QueuedMessage {
public boolean isForwardable()
{
+ if (app.isTestMode() && !app.isTestPhoneNumber(from))
+ {
+ return false;
+ }
+
/*
* don't forward messages from shortcodes
* because they're likely to be spam or messages from network
diff --git a/src/org/envaya/kalsms/OutgoingMessage.java b/src/org/envaya/kalsms/OutgoingMessage.java
index 52d7d1a..e727be7 100755
--- a/src/org/envaya/kalsms/OutgoingMessage.java
+++ b/src/org/envaya/kalsms/OutgoingMessage.java
@@ -1,9 +1,6 @@
package org.envaya.kalsms;
-import android.app.Activity;
-import android.content.BroadcastReceiver;
-import android.content.Context;
import org.envaya.kalsms.receiver.OutgoingMessageRetry;
import android.content.Intent;
import android.net.Uri;
diff --git a/src/org/envaya/kalsms/receiver/SMSReceiver.java b/src/org/envaya/kalsms/receiver/SMSReceiver.java
index d95ba83..4a9a58b 100755
--- a/src/org/envaya/kalsms/receiver/SMSReceiver.java
+++ b/src/org/envaya/kalsms/receiver/SMSReceiver.java
@@ -27,31 +27,27 @@ public class SmsReceiver extends BroadcastReceiver {
}
try {
- String action = intent.getAction();
+ boolean hasUnhandledMessage = false;
- if (action.equals("android.provider.Telephony.SMS_RECEIVED")) {
-
- boolean hasUnhandledMessage = false;
-
- for (IncomingMessage sms : getMessagesFromIntent(intent)) {
-
- if (sms.isForwardable())
- {
- app.forwardToServer(sms);
- }
- else
- {
- hasUnhandledMessage = true;
- }
+ for (IncomingMessage sms : getMessagesFromIntent(intent)) {
+
+ if (sms.isForwardable())
+ {
+ app.forwardToServer(sms);
}
-
- if (!hasUnhandledMessage && !app.getKeepInInbox())
+ else
{
- this.abortBroadcast();
+ app.log("Ignoring incoming SMS from " + sms.getFrom());
+ hasUnhandledMessage = true;
}
}
+
+ if (!hasUnhandledMessage && !app.getKeepInInbox())
+ {
+ this.abortBroadcast();
+ }
} catch (Throwable ex) {
- app.logError("Unexpected error in IncomingMessageForwarder", ex, true);
+ app.logError("Unexpected error in SmsReceiver", ex, true);
}
}
diff --git a/src/org/envaya/kalsms/ui/Help.java b/src/org/envaya/kalsms/ui/Help.java
index 9f2da9a..6796db8 100755
--- a/src/org/envaya/kalsms/ui/Help.java
+++ b/src/org/envaya/kalsms/ui/Help.java
@@ -20,7 +20,7 @@ public class Help extends Activity {
String html = "KalSMS is a SMS gateway.
"
+ "It forwards all incoming SMS messages received by this phone to a server on the internet, "
+ "and also sends outgoing SMS messages from that server to other phones.
"
- + "(See https://kalsms.net for information about setting up a server.)
"
+ + "(See https://kalsms.net for more information.)
"
+ "The Settings screen allows you configure KalSMS to work with a particular server, "
+ "by entering the server URL, your phone number, "
+ "and the password assigned to your phone on the server.
"
diff --git a/src/org/envaya/kalsms/ui/Prefs.java b/src/org/envaya/kalsms/ui/Prefs.java
index ef3e8f5..0753f33 100755
--- a/src/org/envaya/kalsms/ui/Prefs.java
+++ b/src/org/envaya/kalsms/ui/Prefs.java
@@ -90,6 +90,10 @@ public class Prefs extends PreferenceActivity implements OnSharedPreferenceChang
{
app.log("Phone number changed to: " + app.getDisplayString(app.getPhoneNumber()));
}
+ else if (key.equals("test_mode"))
+ {
+ app.log("Test mode changed to: " + (app.isTestMode() ? "ON": "OFF"));
+ }
else if (key.equals("password"))
{
app.log("Password changed");
diff --git a/src/org/envaya/kalsms/ui/TestPhoneNumbers.java b/src/org/envaya/kalsms/ui/TestPhoneNumbers.java
new file mode 100755
index 0000000..87201dc
--- /dev/null
+++ b/src/org/envaya/kalsms/ui/TestPhoneNumbers.java
@@ -0,0 +1,107 @@
+package org.envaya.kalsms.ui;
+
+import android.app.AlertDialog;
+import android.app.ListActivity;
+import android.content.DialogInterface;
+import android.content.DialogInterface.OnClickListener;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.AdapterView;
+import android.widget.AdapterView.OnItemClickListener;
+import android.widget.ArrayAdapter;
+import android.widget.EditText;
+import android.widget.ListView;
+import android.widget.TextView;
+import org.envaya.kalsms.App;
+import org.envaya.kalsms.R;
+
+public class TestPhoneNumbers extends ListActivity {
+
+ private App app;
+
+ @Override
+ public void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+ setContentView(R.layout.test_phone_numbers);
+
+ app = (App)getApplication();
+
+ ListView lv = getListView();
+ lv.setOnItemClickListener(new OnItemClickListener() {
+ public void onItemClick(AdapterView> parent, View view,
+ int position, long id)
+ {
+ final String phoneNumber = ((TextView) view).getText().toString();
+
+ new AlertDialog.Builder(TestPhoneNumbers.this)
+ .setTitle("Remove Test Phone")
+ .setMessage("Do you want to remove "+phoneNumber
+ +" from the list of test phone numbers?")
+ .setPositiveButton("OK",
+ new OnClickListener() {
+ public void onClick(DialogInterface dialog, int which)
+ {
+ app.removeTestPhoneNumber(phoneNumber);
+ updateTestPhoneNumbers();
+ dialog.dismiss();
+ }
+ }
+ )
+ .setNegativeButton("Cancel",
+ new OnClickListener() {
+ public void onClick(DialogInterface dialog, int which)
+ {
+ dialog.dismiss();
+ }
+ }
+ )
+ .show();
+ }
+ });
+
+ updateTestPhoneNumbers();
+ }
+
+ public void updateTestPhoneNumbers()
+ {
+ String[] senders = app.getTestPhoneNumbers().toArray(new String[]{});
+
+ ArrayAdapter arrayAdapter = new ArrayAdapter(this,
+ R.layout.test_phone_number,
+ senders);
+
+ setListAdapter(arrayAdapter);
+ }
+
+ public void addTestSender(View v)
+ {
+ LayoutInflater factory = LayoutInflater.from(this);
+ final EditText textEntryView =
+ (EditText)factory.inflate(R.layout.add_test_phone_number, null);
+
+ new AlertDialog.Builder(this)
+ .setTitle("Add Test Phone")
+ .setMessage("Enter the phone number that you will be testing with:")
+ .setView(textEntryView)
+ .setPositiveButton("OK",
+ new OnClickListener() {
+ public void onClick(DialogInterface dialog, int which)
+ {
+ app.addTestPhoneNumber(textEntryView.getText().toString());
+ updateTestPhoneNumbers();
+ dialog.dismiss();
+ }
+ }
+ )
+ .setNegativeButton("Cancel",
+ new OnClickListener() {
+ public void onClick(DialogInterface dialog, int which)
+ {
+ dialog.dismiss();
+ }
+ }
+ )
+ .show();
+ }
+}