Search code examples
androidsmsconfirmationsmsmanager

Android: send SMS to multiple recepients and get confirmation


I want to send to multiple number of recepients. I also want to use the built in SMS mechanism without being prompt for a required App (Whatsapp, etc.)

In order to acomplish this, I am using Android's SmsManager.

The for loop iterates through the mobileList array of mobile numbers and send SMS to each one of them, one by one.

The indication for delivered SMS is retrieved by the BroadcastReceiver for the deliveredActionIntent intent.

I am popping a toast with the word "Delivered" and the index number of the message being delivered.

My questions are:

  1. The actual index (idx) is not shown. I get for all toasts the same index number which is the number of mobileList items. Why is this happening? I expected the index for each mobile by itself.

  2. Is the number of mobileList items limited? Can I have 200 people for instance?

  3. I tested this on a list of 4 mobile numbers but then I got 8-10 toasts. I expected one toast for one mobile delivery. What is wrong here?

  4. How can I get a notification when all SMSs are delivered? I guess this should be a background action like AsyncTask. Can someone please show me how to do this?

The code of the SmsManager is shown below.

SmsManager smsManager = SmsManager.getDefault();

for(idx = 0; idx < mobileList.length; idx++) {

    String toNumber = mobileList[idx];
    String sms = message;

    // SMS sent pending intent
    Intent sentActionIntent = new Intent(SENT_ACTION);
    sentActionIntent.putExtra(EXTRA_IDX, idx);
    sentActionIntent.putExtra(EXTRA_TONUMBER, toNumber);
    sentActionIntent.putExtra(EXTRA_SMS, sms);
    PendingIntent sentPendingIntent = PendingIntent.getBroadcast(this, 0, sentActionIntent, PendingIntent.FLAG_UPDATE_CURRENT);

    /* Register for SMS send action */
    registerReceiver(new BroadcastReceiver() {

        @Override
        public void onReceive(Context context, Intent intent) {
            String result = "";

            switch (getResultCode()) {

            case Activity.RESULT_OK:
                result = "Transmission successful";
                break;
            case SmsManager.RESULT_ERROR_GENERIC_FAILURE:
                result = "Transmission failed";
                break;
            case SmsManager.RESULT_ERROR_RADIO_OFF:
                result = "Radio off";
                break;
            case SmsManager.RESULT_ERROR_NULL_PDU:
                result = "No PDU defined";
                break;
            case SmsManager.RESULT_ERROR_NO_SERVICE:
                result = "No service";
                break;
            }

            // Toast.makeText(getApplicationContext(), result,  Toast.LENGTH_SHORT).show();
        }

    }, new IntentFilter(SENT_ACTION));                  


    // SMS delivered pending intent
    Intent deliveredActionIntent = new Intent(DELIVERED_ACTION);
    deliveredActionIntent.putExtra(EXTRA_IDX, idx);
    deliveredActionIntent.putExtra(EXTRA_TONUMBER, toNumber);
    deliveredActionIntent.putExtra(EXTRA_SMS, sms);
    PendingIntent deliveredPendingIntent = PendingIntent.getBroadcast(this, 0, deliveredActionIntent, PendingIntent.FLAG_UPDATE_CURRENT);

    /* Register for Delivery event */
    registerReceiver(new BroadcastReceiver() {

        @Override
        public void onReceive(Context context, Intent intent) {
            Toast.makeText(getApplicationContext(), "Deliverd " + Integer.toString(idx), Toast.LENGTH_SHORT).show();
        }

    }, new IntentFilter(DELIVERED_ACTION));

    //send
    smsManager.sendTextMessage(toNumber, null, sms, sentPendingIntent, deliveredPendingIntent);
}

Solution

  • 1) idx changes as you run through the for-loop. Thus, each time you toast, you're showing the current value for idx, which is the number of messages being shown. Since you've packed it in your intent, you can simply show the text "Delivered" + intent.getIntExtra(EXTRA_IDX, -1) in your onReceive method.

    2) I'm not sure what you're asking.

    3) I'm not sure off-hand, and can't currently debug.

    4) You're going to have to keep track of which indices you've received. A HashSet<Integer> should do the trick.

    Above your for loop, add this:

    final HashSet<Integer> undelivered = new HashSet<Integer>();
    

    In your for loop, add this:

    undelivered.add(idx);
    

    To answer your questions for 1, 3, and 4 at once, change your onReceived body to this:

    // Get the index from the intent
    int idx = intent.getIntExtra(EXTRA_IDX, -1);
    
    if (undelivered.contains(idx)) {
        // This index is now delivered. We remove it from the undelivered set, and Toast that it was delivered.
        undelivered.remove(idx);
        Toast.makeText(getApplicationContext(), "Delivered " + idx, Toast.LENGTH_SHORT).show();
    
        if (undelivered.isEmpty() {
            // We've delivered all of the messages ...
            Toast.makeText(getApplicationContext(), "All messages were delivered.", Toast.LENGTH_SHORT).show();
        }
    }