【问题标题】:Behavior of SMS NotificationsSMS 通知的行为
【发布时间】:2012-03-13 07:35:32
【问题描述】:

现在我正在尝试使用以下代码以编程方式发送 SMS,但我不了解 SMS SENT Receiver 的行为。

1) 例如,如果我发送一条短信,那么Activity.RESULT_OK 在里面 registerReceiver 被调用了 3 次。如果我使用发送 3 条短信 循环调用sendSMS 然后Activity.RESULT_OK 正在 叫了9次。现在我真的不知道为什么要发送一条短信 registerReceiver 被调用了这么多次?

2) 此外,当我在模拟器上运行此代码时,我通过了模拟器 端口将 SMS 发送到其他模拟器,这是很自然的,但是当我尝试 将短信发送到真实号码然后我没有收到短信发送失败 notification ,因为它只通知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);               
        } 

【问题讨论】:

    标签: android android-service android-2.2-froyo


    【解决方案1】:

    一般来说,这取决于您发送的消息的大小 - 如果消息超过单条消息限制(在您的情况下,这听起来像是单条消息限制的 3 倍),那么您将收到一个发送和消息的每个部分的传递报告。因为您没有手动拆分消息,所以无法为每个部分指定不同的意图。

    值得看看SmsManager.divideMessage() 自己拆分消息,然后在SmsManager.sendMultiPartTextMessage() 进行实际发送。这允许您为消息的不同部分指定不同的待处理意图,这样您就可以确定消息最终发送的时间。

    我认为模拟器将所有消息目的地视为准确,并且由于没有网络可以返回并说否则您可能不会从模拟器发送失败(除非您执行了诸如将模拟器置于飞行模式之类的操作)。根据经验,您肯定会在真实设备上收到这些错误代码。

    编辑: 考虑一下,您每次发送消息时也在注册接收器,我使用的代码有一个清单注册接收器。有可能您已经多次注册它(它的存在时间与您注册的上下文一样长),这会给您多次提供它 - 这也会使其重复 3 条消息可能 9 次(假设注册第三次在第一次发送完成之前完成)-可能,但我不知道可能性有多大。您可以通过在注册的接收器中记录对象来进行相对较好的测试。

    这是我用来发送短信的代码的精简版,它不会得到重复的消息响应:

    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>
    

    【讨论】:

    • 我的短信是“John Right,这是我的简单信息!” ,所以这个文本不是那么长吗?那么还需要使用 divideMessage 吗?
    • 仍然需要(由于 HTC 错误 - 这很烦人,然后它击中了我的应用程序),但它不应该对待处理的意图造成三重响应。
    • 刚刚更新了另一种可能性和一些至少对我有用的示例代码!
    • 你是对的,因为我再次注册它 n 再次感谢您的快速 n 描述性响应 n 代码示例它也有助于 +1
    • @zeetoobiker 你的例子可以证明是一个很大的帮助,只是想知道“partInfo”是什么以及你在哪里声明它? +1
    【解决方案2】:

    或者你可以为寄存器做一个单例类:

    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;
    }
    

    }

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-03-08
      • 1970-01-01
      • 2013-09-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多