我想向多人发送短信并验证短信是否发送.我检查了多个链接(这里提到),并得到了使用PendingIntent
和broadCast Receiver
确认的想法.
找出SMS是否已发送的实用方法
在android中以编程方式发送文本消息
http://mobiforge.com/design-development/sms-messaging-android
但关键问题在于,我在一个中有不同的50个联系人号码,arrayList
在另一个中有不同的消息arrayList
.
我用这个代码:
for (Condition) { sms = SmsManager.getDefault(); try { . . . sms.sendTextMessage(phoneNumbers[i], null, messages[i], sentPI, deliveredPI); } catch(IllegalArgumentException e) { } }
现在,我无法确定有多少人获得了他们的消息,有多少人没有.因为如帖子(上面提到的链接)所示,每次我们只获得一个消息,"短信发送".
所以请让我知道,Intent
当我发送消息并获取额外信息broadcast Receiver
以获取特定联系人/人的详细信息时,我怎样才能添加"额外内容" .
还有一两件事:有在标志值四个不同的选项PendingIntent
(FLAG_ONE_SHOT
,FLAG_NO_CREATE
,FLAG_CANCEL_CURRENT
,FLAG_UPDATE_CURRENT
).当我在for循环中发送消息以获得正确的结果时,我应该使用哪一个?
这是一个非常简单的示例,用于演示如何使用PendingIntent
可用于所有SmsManager#send*()
方法的发送和传递,并将数据附加到这些方法以轻松区分Receiver中的结果.
附加数据就像在我们传递给方法Intent
的背景上添加额外内容一样简单.问题是,s可能不像人们期望的那样.为了节省资源,系统只会在必要时创建新资源.如果方法不同,则方法将仅返回不同的方法,请求代码当前未用于相等,或者传递适当的标志.PendingIntent
send*()
PendingIntent
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"; } } } }
笔记:
请记下我们用于获取交付状态的方法.接收器中的结果代码不是可靠的指标.我们必须检查从PDU额外获得的getStatus()
返回以获得实际结果.SmsMessage
Intent
另请注意,并非所有运营商都提供交付结果,在这种情况下,交付PendingIntent
将永远不会发生.不要依赖交付结果.
此示例使用"正确"(虽然简单)方法来顺序发送多个消息,因为它等待当前发送竞争然后继续下一个消息.对于简短列表,您可能能够在执行时尽快触发所有发送的循环,但如果系统无法跟上,则可能导致一般性故障.
如上所述,这是一个非常简单的例子.它不适合生产,因为动态注册的Receiver与Activity
生命周期紧密相关.理想情况下,您需要实现在清单中注册的静态Receiver类,并使用显式Intent
s来定位它.Service
还建议使用a 来处理结果,并且可以通过任意数量的机制将这些结果传递给UI; 例如,LocalBroadcastManager
另一个事件总线实现,Intent
s,Notification
s等.