Как получить подтверждение отправки 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 ответ:
Это очень простой пример, демонстрирующий использование методов отправки и доставки
PendingIntent
, доступных для всех методовSmsManager#send*()
, и прикрепление данных к ним, чтобы легко дифференцировать результаты в приемнике.Прикрепление этих данных так же просто, как добавление дополнительных функций к
Intent
s, поддерживающимPendingIntent
s, которые мы передаем в методыsend*()
. Загвоздка в том, чтоPendingIntent
s может вести себя не так, как ожидалось. Чтобы сохранить ресурсы, система будет создавать новые только тогда, когда это необходимо. Методыget*()
будут возвращайте только различноеPendingIntent
, еслиIntent
отличается в соответствии сIntent#filterEquals()
метод, код запроса в настоящее время не используется для равногоIntent
, или передается соответствующий флаг.Различные дополнительные функции на одном и том же
Intent
с одним и тем же кодом запроса не будутвызывать создание новогоPendingIntent
. В зависимости от флага, переданного в этом случае, эти дополнительные функции могут быть проигнорированы или перезаписаны в текущем активномPendingIntent
, что может привести к неверным результатам.В в нашем примере мы в основном используем один и тот же
Intent
для каждой отправки, поэтому мы обеспечим отдельныйPendingIntent
для каждого, передавая уникальные коды запроса. В этом простом примере используется размер сжимающегося списка для тех кодов, которые будут уникальными в контексте одного запуска. Код запроса в конечном счете может быть любым произвольнымint
, Если вы знаете, что он не используется во время запроса.Система захочет кэшировать эти
PendingIntent
s, Если они снова понадобятся нам в ближайшем будущем, поэтому мы также передадим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
, чтобы получить фактический результат.Также имейте в виду, что не все перевозчики предоставляют результаты доставки, в в этом случае доставка
PendingIntent
s никогда не выстрелит. Не полагайтесь на результат доставки.В этом примере используется "правильный", хотя и простой, метод для последовательной отправки нескольких сообщений, в том смысле, что он ожидает, пока текущая отправка не будет завершена, прежде чем перейти к следующей. Для коротких списков, вы можете быть в состоянии уйти с циклом, запускающим все отправки так же быстро, как он выполняется, но это может привести к общему сбою, если система не может идти в ногу.
Как уже отмечалось, это очень простой пример. Он не очень подходит для производства, так как динамически зарегистрированный приемник привязан к жизненному циклу
Activity
. В идеале нужно реализовать статический класс Receiver, зарегистрированный в манифесте, и использовать явныеIntent
s для его целевого назначения. Также рекомендуется использоватьService
для обработки результатов, и эти результаты могут быть доставлены в пользовательский интерфейс через любое количество механизмов; например,LocalBroadcastManager
, другая реализация шины событий,Intent
s,Notification
s, и т.д.