Alex Busuioc
Alex Busuioc

Reputation: 1182

Android - SMS sent intent not received 100% of time

I'm sending more than 400 sms messages a day, but only for around 95% of them i receive the sms sent intent into the broadcast receiver. The messages are sent at 5 seconds interval.

ArrayList<String> partsArray = SmsManager.getDefault().divideMessage(this.message);
ArrayList<PendingIntent> sentPendingIntents = new ArrayList<>(partsArray.size());
ArrayList<PendingIntent> deliveredPendingIntents = new ArrayList<>(partsArray.size());
      .....

for (int i = 0; i < partsArray.size(); i++) {
        sentIntent = new Intent("SMS_SENT_2");
        deliveredIntent = new Intent(C.SMS_DELIVERED);
        sentPI = PendingIntent.getBroadcast(context, 0,sentIntent, PendingIntent.FLAG_ONE_SHOT);
        deliveredPI = PendingIntent.getBroadcast(context, 0, deliveredIntent, PendingIntent.FLAG_ONE_SHOT);

        sentPendingIntents.add(sentPI);
        deliveredPendingIntents.add(deliveredPI);
}

SmsManager sms = SmsManager.getDefault();
sms.sendMultipartTextMessage(phoneNumber, null,partsArray, sentPendingIntents, deliveredPendingIntents);

and the broadcast receiver in the manifest:

<receiver android:name="._broadcastReceivers.SMSSentBroadcastReceiver">
        <intent-filter android:priority="999">
            <action android:name="SMS_SENT_2" />
        </intent-filter>
</receiver>

I know for a fact that for some of the messages the broadcast receiver didn't get the intent, but the sms was actually sent.

How can i reliably determine whether an sms "left the phone" or not?

Upvotes: 2

Views: 406

Answers (1)

David Wasser
David Wasser

Reputation: 95578

Instead of using FLAG_ONE_SHOT you should ensure that the PendingIntents are unique. The easiest way to do that is to use explicit Intent instead of implicit Intent and make sure that the ACTION in each Intent is unique. Here's an example:

for (int i = 0; i < partsArray.size(); i++) {
    sentIntent = new Intent(this, _broadcastReceivers.SMSSentBroadcastReceiver.class);
    sentIntent.setAction("SMS_SENT_2" + System.currentTimeMillis());
    deliveredIntent = new Intent(this, DeliveryReceiver.class);
    deliveredIntent.setAction(C.SMS_DELIVERED + System.currentTimeMillis());
    sentPI = PendingIntent.getBroadcast(context, 0, sentIntent, 0);
    deliveredPI = PendingIntent.getBroadcast(context, 0, deliveredIntent, 0);

    sentPendingIntents.add(sentPI);
    deliveredPendingIntents.add(deliveredPI);
}

I've ensured that the ACTION is unique by appending the current timestamp to each ACTION.

You can now remove the <intent-filter> from the manifest definition for the BroadcastReceiver as you don't need it anymore (you are using explicit Intent). Make sure, however, that you add android:exported="true" to the manifest definition for the BroadcastReceiver because it will not be exported unless you either have an <intent-filter> or specifically declare that it is exported.

Upvotes: 2

Related Questions