我想向多人发送短信并验证是否发送了短信。我检查了多个链接(这里提到),并想到了使用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
中有不同的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_SHOT
,FLAG_NO_CREATE
,FLAG_CANCEL_CURRENT
,FLAG_UPDATE_CURRENT
)。
当我在for循环中发送消息以获得正确的结果时,我应该使用哪一个?
答案 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
,另一个事件总线实现,Service
,LocalBroadcastManager
等等。