Android - Receiving Long Sms (Multipart)

Android - receiving long SMS (multipart)

It may be useful to look at how gTalkSMS handles incoming SMS'es, as it appears to handle multipart messages correctly.

Listen to incoming multipart SMS message

Holy...!

After reading the Android source (this file), I realize that this is such a stupid question...

Here is my receiver:

@Override
public void onReceive(Context context, Intent intent) {
Log.d(ClassName, "received SMS");

Bundle bundle = intent.getExtras();
if (bundle != null) {
Object[] pdus = (Object[]) bundle.get("pdus");
// here is what I need, just combine them all :-)
final SmsMessage[] messages = new SmsMessage[pdus.length];
Log.d(ClassName, String.format("message count = %s", messages.length));
for (int i = 0; i < pdus.length; i++) {
messages[i] = SmsMessage.createFromPdu((byte[]) pdus[i]);
}
}
}// onReceive()

Oops... I was too lazy to look at my code. I already got all parts of the message at a time.

Android - Sending Many multi-part Messages will miss some of them

I tried to follow and use Mike M's very insightful guidance and code to write an SMS message sending service that enqueues (large or small) messages and waits for each message to be completely sent before sending the next one. Most of the real work is done in the background.

SmsService.java is a gist on GitHub because it's a bit large to paste here.

One of my goals was to see if I could put the necessary functionality into one single android component. It's been tested with small numbers of messages but it's still experimental. (e.g. it avoids using a BroadcastReceiver, relies on the uniqueness of Service startIds sent in by the system, heavily relies on intents to represent messages, etc.)

The class has three static methods for setting it up, sending messages, and tearing it down:

@Override
protected void onCreate(Bundle savedInstanceState) {
...
SmsService.setup(this);
}

private void sendMyMessages() {
SmsService.send(this, recipient, sender, "the message text");
}

@Override
protected void onDestroy() {
SmsService.teardown(this);
...
}

Sending long sms messages

seems to me that the first option is what most mobile phones do by default. sms messages by design can only send a certain amount of characters (160 probbaly), just inform the user that the message is too big and if he still wants to send it anyway (informing also how many sms would the total be).

as for MMS and multipart as you said not every carrier supports it, so they dont seem to be the best option.

EDIT: as for how does MMS work on android-sdk check this thread out: Android SDK MMS

How to check for successful Multi-part sms send

Here is the code I have ended up using, it is a mix of my original and that of Bolton (thanks Bolton :-)).

The new code may detect a failure of a part better, a bit hard to test, the code above sets anyError to false for each message part, so if part 1 failed and part 2 succeeded it might think that the whole thing succeeded... the code below calls (my) messageInfo.fail which won't get reset if a subsequent message part succeeds... I imagine this is all pretty unneeded as you would think that if one part works, the rest will too... anyhow, below is the code I ultimately used.

Edit > Updated the code to remove the Extras in the intent as under heavy load, multiple intents (I think) got merged into one (using different PendingIntent flags did not help). In the end, I used a different intent action for each message (e.g. new Intent(SENT + messageInfo.getMessageId())), this way the receiver definitely only gets broadcasts for its own message. Seems to work better under heavy load.

Thanks.

private void sendLongSmsMessage4(Context context, final SmsMessageInfo messageInfo) {

// Receive when each part of the SMS has been sent
BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
// We need to make all the parts succeed before we say we have succeeded.
switch (getResultCode()) {
case Activity.RESULT_OK:
break;
case SmsManager.RESULT_ERROR_GENERIC_FAILURE:
messageInfo.fail("Error - Generic failure");
break;
case SmsManager.RESULT_ERROR_NO_SERVICE:
messageInfo.fail("Error - No Service");
break;
case SmsManager.RESULT_ERROR_NULL_PDU:
messageInfo.fail("Error - Null PDU");
break;
case SmsManager.RESULT_ERROR_RADIO_OFF:
messageInfo.fail("Error - Radio off");
break;
}

nMsgParts--;
if (nMsgParts <= 0) {
// Stop us from getting any other broadcasts (may be for other messages)
Log.i(LOG_TAG, "All message part resoponses received, unregistering message Id: " + messageInfo.getMessageId());
context.unregisterReceiver(this);

if (messageInfo.isFailed()) {
Log.d(LOG_TAG, "SMS Failure for message id: " + messageInfo.getMessageId());
} else {
Log.d(LOG_TAG, "SMS Success for message id: " + messageInfo.getMessageId());
messageInfo.setSent(true);
}
}
}
};

context.registerReceiver(broadcastReceiver, new IntentFilter(SENT + messageInfo.getMessageId()));

SmsManager smsManager = SmsManager.getDefault();

ArrayList<String> messageParts = smsManager.divideMessage(messageInfo.getMessage());
ArrayList<PendingIntent> pendingIntents = new ArrayList<PendingIntent>(messageParts.size());
nMsgParts = messageParts.size();

for (int i = 0; i < messageParts.size(); i++) {
Intent sentIntent = new Intent(SENT + messageInfo.getMessageId());
pendingIntents.add(PendingIntent.getBroadcast(context, 0, sentIntent, 0));
}

Log.i(LOG_TAG, "About to send multi-part message Id: " + messageInfo.getMessageId());
smsManager.sendMultipartTextMessage(messageInfo.getPhoneNumber(), null, messageParts, pendingIntents, null);
}


Related Topics



Leave a reply



Submit