2012-06-06 31 views
5

我最近問了一個關於檢查已發送短信狀態的問題,給出的答案是一個代碼片段,它註冊了兩個「匿名內部」(請糾正我的術語,如果它不正確)BroadcastReceivers收聽SMS發送/傳送的廣播。這些接收者只需要接收我剛剛發送的短信的數據,因此不需要永久收聽。我需要註銷'anonymous'BroadcastReceiver

我的直接想法是「好的,我需要在他們結束後取消註冊他們」,但這是正確的嗎?我問海報,因爲他沒有包含任何註銷代碼,但沒有回覆。該代碼似乎是一個非常標準的做我想做的事情,因爲它出現在衆多的Android開發網站上。這裏是:

//---sends an SMS message to another device--- 
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); 

    //---when the SMS has been sent--- 
    registerReceiver(new BroadcastReceiver(){ 
     @Override 
     public void onReceive(Context arg0, Intent arg1) { 
      switch (getResultCode()) 
      { 
       case Activity.RESULT_OK: 
        Toast.makeText(getBaseContext(), "SMS sent", 
          Toast.LENGTH_SHORT).show(); 
        break; 
       case SmsManager.RESULT_ERROR_GENERIC_FAILURE: 
        Toast.makeText(getBaseContext(), "Generic failure", 
          Toast.LENGTH_SHORT).show(); 
        break; 
       case SmsManager.RESULT_ERROR_NO_SERVICE: 
        Toast.makeText(getBaseContext(), "No service", 
          Toast.LENGTH_SHORT).show(); 
        break; 
       case SmsManager.RESULT_ERROR_NULL_PDU: 
        Toast.makeText(getBaseContext(), "Null PDU", 
          Toast.LENGTH_SHORT).show(); 
        break; 
       case SmsManager.RESULT_ERROR_RADIO_OFF: 
        Toast.makeText(getBaseContext(), "Radio off", 
          Toast.LENGTH_SHORT).show(); 
        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(); 
        break; 
       case Activity.RESULT_CANCELED: 
        Toast.makeText(getBaseContext(), "SMS not delivered", 
          Toast.LENGTH_SHORT).show(); 
        break;       
      } 
     } 
    }, new IntentFilter(DELIVERED));   

    SmsManager sms = SmsManager.getDefault(); 
    sms.sendTextMessage(phoneNumber, null, message, sentPI, deliveredPI); 

該代碼工作正常。

更重要的是,它不會收到我的應用程序外部發送的任何SMS發送/傳遞事件的通知。例如。在這些BroadcastReceivers已註冊之後,我可以發送短信,但沒有看到任何Toast消息。

所以,我有兩個問題:

  1. 我需要註銷這些BroadcastReceivers
  2. 如果不是,爲什麼不呢?

回答

0

您將需要取消註冊。否則,它很可能會崩潰。我很確定。但是,如果你說它沒有崩潰,那麼,好吧,需要看看它:)

因爲,Android會認爲你忘了取消註冊。它期望您取消註冊。 「注意:如果在你的Activity.onResume()實現中註冊一個接收者,你應該在Activity.onPause()中註銷它(當你暫停時你不會收到intent,這將減少不必要的系統開銷)。在Activity.onSaveInstanceState()中取消註冊,因爲如果用戶移回歷史堆棧中,將不會調用它。「 < =====從文檔

+0

你爲什麼認爲它會崩潰? – barry

+0

更新了我的答案。 –

+0

那麼,代碼是在不同的BroadcastReceiver(由AlarmManager喚醒),所以我沒有任何生命週期方法來做我的註銷。如果需要,我會在onReceive()的結尾處註銷註冊 – barry

1

您只需保存BroadcastReceiver到一個實例,這樣您就可以註銷其;-)

剛剛從改變這一行:

registerReceiver(new BroadcastReceiver(){ 

到:

BroadcastReceiver smsReceiver=new BroadcastReceiver(){...} 
registerReceiver(smsReceiver); 

稍後,您可以執行比:

unregisterReceiver(smsReceiver); 

請記住將smsReceiver保存爲班級成員。

+0

我不認爲我需要將BroadcastReceiver保存到一個實例 - 如果需要,我可以在onReceive()的末尾取消註冊。我只想知道是否有必要。正如我所說,這個代碼是在互聯網上點綴着,沒有註銷正在進行! – barry

0

所以,如果我理解你寫的正確,它看起來像BroadcastReceiver只應在sendSMS()調用中存在,所以即使他們註冊了SENTDELIVERED意圖,他們可能無法左右接收他們。另外,我相信你總是想在你完成它們時註銷接收器,我已經看到調試器警告接收器泄漏。

會更好地工作,如果你有一流的參數,像sent_broadcast_receiverdelivered_broadcast_receiver包含一個引用您正在註冊的接收器,這樣的對象依然存在,他們在完成後可被註銷。

編輯: 不管對象適用於SENTDELIVERED的BroadcastReceivers要持續到返回的意圖,或意圖(因爲他們是PendingIntents)應該直接的東西,可以被喚醒,如果這是你的願望。

+0

SMS BroadcastReceivers是在不同的由AlarmManager調用的BroadcastReceiver中創建的 - 即發生警報,​​並且我想發送SMS以便執行已在AlarmManager中註冊的BroadcastReceiver中的代碼片段。您建議將接收器作爲變量存儲在接收器中,以便它們保持不變,但如果廣播發生時警報接收器不在周圍,該怎麼辦?我需要服務嗎? – barry

+0

我並不是指你在AlarmManager中註冊的內容,而是指向「新的BroadcastReceiver」構造函數。實際上,您的代碼中似乎沒有任何註冊的AlarmManager。它爲SENT和DELIVERED創建兩個PendingIntents,爲這些Intents註冊方法範圍BroadcastReceivers,然後使用SmsManager。 –

+0

對不起,但你的編輯對我來說沒有意義 - 「......或意圖(因爲他們是PendingIntents)如此直接地指向某些可以喚醒的東西,如果這就是你的願望。」你能否請進一步解釋? – barry

1

更重要的是,它不會收到我的應用程序外部發送的任何SMS發送/傳遞事件的通知。

您正在動態註冊接收器。如果您想聽其他應用程序的意圖,則需要在清單文件中註冊您的接收器。這樣它將永遠活躍。你不需要註銷它。

相關問題