如何获取短信发送确认为Android中的每个联系人/人?

时间:2014-07-10 09:58:51

标签: android sms broadcastreceiver android-broadcast

我想向多人发送短信并验证是否发送了短信。我检查了多个链接(这里提到),并想到了使用PendingIntentbroadCast Receiver进行确认。

  

Practical way to find out if SMS has been sent
  Sending text messages programmatically in android
  http://mobiforge.com/design-development/sms-messaging-android

但关键问题是,我在arrayList中有不同的50个联系人号码,而在另一个arrayList中有不同的msg。

我使用此代码:

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

现在,我无法确定有多少人获得了他们的消息以及有多少人没有消息。因为如帖子(上面提到的链接)所示,每次我们只获得一个消息,"短信发送"。

所以请让我知道,我怎样才能把#34;额外的"在Intent中,当我发送消息并从broadcast Receiver获取额外内容以获取特定联系人/人的详细信息。

还有一件事PendingIntent中的旗帜值有四种不同的选项 (FLAG_ONE_SHOTFLAG_NO_CREATEFLAG_CANCEL_CURRENTFLAG_UPDATE_CURRENT)。 当我在for循环中发送消息以获得正确的结果时,我应该使用哪一个?

1 个答案:

答案 0 :(得分:18)

这是一个非常简单的示例,用于演示如何使用可用于所有PendingIntent方法的发送和传递SmsManager#send*(),并将数据附加到这些方法以便轻松区分Receiver中的结果。

附加数据非常简单,只需在支持我们传递给Intent方法的PendingIntent的{​​{1}}上添加额外内容即可。问题在于send*()可能不像预期的那样表现。为了节省资源,系统只会在必要时创建新资源。如果PendingIntent根据Intent#filterEquals()方法不同,则get*()方法只返回不同的PendingIntent,请求代码当前未用于相等Intent },或传递适当的标志。

具有相同请求代码的其他Intent上的不同附加内容会导致创建新的Intent。根据在这种情况下传递的标志,可能会忽略这些额外内容,或覆盖当前活动PendingIntent中的附加内容,这可能会导致错误的结果。

在我们的示例中,我们基本上为每个发送使用相同的PendingIntent,因此我们通过传递唯一的请求代码来确保每个发送的Intent不同。这个简单的示例使用缩小列表的大小来表示这些代码,这些代码在单次运行的上下文中是唯一的。请求代码最终可以是任意PendingIntent,只要您知道它在请求时未使用。

系统会想要缓存这些int,如果我们在不久的将来再次需要它们,那么我们也会在使用后通过PendingIntent“清除它们”,并确保我们在后续运行中获得正确的,当前的额外内容。

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"; } } } } 从[{1}}上的PDU额外获得的getStatus()返回,以获得实际结果。

  • 另请注意,并非所有运营商都提供投放结果,在这种情况下,投放SmsMessage将永远不会触发。不要依赖交付结果。

  • 此示例使用“正确”(虽然简单)方法来顺序发送多条消息,因为它等待当前发送竞争,然后再继续下一步。对于简短列表,您可以在执行时尽快触发所有发送的循环,但如果系统无法跟上,则可能导致一般性故障。

  • 如上所述,这是一个非常简单的例子。它不适合生产,因为动态注册的Receiver与Intent的生命周期相关联。理想情况下,您需要实现在清单中注册的静态Receiver类,并使用显式PendingIntent来定位它。还建议使用Activity来处理结果,并且可以通过任意数量的机制将这些结果传递给UI;例如,Intent,另一个事件总线实现,ServiceLocalBroadcastManager等等。