Как получить подтверждение отправки sms для каждого контакта / человека в android?


Я хочу отправить sms нескольким людям и проверить, отправлено ли sms или нет. Я проверил несколько ссылок (упомянутых здесь) и получил идею использовать PendingIntent и broadCast Receiver для подтверждения.

Практический способ узнать, было ли отправлено SMS
отправка текстовых сообщений программно в android
http://mobiforge.com/design-development/sms-messaging-android

Но ключевая проблема заключается в том, что у меня есть разные 50 номеров контактов в одном arrayList и их различных msgs в другом arrayList.

Я использую этот код:

for (Condition) {   
    sms = SmsManager.getDefault();   
    try {   
        . . . sms.sendTextMessage(phoneNumbers[i], null, messages[i], sentPI, deliveredPI);  
    }   
    catch(IllegalArgumentException e) {     }  
}

Теперь я не могу определить, сколько людей получают свой msg, а сколько нет, потому что, как показано в сообщении(упомянутой выше ссылке), каждый раз, когда мы получаем только один msg, "SMS доставляется".

Поэтому, пожалуйста, дайте мне знать, как я могу поместить "дополнительные услуги" в Intent, Когда я отправляю msg и получаю дополнительные услуги от broadcast Receiver, чтобы получить подробную информацию о конкретном контакте/лице.

Еще одна вещь : есть четыре другой вариант для значения флага в PendingIntent (FLAG_ONE_SHOT, FLAG_NO_CREATE, FLAG_CANCEL_CURRENT,FLAG_UPDATE_CURRENT). Какой из них следует использовать при отправке сообщений в цикле for для получения правильного результата?

1 2

1 ответ:

Это очень простой пример, демонстрирующий использование методов отправки и доставки PendingIntent, доступных для всех методов SmsManager#send*(), и прикрепление данных к ним, чтобы легко дифференцировать результаты в приемнике.

Прикрепление этих данных так же просто, как добавление дополнительных функций к Intents, поддерживающим PendingIntents, которые мы передаем в методы send*(). Загвоздка в том, что PendingIntent s может вести себя не так, как ожидалось. Чтобы сохранить ресурсы, система будет создавать новые только тогда, когда это необходимо. Методы get*() будут возвращайте только различное PendingIntent, если Intent отличается в соответствии с Intent#filterEquals() метод, код запроса в настоящее время не используется для равного Intent, или передается соответствующий флаг.

Различные дополнительные функции на одном и том же Intent с одним и тем же кодом запроса не будутвызывать создание нового PendingIntent. В зависимости от флага, переданного в этом случае, эти дополнительные функции могут быть проигнорированы или перезаписаны в текущем активном PendingIntent, что может привести к неверным результатам.

В в нашем примере мы в основном используем один и тот же Intent для каждой отправки, поэтому мы обеспечим отдельный PendingIntent для каждого, передавая уникальные коды запроса. В этом простом примере используется размер сжимающегося списка для тех кодов, которые будут уникальными в контексте одного запуска. Код запроса в конечном счете может быть любым произвольным int, Если вы знаете, что он не используется во время запроса.

Система захочет кэшировать эти PendingIntents, Если они снова понадобятся нам в ближайшем будущем, поэтому мы также передадим FLAG_ONE_SHOT чтобы "очистить их" после использования, и убедитесь, что мы получаем правильные, текущие дополнения в последующих запусках.

public class SmsActivity extends Activity implements View.OnClickListener {
    private static final String SMS_SENT_ACTION = "com.mycompany.myapp.SMS_SENT";
    private static final String SMS_DELIVERED_ACTION = "com.mycompany.myapp.SMS_DELIVERED";
    private static final String EXTRA_NUMBER = "number";
    private static final String EXTRA_MESSAGE = "message";

    // Initialize our sample numbers list.
    private final List<String> numberList = new ArrayList<String>() {{{
                add("111-111-1111");
                add("222-222-2222");
                add("333-333-3333");
    }}};

    // Initialize our sample message list.
    private final List<String> messageList = new ArrayList<String>() {{{
                add("Hello.");
                add("Howdy.");
                add("Hi.");
    }}};

    private SmsManager smsManager;
    private IntentFilter intentFilter;
    private BroadcastReceiver resultsReceiver;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_sms);

        findViewById(R.id.button_send).setOnClickListener(this);

        smsManager = SmsManager.getDefault();
        resultsReceiver = new SmsResultReceiver();

        intentFilter = new IntentFilter(SMS_SENT_ACTION);
        intentFilter.addAction(SMS_DELIVERED_ACTION);
    }

    @Override
    protected void onResume() {
        super.onResume();
        registerReceiver(resultsReceiver, intentFilter);
    }

    @Override
    protected void onPause() {
        super.onPause();
        unregisterReceiver(resultsReceiver);
    }

    public void onClick(View v) {
        v.setEnabled(false);
        sendNextMessage();
    }

    private void sendNextMessage() {
        // We're going to remove numbers and messages from
        // the lists as we send, so if the lists are empty, we're done.
        if (numberList.size() == 0) {
            return;
        }

        // The list size is a sufficiently unique request code,
        // for the PendingIntent since it decrements for each send.
        int requestCode = numberList.size();

        String number = numberList.get(0);
        String message = messageList.get(0);

        // The Intents must be implicit for this example,
        // as we're registering our Receiver dynamically.
        Intent sentIntent = new Intent(SMS_SENT_ACTION);
        Intent deliveredIntent = new Intent(SMS_DELIVERED_ACTION);

        // We attach the recipient's number and message to
        // the Intents for easy retrieval in the Receiver.
        sentIntent.putExtra(EXTRA_NUMBER, number);
        sentIntent.putExtra(EXTRA_MESSAGE, message);
        deliveredIntent.putExtra(EXTRA_NUMBER, number);
        deliveredIntent.putExtra(EXTRA_MESSAGE, message);

        // Construct the PendingIntents for the results.
        // FLAG_ONE_SHOT cancels the PendingIntent after use so we
        // can safely reuse the request codes in subsequent runs.
        PendingIntent sentPI = PendingIntent.getBroadcast(this,
                                                          requestCode,
                                                          sentIntent,
                                                          PendingIntent.FLAG_ONE_SHOT);

        PendingIntent deliveredPI = PendingIntent.getBroadcast(this,
                                                               requestCode,
                                                               deliveredIntent,
                                                               PendingIntent.FLAG_ONE_SHOT);

        // Send our message.
        smsManager.sendTextMessage(number, null, message, sentPI, deliveredPI);

        // Remove the number and message we just sent to from the lists.
        numberList.remove(0);
        messageList.remove(0);
    }

    private class SmsResultReceiver extends BroadcastReceiver {

        @Override
        public void onReceive(Context context, Intent intent) {
            // A simple result Toast text.
            String result = null;

            // Get the result action.
            String action = intent.getAction();

            // Retrieve the recipient's number and message.
            String number = intent.getStringExtra(EXTRA_NUMBER);
            String message = intent.getStringExtra(EXTRA_MESSAGE);

            // This is the result for a send.
            if (SMS_SENT_ACTION.equals(action)) {
                int resultCode = getResultCode();
                result = "Send result : " + translateSentResult(resultCode);

                // The current send is complete. Send the next one.
                sendNextMessage();
            }
            // This is the result for a delivery.
            else if (SMS_DELIVERED_ACTION.equals(action)) {
                SmsMessage sms = null;

                // A delivery result comes from the service
                // center as a simple SMS in a single PDU.
                byte[] pdu = intent.getByteArrayExtra("pdu");
                String format = intent.getStringExtra("format");

                // Construct the SmsMessage from the PDU.
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && format != null) {
                    sms = SmsMessage.createFromPdu(pdu, format);
                }
                else {
                    sms = SmsMessage.createFromPdu(pdu);
                }

                // getResultCode() is not reliable for delivery results.
                // We need to get the status from the SmsMessage.
                result = "Delivery result : " + translateDeliveryStatus(sms.getStatus());
            }

            result = number + ", " + message + "\n" + result;
            Toast.makeText(context, result, Toast.LENGTH_SHORT).show();
        }

        String translateSentResult(int resultCode) {
            switch (resultCode) {
                case Activity.RESULT_OK:
                    return "Activity.RESULT_OK";
                case SmsManager.RESULT_ERROR_GENERIC_FAILURE:
                    return "SmsManager.RESULT_ERROR_GENERIC_FAILURE";
                case SmsManager.RESULT_ERROR_RADIO_OFF:
                    return "SmsManager.RESULT_ERROR_RADIO_OFF";
                case SmsManager.RESULT_ERROR_NULL_PDU:
                    return "SmsManager.RESULT_ERROR_NULL_PDU";
                case SmsManager.RESULT_ERROR_NO_SERVICE:
                    return "SmsManager.RESULT_ERROR_NO_SERVICE";
                default:
                    return "Unknown error code";
            }
        }

        String translateDeliveryStatus(int status) {
            switch (status) {
                case Telephony.Sms.STATUS_COMPLETE:
                    return "Sms.STATUS_COMPLETE";
                case Telephony.Sms.STATUS_FAILED:
                    return "Sms.STATUS_FAILED";
                case Telephony.Sms.STATUS_PENDING:
                    return "Sms.STATUS_PENDING";
                case Telephony.Sms.STATUS_NONE:
                    return "Sms.STATUS_NONE";
                default:
                    return "Unknown status code";
            }
        }
    }
}

Примечания:

  • Обратите внимание на метод, который мы используем, чтобы получить статус доставки. Код результата в приемнике не является надежным индикатором. Мы должны проверить getStatus() возврат SmsMessage, полученный из PDU extra на Intent, чтобы получить фактический результат.

  • Также имейте в виду, что не все перевозчики предоставляют результаты доставки, в в этом случае доставка PendingIntents никогда не выстрелит. Не полагайтесь на результат доставки.

  • В этом примере используется "правильный", хотя и простой, метод для последовательной отправки нескольких сообщений, в том смысле, что он ожидает, пока текущая отправка не будет завершена, прежде чем перейти к следующей. Для коротких списков, вы можете быть в состоянии уйти с циклом, запускающим все отправки так же быстро, как он выполняется, но это может привести к общему сбою, если система не может идти в ногу.

  • Как уже отмечалось, это очень простой пример. Он не очень подходит для производства, так как динамически зарегистрированный приемник привязан к жизненному циклу Activity. В идеале нужно реализовать статический класс Receiver, зарегистрированный в манифесте, и использовать явные Intents для его целевого назначения. Также рекомендуется использовать Service для обработки результатов, и эти результаты могут быть доставлены в пользовательский интерфейс через любое количество механизмов; например, LocalBroadcastManager, другая реализация шины событий, Intents, Notifications, и т.д.