2012-03-13 53 views
2

儀式現在我試圖通過編程方式使用以下代碼發送短信,但我不明白SMS SENT Receiver的行爲。短信通知的行爲

1)例如,如果我發送一個SMS然後Activity.RESULT_OK內部 registerReceiver正在被呼叫的3倍。如果我發送3短信使用 爲loopby調用sendSMS然後Activity.RESULT_OK正在 調用9次。現在我真的不知道一個短信發送爲什麼這個 registerReceiver被稱爲這麼多次?

2)此外,當我運行這段代碼在模擬器我通過模擬器 端口發送短信到其他仿真這是很自然的,但是當我嘗試 發送短信到一個真實的號碼,然後我沒有得到短信發送失敗 通知,因爲它通知Activity.RESULT_OK

代碼發送SMS

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

回答

6

通常這取決於m的大小您要發送的消息 - 如果消息超過單個消息限制(在您的情況下,它聽起來像是單個消息限制的約3倍),那麼您將收到消息每個部分的發送和遞送報告。由於您沒有手動分割訊息,因此無法爲每個聲部指定不同的意圖。

值得看看SmsManager.divideMessage()自己拆分消息,然後在SmsManager.sendMultiPartTextMessage()做實際的發送。這允許您爲消息的不同部分指定不同的待定目標,因此您可以確定消息何時最終發送。

我認爲模擬器將所有消息目標視爲準確,並且因爲沒有網絡可以回來並且說不然你可能不會從模擬器發送失敗(除非你做了類似將模擬器放在飛機上的東西模式)。根據經驗,您肯定會在真實設備上獲取這些錯誤代碼。

編輯: 它你也註冊在每次發送郵件時接收思考,我用的代碼有一個清單註冊的接收器。有可能你已經多次註冊它(它只要註冊的上下文一直存在),這會多次給你 - 這也會使它重複可能9次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> 
+0

以及我的短信文本是「John Right,這是我的簡單信息!」 ,所以這段文字沒有那麼長吧?那麼仍然需要使用divideMessage? – Hunt 2012-03-13 08:26:26

+0

還有一個需要(由於HTC的bug - 這是令人討厭的,然後它擊中我的應用程序),但它不應該導致未決意圖的三重響應。 – zeetoobiker 2012-03-13 09:21:10

+0

只是更新了另一種可能性和一些示例代碼,至少適合我! – zeetoobiker 2012-03-13 09:36:54

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

}