我想向多人发送短信并验证短信是否已发送。我检查了多个链接(此处提到)并想到使用 PendingIntent
和 broadCast 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
中有不同的消息。
我使用这段代码:
for (Condition) {
sms = SmsManager.getDefault();
try {
. . . sms.sendTextMessage(phoneNumbers[i], null, messages[i], sentPI, deliveredPI);
}
catch(IllegalArgumentException e) { }
}
现在,我无法确定有多少人收到了他们的消息,有多少人没有收到。因为如帖子(上面提到的链接)所示,每次我们只收到一条消息,“短信已送达”。
所以请告诉我,当我发送消息并从 broadcast Receiver
获取额外信息以获取特定细节时,如何将“额外信息”放入 Intent
联系人/人。
还有一件事:PendingIntent
中有四种不同的标志值选项
(FLAG_ONE_SHOT
、FLAG_NO_CREATE
、FLAG_CANCEL_CURRENT
、FLAG_UPDATE_CURRENT
)。
当我在 for 循环中发送消息以获得正确结果时,我应该使用哪个?
最佳答案
这是一个非常简单的示例,用于演示可用于所有 SmsManager#send*()
方法的发送和传递 PendingIntent
的使用,以及附加数据以便轻松区分接收器中的结果。
附加该数据就像在 Intent
上添加额外内容一样简单,以支持我们传递给 send*()
方法的 PendingIntent
.问题是 PendingIntent
的行为可能不像人们预期的那样。为了节约资源,系统只会在必要时创建新资源。如果 Intent
根据 Intent#filterEquals()
不同,get*()
方法将仅返回不同的 PendingIntent
方法,请求代码当前未用于相同的 Intent
,或者传递了适当的标志。
具有相同请求代码的其他相同 Intent
的不同附加项 不会 导致创建新的 PendingIntent
。根据在这种情况下传递的标志,这些额外内容可能会被忽略,或者覆盖当前 Activity 的 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";
}
}
}
}
注意事项:
请记下我们用于获取交付状态的方法。接收器中的结果代码不是可靠的指标。我们必须检查从
Intent
上的 PDU extra 获取的SmsMessage
的getStatus()
返回,以获得实际结果。另请注意,并非所有承运商都提供交付结果,在这种情况下,交付
PendingIntent
永远不会触发。不要依赖交付结果。此示例使用“正确”但简单的方法按顺序发送多条消息,因为它会等到当前发送完成后再继续下一个。对于短列表,您可以通过一个在执行时尽快触发所有发送的循环来逃脱,但如果系统跟不上,这可能会导致一般性故障。
如前所述,这是一个非常简单的示例。它不太适合生产,因为动态注册的 Receiver 与
Activity
的生命周期相关联。理想情况下,您希望实现一个在 list 中注册的静态 Receiver 类,并使用显式Intent
来定位它。还建议使用Service
来处理结果,这些结果可以通过多种机制传递到 UI;例如,LocalBroadcastManager
、另一个事件总线实现、Intent
、Notification
等。
关于android - 如何为android中的每个联系人/人发送短信确认?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24673595/