现在我试图使用以下代码以编程方式发送短信,但我不理解SMS SENT接收器的行为。
1)例如,如果我发送一条短信,然后发送
Activity.RESULT_OK
registerReceiver
被召唤3次。如果我发送3短信使用 for for循环调用sendSMS
然后Activity.RESULT_OK
正在进行 叫了9次。现在我真的不知道一个短信发送为什么这个 registerReceiver被调用了很多次?2)此外,当我在模拟器上运行此代码时,我通过了模拟器 端口发送短信到其他模拟器,这是很自然,但当我尝试 发送短信到一个实数,然后我没有收到短信发送失败 通知,因为它仅通知
Activity.RESULT_OK
发送短信的代码
private void sendSMS(String phoneNumber, String message)
{
String SENT = "SMS_SENT";
String DELIVERED = "SMS_DELIVERED";
PendingIntent sentPI = PendingIntent.getBroadcast(this, 0,
new Intent(SENT), 0);
PendingIntent deliveredPI = PendingIntent.getBroadcast(this, 0,
new Intent(DELIVERED), 0);
Log.d("SMS Service", "SMS SEND CALLED");
//---when the SMS has been sent---
registerReceiver(new BroadcastReceiver(){
@Override
public void onReceive(Context arg0, Intent arg1) {
Log.d("SMS Service", "RECEIVE CALLED");
switch (getResultCode())
{
case Activity.RESULT_OK:
Toast.makeText(SMSService.this, "SMS sent",
Toast.LENGTH_SHORT).show();
System.out.println("SMSService " + "SMS SENT");
break;
case SmsManager.RESULT_ERROR_GENERIC_FAILURE:
Toast.makeText(SMSService.this, "Generic failure",
Toast.LENGTH_SHORT).show();
System.out.println("SMSService " + "GENERIC FAILURE");
break;
case SmsManager.RESULT_ERROR_NO_SERVICE:
Toast.makeText(SMSService.this, "No service",
Toast.LENGTH_SHORT).show();
System.out.println("SMSService " + "NO SERVICE");
break;
case SmsManager.RESULT_ERROR_NULL_PDU:
Toast.makeText(SMSService.this, "Null PDU",
Toast.LENGTH_SHORT).show();
System.out.println("SMSService " + "Null PDU");
break;
case SmsManager.RESULT_ERROR_RADIO_OFF:
Toast.makeText(SMSService.this, "Radio off",
Toast.LENGTH_SHORT).show();
System.out.println("SMSService " + "Radio Off");
break;
}
}
}, new IntentFilter(SENT));
//---when the SMS has been delivered---
registerReceiver(new BroadcastReceiver(){
@Override
public void onReceive(Context arg0, Intent arg1) {
switch (getResultCode())
{
case Activity.RESULT_OK:
Toast.makeText(getBaseContext(), "SMS delivered",
Toast.LENGTH_SHORT).show();
System.out.println("SMSService " + "SMS Delivered");
break;
case Activity.RESULT_CANCELED:
Toast.makeText(getBaseContext(), "SMS not delivered",
Toast.LENGTH_SHORT).show();
System.out.println("SMSService " + "SMS not delivered");
break;
}
}
}, new IntentFilter(DELIVERED));
SmsManager sms = SmsManager.getDefault();
sms.sendTextMessage(phoneNumber, null, message, sentPI, deliveredPI);
}
答案 0 :(得分:6)
一般情况下,它取决于您发送的邮件大小 - 如果邮件超过单个邮件限制(在您的情况下,它听起来大约是单个邮件限制的3倍)那么您将获得邮件的每个部分的发送和传递报告。由于您未手动拆分邮件,因此无法为每个部分指定不同的意图。
值得一看[{3}}自己拆分信息,然后在SmsManager.divideMessage()进行实际发送。这允许您为消息的不同部分指定不同的待处理意图,这样您就可以确定消息最终被发送的时间。
我认为模拟器将所有邮件目的地视为准确,因为没有网络可以回来说,否则你可能无法从模拟器发送失败(除非你做了类似的事情)将模拟器置于飞行模式)。根据经验,您肯定会在真实设备上获取这些错误代码。
修改强> 考虑到它,你每次发送消息时都会注册接收器,我使用的代码有一个明显的注册接收器。您可能已经多次注册它(只要您注册的上下文存在),这可能会多次给您 - 这也可能使其重复9次对于3条消息(假设第3次注册是在第一次发送完成之前完成的) - 可能但我不知道有多大可能。您可以通过在已注册的接收器中记录对象来相对较好地进行测试。
这是我用来发送短信的代码的简化版本,它没有得到重复的邮件回复:
ArrayList<String> split = SmsManager.getDefault().divideMessage(message);
ArrayList<PendingIntent> success = new ArrayList<PendingIntent>(partInfo.length);
Intent sendInt = null;
for (int i = 0; i < partInfo.length; i++)
{
sendInt = new Intent(context.getPackageName() + RELAY_INTERNAL_RESPONSE);
sendInt.putExtra(KEY_MESSAGEID, messageID);
sendInt.putExtra(KEY_PART_NUMBER, i);
sendInt.putExtra(KEY_REPLY_SEND_INTENT, sendIntAction);
sendInt.putExtra(KEY_NUMBER, number);
PendingIntent sendResult = PendingIntent.getBroadcast(context, i, sendInt, PendingIntent.FLAG_ONE_SHOT); //You have to use an incrementing request code to ensure you don't just get the same pending intent.
success.add(sendResult);
}
ArrayList<PendingIntent> receipt = new ArrayList<PendingIntent>(partInfo.length);
sendInt = new Intent(context.getPackageName() + RELAY_INTERNAL_RECEIPT);
sendInt.putExtra(KEY_MESSAGEID, messageID);
sendInt.putExtra(KEY_REPLY_RECEIPT_INTENT, receiptIntAction);
sendInt.putExtra(KEY_NUMBER, number);
PendingIntent sendResult = PendingIntent.getBroadcast(context, nextReceiptCounter(context), sendInt, PendingIntent.FLAG_ONE_SHOT);
for (int i = 0; i < partInfo.length; i++)
{
receipt.add(sendResult);
}
SmsManager sm = SmsManager.getDefault();
sm.sendMultipartTextMessage(target, null, split, success, receipt);
我的接收器定义:
<receiver android:name="<package>.SMSBroadcastModule"
android:enabled="true"
android:exported="false">
<intent-filter>
<action android:name="<package>.RELAY_INTERNAL_RESPONSE" />
<action android:name="<package>.RELAY_INTERNAL_RESPONSE_RECEIPT" />
</intent-filter>
</receiver>
答案 1 :(得分:1)
或者您可以为寄存器执行单例类:
public class RegisterReceiverSingleton {
private static RegisterReceiverSingleton rrS;
public static final String SENT = "SMS_SENT";
public static final String DELIVERED = "SMS_DELIVERED";
private RegisterReceiverSingleton(final Context ctx){
//when the SMS has been sent
ctx.registerReceiver(new BroadcastReceiver(){
@Override
public void onReceive(Context arg0, Intent arg1) {
switch (getResultCode())
{
case Activity.RESULT_OK:
Toast.makeText(ctx, "SMS Enviado",
Toast.LENGTH_SHORT).show();
break;
case SmsManager.RESULT_ERROR_GENERIC_FAILURE:
Toast.makeText(ctx, "Generic failure",
Toast.LENGTH_SHORT).show();
break;
case SmsManager.RESULT_ERROR_NO_SERVICE:
Toast.makeText(ctx, "No service",
Toast.LENGTH_SHORT).show();
break;
case SmsManager.RESULT_ERROR_NULL_PDU:
Toast.makeText(ctx, "Null PDU",
Toast.LENGTH_SHORT).show();
break;
case SmsManager.RESULT_ERROR_RADIO_OFF:
Toast.makeText(ctx, "Radio off",
Toast.LENGTH_SHORT).show();
break;
}
}
}, new IntentFilter(SENT));
//when the SMS has been delivered
ctx.registerReceiver(new BroadcastReceiver(){
@Override
public void onReceive(Context arg0, Intent arg1) {
switch (getResultCode())
{
case Activity.RESULT_OK:
Toast.makeText(ctx, "SMS Entregado",
Toast.LENGTH_SHORT).show();
break;
case Activity.RESULT_CANCELED:
Toast.makeText(ctx, "SMS No Entregado",
Toast.LENGTH_SHORT).show();
break;
}
}
}, new IntentFilter(DELIVERED));
}
public static RegisterReceiverSingleton getInstance(final Context ctx){
if(rrS==null){
rrS = new RegisterReceiverSingleton(ctx);
}
return rrS;
}
}