Android: отправьте SMS нескольким получателям и получите подтверждение

Я хочу отправить нескольким получателям. Я также хочу использовать встроенный механизм SMS без запроса необходимого приложения (Whatsapp и т. д.)

Для этого я использую Android SmsManager.

Цикл for перебирает массив мобильных номеров mobileList и отправляет SMS на каждый из них, один за другим.

Индикация для доставленного SMS извлекается BroadcastReceiver для намерения DeliverActionIntent.

Я выдвигаю тост со словом «Доставлено» и порядковым номером доставляемого сообщения.

Мои вопросы:

  1. Фактический индекс (idx) не отображается. Я получаю для всех тостов один и тот же номер индекса, который является количеством элементов мобильного списка. Почему это происходит? Я ожидал индекс для каждого мобильного телефона сам по себе.

  2. Ограничено ли количество элементов mobileList? Могу ли я иметь 200 человек, например?

  3. Я проверил это на списке из 4 мобильных номеров, но потом получил 8-10 тостов. Я ожидал один тост за одну мобильную доставку. Что здесь не так?

  4. Как я могу получить уведомление, когда все SMS доставлены? Я предполагаю, что это должно быть фоновое действие, такое как AsyncTask. Может кто-нибудь показать мне, как это сделать?

Код SmsManager показан ниже.

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);
}

person AJ Gottes    schedule 18.12.2014    source источник


Ответы (1)


1) idx изменяется по мере прохождения цикла for. Таким образом, каждый раз, когда вы поднимаете тост, вы показываете текущее значение idx, то есть количество отображаемых сообщений. Поскольку вы упаковали его в свое намерение, вы можете просто показать текст "Delivered" + intent.getIntExtra(EXTRA_IDX, -1) в своем методе onReceive.

2) Я не уверен, что вы спрашиваете.

3) Я не уверен навскидку и в настоящее время не могу отлаживать.

4) Вам нужно будет отслеживать, какие индексы вы получили. HashSet<Integer> должно помочь.

Над циклом for добавьте следующее:

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

В вашем цикле for добавьте следующее:

undelivered.add(idx);

Чтобы ответить на ваши вопросы для 1, 3 и 4 одновременно, измените свое тело onReceived на это:

// 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();
    }
}
person Tim Cooke    schedule 18.12.2014
comment
большое спасибо за ответ. Извините, что я так долго не отвечал. Я использовал предложенный вами код и добавил несколько журналов, чтобы объяснить, что он у меня не работает. Я написал несколько журналов. Если у меня есть два номера телефонов в списке, приемная трансляция вызывается более двух раз... undelivered.add правильно добавляет idx, но undelivered.remove вызывается более двух раз. Более того, он вызывается с постоянным индексом: 0. Это приводит к тому, что undelivered.isEmpty никогда не становится активным. Я расстроен. Не знаю, как это решить. У вас есть идея? - person AJ Gottes; 19.12.2014
comment
Большое спасибо. У меня все заработало, и я использовал вашу идею для недоставленного хэша :-) Большое спасибо! - person AJ Gottes; 22.12.2014
comment
Я думаю, что вы что-то упускаете здесь. Широковещательный приемник должен быть зарегистрирован только один раз, а не в цикле for, это приведет к сбою. - person MIKE PERETZ; 09.09.2018