mirror of
https://github.com/cwinfo/envayasms.git
synced 2024-09-18 21:39:34 +00:00
keep backlogged outgoing messages in priority queue; allow server to set priority of outgoing messages; reschedule messages until the next time the android sending limit would not be exceeded
This commit is contained in:
parent
faffc6c568
commit
31085128eb
@ -1,8 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="org.envaya.sms"
|
||||
android:versionCode="10"
|
||||
android:versionName="2.0-beta8">
|
||||
android:versionCode="11"
|
||||
android:versionName="2.0-rc1">
|
||||
|
||||
<uses-sdk android:minSdkVersion="4" />
|
||||
|
||||
@ -68,6 +68,9 @@
|
||||
</receiver>
|
||||
-->
|
||||
|
||||
<receiver android:name=".receiver.DequeueOutgoingMessageReceiver">
|
||||
</receiver>
|
||||
|
||||
<receiver android:name=".receiver.OutgoingMessagePoller">
|
||||
</receiver>
|
||||
|
||||
|
@ -125,7 +125,8 @@ class EnvayaSMS_Request
|
||||
{
|
||||
$id = isset($message->id) ? " id=\"".EnvayaSMS::escape($message->id)."\"" : "";
|
||||
$to = isset($message->to) ? " to=\"".EnvayaSMS::escape($message->to)."\"" : "";
|
||||
echo "<sms$id$to>".EnvayaSMS::escape($message->message)."</sms>";
|
||||
$priority = isset($message->priority) ? " priority=\"".$message->priority."\"" : "";
|
||||
echo "<sms$id$to$priority>".EnvayaSMS::escape($message->message)."</sms>";
|
||||
}
|
||||
echo "</messages>";
|
||||
return ob_get_clean();
|
||||
@ -137,6 +138,7 @@ class EnvayaSMS_OutgoingMessage
|
||||
public $id; // ID generated by server
|
||||
public $to; // destination phone number
|
||||
public $message; // content of SMS message
|
||||
public $priority; // integer priority, higher numbers will be sent first
|
||||
}
|
||||
|
||||
class EnvayaSMS_Action
|
||||
|
@ -20,10 +20,12 @@ import android.text.SpannableStringBuilder;
|
||||
import android.util.Log;
|
||||
import java.text.DateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.PriorityQueue;
|
||||
import org.apache.http.client.HttpClient;
|
||||
import org.apache.http.conn.scheme.PlainSocketFactory;
|
||||
import org.apache.http.conn.scheme.Scheme;
|
||||
@ -36,6 +38,7 @@ import org.apache.http.params.BasicHttpParams;
|
||||
import org.apache.http.params.HttpConnectionParams;
|
||||
import org.apache.http.params.HttpParams;
|
||||
import org.apache.http.params.HttpProtocolParams;
|
||||
import org.envaya.sms.receiver.DequeueOutgoingMessageReceiver;
|
||||
import org.envaya.sms.receiver.OutgoingMessagePoller;
|
||||
import org.envaya.sms.task.HttpTask;
|
||||
import org.envaya.sms.task.PollerTask;
|
||||
@ -100,6 +103,27 @@ public final class App extends Application {
|
||||
private Map<Uri, IncomingMessage> incomingMessages = new HashMap<Uri, IncomingMessage>();
|
||||
private Map<Uri, OutgoingMessage> outgoingMessages = new HashMap<Uri, OutgoingMessage>();
|
||||
|
||||
private int numPendingOutgoingMessages = 0;
|
||||
private PriorityQueue<OutgoingMessage> outgoingQueue = new PriorityQueue<OutgoingMessage>(10,
|
||||
new Comparator<OutgoingMessage>() {
|
||||
public int compare(OutgoingMessage t1, OutgoingMessage t2)
|
||||
{
|
||||
int pri2 = t2.getPriority();
|
||||
int pri1 = t1.getPriority();
|
||||
|
||||
if (pri1 != pri2)
|
||||
{
|
||||
return pri2 - pri1;
|
||||
}
|
||||
|
||||
int order2 = t2.getLocalId();
|
||||
int order1 = t1.getLocalId();
|
||||
|
||||
return order1 - order2;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
private SharedPreferences settings;
|
||||
private MmsObserver mmsObserver;
|
||||
private SpannableStringBuilder displayedLog = new SpannableStringBuilder();
|
||||
@ -114,6 +138,8 @@ public final class App extends Application {
|
||||
// count to provide round-robin selection of expansion packs
|
||||
private int outgoingMessageCount = -1;
|
||||
|
||||
private long nextValidOutgoingTime;
|
||||
|
||||
// map of package name => sorted list of timestamps of outgoing messages
|
||||
private HashMap<String, ArrayList<Long>> outgoingTimestamps
|
||||
= new HashMap<String, ArrayList<Long>>();
|
||||
@ -187,8 +213,7 @@ public final class App extends Application {
|
||||
return packageInfo;
|
||||
}
|
||||
|
||||
|
||||
public synchronized String chooseOutgoingSmsPackage(int numParts)
|
||||
private synchronized String chooseOutgoingSmsPackage(int numParts)
|
||||
{
|
||||
outgoingMessageCount++;
|
||||
|
||||
@ -237,6 +262,48 @@ public final class App extends Application {
|
||||
return null;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the next time (in currentTimeMillis) that we can send an
|
||||
* outgoing SMS with numParts parts. Only valid immediately after
|
||||
* chooseOutgoingSmsPackage returns null.
|
||||
*/
|
||||
private synchronized long getNextValidOutgoingTime(int numParts)
|
||||
{
|
||||
long minTime = System.currentTimeMillis() + OUTGOING_SMS_CHECK_PERIOD;
|
||||
|
||||
for (String packageName : outgoingMessagePackages)
|
||||
{
|
||||
ArrayList<Long> timestamps = outgoingTimestamps.get(packageName);
|
||||
if (timestamps == null) // should never happen
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
int numTimestamps = timestamps.size();
|
||||
|
||||
// get 100th-to-last timestamp for 1 part msg,
|
||||
// 99th-to-last timestamp for 2 part msg, etc.
|
||||
|
||||
int timestampIndex = numTimestamps - 1 - OUTGOING_SMS_MAX_COUNT + numParts;
|
||||
|
||||
if (timestampIndex < 0 || timestampIndex >= numTimestamps)
|
||||
{
|
||||
// should never happen
|
||||
// (unless someone tries to send a 101-part SMS message)
|
||||
continue;
|
||||
}
|
||||
|
||||
long minTimeForPackage = timestamps.get(timestampIndex) + OUTGOING_SMS_CHECK_PERIOD;
|
||||
if (minTimeForPackage < minTime)
|
||||
{
|
||||
minTime = minTimeForPackage;
|
||||
}
|
||||
}
|
||||
|
||||
// return time immediately after limiting timestamp
|
||||
return minTime + 1;
|
||||
}
|
||||
|
||||
private synchronized void setExpansionPacks(List<String> packages)
|
||||
{
|
||||
int prevLimit = getOutgoingMessageLimit();
|
||||
@ -392,6 +459,9 @@ public final class App extends Application {
|
||||
}
|
||||
|
||||
public synchronized void retryStuckMessages() {
|
||||
|
||||
this.nextValidOutgoingTime = 0;
|
||||
|
||||
retryStuckOutgoingMessages();
|
||||
retryStuckIncomingMessages();
|
||||
}
|
||||
@ -402,17 +472,32 @@ public final class App extends Application {
|
||||
|
||||
public synchronized void retryStuckOutgoingMessages() {
|
||||
for (OutgoingMessage sms : outgoingMessages.values()) {
|
||||
sms.retryNow();
|
||||
|
||||
OutgoingMessage.ProcessingState state = sms.getProcessingState();
|
||||
|
||||
if (state != OutgoingMessage.ProcessingState.Queued
|
||||
&& state != OutgoingMessage.ProcessingState.Sending)
|
||||
{
|
||||
enqueueOutgoingMessage(sms);
|
||||
}
|
||||
}
|
||||
maybeDequeueOutgoingMessage();
|
||||
}
|
||||
|
||||
public synchronized void retryStuckIncomingMessages() {
|
||||
for (IncomingMessage sms : incomingMessages.values()) {
|
||||
sms.retryNow();
|
||||
IncomingMessage.ProcessingState state = sms.getProcessingState();
|
||||
if (state != IncomingMessage.ProcessingState.Forwarding)
|
||||
{
|
||||
enqueueIncomingMessage(sms);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void setIncomingMessageStatus(IncomingMessage message, boolean success) {
|
||||
|
||||
message.setProcessingState(IncomingMessage.ProcessingState.None);
|
||||
|
||||
Uri uri = message.getUri();
|
||||
if (success)
|
||||
{
|
||||
@ -428,9 +513,16 @@ public final class App extends Application {
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (!message.scheduleRetry())
|
||||
else
|
||||
{
|
||||
incomingMessages.remove(uri);
|
||||
if (message.scheduleRetry())
|
||||
{
|
||||
message.setProcessingState(IncomingMessage.ProcessingState.Scheduled);
|
||||
}
|
||||
else
|
||||
{
|
||||
incomingMessages.remove(uri);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -468,11 +560,16 @@ public final class App extends Application {
|
||||
break;
|
||||
}
|
||||
|
||||
sms.setProcessingState(OutgoingMessage.ProcessingState.None);
|
||||
|
||||
switch (resultCode) {
|
||||
case SmsManager.RESULT_ERROR_GENERIC_FAILURE:
|
||||
case SmsManager.RESULT_ERROR_RADIO_OFF:
|
||||
case SmsManager.RESULT_ERROR_NO_SERVICE:
|
||||
if (!sms.scheduleRetry()) {
|
||||
if (sms.scheduleRetry()) {
|
||||
sms.setProcessingState(OutgoingMessage.ProcessingState.Scheduled);
|
||||
}
|
||||
else {
|
||||
outgoingMessages.remove(uri);
|
||||
}
|
||||
break;
|
||||
@ -480,6 +577,9 @@ public final class App extends Application {
|
||||
outgoingMessages.remove(uri);
|
||||
break;
|
||||
}
|
||||
|
||||
numPendingOutgoingMessages--;
|
||||
maybeDequeueOutgoingMessage();
|
||||
}
|
||||
|
||||
public synchronized void sendOutgoingMessage(OutgoingMessage sms) {
|
||||
@ -487,7 +587,7 @@ public final class App extends Application {
|
||||
String to = sms.getTo();
|
||||
if (to == null || to.length() == 0)
|
||||
{
|
||||
log("Ignoring outgoing SMS; destination is empty");
|
||||
notifyStatus(sms, App.STATUS_FAILED, "Destination address is empty");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -495,8 +595,7 @@ public final class App extends Application {
|
||||
{
|
||||
// this is mostly to prevent accidentally sending real messages to
|
||||
// random people while testing...
|
||||
|
||||
log("Ignoring outgoing SMS to " + to);
|
||||
notifyStatus(sms, App.STATUS_FAILED, "Destination number is not in list of test senders");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -504,21 +603,91 @@ public final class App extends Application {
|
||||
|
||||
if (messageBody == null || messageBody.length() == 0)
|
||||
{
|
||||
log("Ignoring outgoing SMS; message body is empty");
|
||||
notifyStatus(sms, App.STATUS_FAILED, "Message body is empty");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
Uri uri = sms.getUri();
|
||||
if (outgoingMessages.containsKey(uri)) {
|
||||
log("Duplicate outgoing " + sms.getLogName() + ", skipping");
|
||||
debug("Duplicate outgoing " + sms.getLogName() + ", skipping");
|
||||
return;
|
||||
}
|
||||
|
||||
outgoingMessages.put(uri, sms);
|
||||
enqueueOutgoingMessage(sms);
|
||||
}
|
||||
|
||||
log("Sending " + sms.getLogName() + " to " + sms.getTo());
|
||||
sms.trySend();
|
||||
public synchronized void maybeDequeueOutgoingMessage()
|
||||
{
|
||||
long now = System.currentTimeMillis();
|
||||
if (nextValidOutgoingTime <= now && numPendingOutgoingMessages < 2)
|
||||
{
|
||||
OutgoingMessage sms = outgoingQueue.peek();
|
||||
|
||||
if (sms == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
SmsManager smgr = SmsManager.getDefault();
|
||||
ArrayList<String> bodyParts = smgr.divideMessage(sms.getMessageBody());
|
||||
|
||||
int numParts = bodyParts.size();
|
||||
|
||||
if (numParts > App.OUTGOING_SMS_MAX_COUNT)
|
||||
{
|
||||
outgoingQueue.poll();
|
||||
outgoingMessages.remove(sms.getUri());
|
||||
notifyStatus(sms, App.STATUS_FAILED, "Message has too many parts ("+(numParts)+")");
|
||||
return;
|
||||
}
|
||||
|
||||
String packageName = chooseOutgoingSmsPackage(numParts);
|
||||
|
||||
if (packageName == null)
|
||||
{
|
||||
nextValidOutgoingTime = getNextValidOutgoingTime(numParts);
|
||||
|
||||
if (nextValidOutgoingTime <= now) // should never happen
|
||||
{
|
||||
nextValidOutgoingTime = now + 2000;
|
||||
}
|
||||
|
||||
long diff = nextValidOutgoingTime - now;
|
||||
|
||||
log("Waiting for " + (diff/1000) + " seconds");
|
||||
|
||||
AlarmManager alarm = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
|
||||
|
||||
Intent intent = new Intent(this, DequeueOutgoingMessageReceiver.class);
|
||||
|
||||
PendingIntent pendingIntent = PendingIntent.getBroadcast(this,
|
||||
0,
|
||||
intent,
|
||||
0);
|
||||
|
||||
alarm.set(
|
||||
AlarmManager.RTC_WAKEUP,
|
||||
nextValidOutgoingTime,
|
||||
pendingIntent);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
outgoingQueue.poll();
|
||||
numPendingOutgoingMessages++;
|
||||
|
||||
sms.setProcessingState(OutgoingMessage.ProcessingState.Sending);
|
||||
|
||||
sms.trySend(bodyParts, packageName);
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void enqueueOutgoingMessage(OutgoingMessage sms)
|
||||
{
|
||||
outgoingQueue.add(sms);
|
||||
sms.setProcessingState(OutgoingMessage.ProcessingState.Queued);
|
||||
maybeDequeueOutgoingMessage();
|
||||
}
|
||||
|
||||
public synchronized void forwardToServer(IncomingMessage message) {
|
||||
@ -533,20 +702,26 @@ public final class App extends Application {
|
||||
|
||||
log("Received "+message.getDisplayType()+" from " + message.getFrom());
|
||||
|
||||
enqueueIncomingMessage(message);
|
||||
}
|
||||
|
||||
public synchronized void enqueueIncomingMessage(IncomingMessage message)
|
||||
{
|
||||
message.setProcessingState(IncomingMessage.ProcessingState.Forwarding);
|
||||
message.tryForwardToServer();
|
||||
}
|
||||
|
||||
public synchronized void retryIncomingMessage(Uri uri) {
|
||||
IncomingMessage message = incomingMessages.get(uri);
|
||||
if (message != null) {
|
||||
message.retryNow();
|
||||
enqueueIncomingMessage(message);
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void retryOutgoingMessage(Uri uri) {
|
||||
OutgoingMessage sms = outgoingMessages.get(uri);
|
||||
if (sms != null) {
|
||||
sms.retryNow();
|
||||
enqueueOutgoingMessage(sms);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -8,12 +8,32 @@ public abstract class IncomingMessage extends QueuedMessage {
|
||||
|
||||
protected String from;
|
||||
|
||||
private ProcessingState state = ProcessingState.None;
|
||||
|
||||
public enum ProcessingState
|
||||
{
|
||||
None, // not doing anything with this sms now... just sitting around
|
||||
Forwarding, // currently sending to server
|
||||
Scheduled // waiting for a while before retrying after failure forwarding
|
||||
}
|
||||
|
||||
public IncomingMessage(App app, String from)
|
||||
{
|
||||
super(app);
|
||||
this.from = from;
|
||||
}
|
||||
|
||||
public ProcessingState getProcessingState()
|
||||
{
|
||||
return state;
|
||||
}
|
||||
|
||||
public void setProcessingState(ProcessingState status)
|
||||
{
|
||||
this.state = status;
|
||||
}
|
||||
|
||||
|
||||
public abstract String getDisplayType();
|
||||
|
||||
public boolean isForwardable()
|
||||
@ -54,11 +74,6 @@ public abstract class IncomingMessage extends QueuedMessage {
|
||||
return from;
|
||||
}
|
||||
|
||||
public void retryNow() {
|
||||
app.log("Retrying forwarding message from " + from);
|
||||
tryForwardToServer();
|
||||
}
|
||||
|
||||
protected Intent getRetryIntent() {
|
||||
Intent intent = new Intent(app, IncomingMessageRetry.class);
|
||||
intent.setData(this.getUri());
|
||||
|
@ -78,7 +78,14 @@ public class IncomingMms extends IncomingMessage {
|
||||
|
||||
public void tryForwardToServer()
|
||||
{
|
||||
app.log("Forwarding MMS to server...");
|
||||
if (numRetries > 0)
|
||||
{
|
||||
app.log("Retrying forwarding MMS from " + from);
|
||||
}
|
||||
else
|
||||
{
|
||||
app.log("Forwarding MMS to server...");
|
||||
}
|
||||
|
||||
List<FormBodyPart> formParts = new ArrayList<FormBodyPart>();
|
||||
|
||||
|
@ -66,6 +66,11 @@ public class IncomingSms extends IncomingMessage {
|
||||
|
||||
public void tryForwardToServer() {
|
||||
|
||||
if (numRetries > 0)
|
||||
{
|
||||
app.log("Retrying forwarding SMS from " + from);
|
||||
}
|
||||
|
||||
new ForwarderTask(this,
|
||||
new BasicNameValuePair("from", getFrom()),
|
||||
new BasicNameValuePair("message_type", App.MESSAGE_TYPE_SMS),
|
||||
|
@ -4,8 +4,6 @@ package org.envaya.sms;
|
||||
import org.envaya.sms.receiver.OutgoingMessageRetry;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.telephony.SmsManager;
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class OutgoingMessage extends QueuedMessage {
|
||||
@ -14,16 +12,34 @@ public class OutgoingMessage extends QueuedMessage {
|
||||
private String message;
|
||||
private String from;
|
||||
private String to;
|
||||
|
||||
private String localId;
|
||||
private int priority;
|
||||
private int localId;
|
||||
private static int nextLocalId = 1;
|
||||
|
||||
private ProcessingState state = ProcessingState.None;
|
||||
|
||||
public enum ProcessingState
|
||||
{
|
||||
None, // not doing anything with this sms now... just sitting around
|
||||
Queued, // in the outgoing queue waiting to be sent
|
||||
Sending, // passed to an expansion pack, waiting for status notification
|
||||
Scheduled // waiting for a while before retrying after failure sending
|
||||
}
|
||||
|
||||
public OutgoingMessage(App app)
|
||||
{
|
||||
super(app);
|
||||
this.localId = "_o" + getNextLocalId();
|
||||
this.localId = getNextLocalId();
|
||||
}
|
||||
|
||||
public ProcessingState getProcessingState()
|
||||
{
|
||||
return state;
|
||||
}
|
||||
|
||||
public void setProcessingState(ProcessingState status)
|
||||
{
|
||||
this.state = status;
|
||||
}
|
||||
|
||||
static synchronized int getNextLocalId()
|
||||
@ -31,9 +47,15 @@ public class OutgoingMessage extends QueuedMessage {
|
||||
return nextLocalId++;
|
||||
}
|
||||
|
||||
public int getLocalId()
|
||||
{
|
||||
return localId;
|
||||
}
|
||||
|
||||
public Uri getUri()
|
||||
{
|
||||
return Uri.withAppendedPath(App.OUTGOING_URI, ((serverId == null) ? localId : serverId));
|
||||
return Uri.withAppendedPath(App.OUTGOING_URI, ((serverId == null) ?
|
||||
("_o" + localId) : serverId));
|
||||
}
|
||||
|
||||
public String getLogName()
|
||||
@ -81,15 +103,26 @@ public class OutgoingMessage extends QueuedMessage {
|
||||
this.to = to;
|
||||
}
|
||||
|
||||
public void retryNow() {
|
||||
app.log("Retrying sending " + getLogName() + " to " + getTo());
|
||||
trySend();
|
||||
public void setPriority(int priority)
|
||||
{
|
||||
this.priority = priority;
|
||||
}
|
||||
|
||||
public void trySend()
|
||||
public int getPriority()
|
||||
{
|
||||
SmsManager smgr = SmsManager.getDefault();
|
||||
ArrayList<String> bodyParts = smgr.divideMessage(getMessageBody());
|
||||
return priority;
|
||||
}
|
||||
|
||||
public void trySend(ArrayList<String> bodyParts, String packageName)
|
||||
{
|
||||
if (numRetries == 0)
|
||||
{
|
||||
app.log("Sending " + getLogName() + " to " + getTo());
|
||||
}
|
||||
else
|
||||
{
|
||||
app.log("Retrying sending " + getLogName() + " to " + getTo());
|
||||
}
|
||||
|
||||
int numParts = bodyParts.size();
|
||||
if (numParts > 1)
|
||||
@ -97,14 +130,6 @@ public class OutgoingMessage extends QueuedMessage {
|
||||
app.log("(Multipart message with "+numParts+" parts)");
|
||||
}
|
||||
|
||||
String packageName = app.chooseOutgoingSmsPackage(bodyParts.size());
|
||||
|
||||
if (packageName == null)
|
||||
{
|
||||
// todo... schedule retry
|
||||
return;
|
||||
}
|
||||
|
||||
Intent intent = new Intent(packageName + App.OUTGOING_SMS_INTENT_SUFFIX, this.getUri());
|
||||
intent.putExtra(App.OUTGOING_SMS_EXTRA_DELIVERY_REPORT, false);
|
||||
intent.putExtra(App.OUTGOING_SMS_EXTRA_TO, getTo());
|
||||
|
@ -66,7 +66,5 @@ public abstract class QueuedMessage
|
||||
|
||||
public abstract Uri getUri();
|
||||
|
||||
public abstract void retryNow();
|
||||
|
||||
protected abstract Intent getRetryIntent();
|
||||
}
|
||||
|
15
src/org/envaya/sms/receiver/DequeueOutgoingMessageReceiver.java
Executable file
15
src/org/envaya/sms/receiver/DequeueOutgoingMessageReceiver.java
Executable file
@ -0,0 +1,15 @@
|
||||
package org.envaya.sms.receiver;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import org.envaya.sms.App;
|
||||
|
||||
public class DequeueOutgoingMessageReceiver extends BroadcastReceiver {
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
App app = (App) context.getApplicationContext();
|
||||
app.maybeDequeueOutgoingMessage();
|
||||
}
|
||||
}
|
@ -198,6 +198,20 @@ public class HttpTask extends AsyncTask<String, Void, HttpResponse> {
|
||||
|
||||
sms.setServerId(serverId.equals("") ? null : serverId);
|
||||
|
||||
String priorityStr = smsElement.getAttribute("priority");
|
||||
|
||||
if (!priorityStr.equals(""))
|
||||
{
|
||||
try
|
||||
{
|
||||
sms.setPriority(Integer.parseInt(priorityStr));
|
||||
}
|
||||
catch (NumberFormatException ex)
|
||||
{
|
||||
app.log("Invalid message priority: " + priorityStr);
|
||||
}
|
||||
}
|
||||
|
||||
StringBuilder messageBody = new StringBuilder();
|
||||
NodeList childNodes = smsElement.getChildNodes();
|
||||
int numChildren = childNodes.getLength();
|
||||
|
Loading…
Reference in New Issue
Block a user