2012-01-31 17 views
23

Sto provando il seguente esempio di sms da: http://mobiforge.com/developing/story/sms-messaging-android ma sto ricevendo la seguente eccezione se provo a inviare messaggi.IntentRecieverLeakedException, Ti manca una chiamata a unregisterReceiver()? in Android

Exception: 
    02-07 12:38:15.447: ERROR/ActivityThread(839): Activity com.micro.MyTest has leaked IntentReceiver [email protected] 
that was originally registered here. Are you missing a call to 
unregisterReceiver()? 
    02-07 12:38:15.447: ERROR/ActivityThread(839): android.app.IntentReceiverLeaked: Activity com.test.SendSMS has leaked 
IntentReceiver com.test.SendSMS [email protected] that was originally 
registered here. Are you missing a call to unregisterReceiver()? 
    02-07 12:38:15.447: ERROR/ActivityThread(839):  at android.app.ActivityThread$PackageInfo$ReceiverDispatcher.<init>(ActivityThread.java:707) 
    02-07 12:38:15.447: ERROR/ActivityThread(839):  at android.app.ActivityThread$PackageInfo.getReceiverDispatcher(ActivityThread.java:535) 
    02-07 12:38:15.447: ERROR/ActivityThread(839):  at android.app.ApplicationContext.registerReceiverInternal(ApplicationContext.java:748) 
    02-07 12:38:15.447: ERROR/ActivityThread(839):  at android.app.ApplicationContext.registerReceiver(ApplicationContext.java:735) 
    02-07 12:38:15.447: ERROR/ActivityThread(839):  at android.app.ApplicationContext.registerReceiver(ApplicationContext.java:729) 
    02-07 12:38:15.447: ERROR/ActivityThread(839):  at android.content.ContextWrapper.registerReceiver(ContextWrapper.java:278) 
    02-07 12:38:15.447: ERROR/ActivityThread(839):  at com.micro.MyTest.sendSMS(SendSMS .java:98) 
    02-07 12:38:15.447: ERROR/ActivityThread(839):  at com.micro.MyTest.onCreate(SendSMS .java:42) 
    02-07 12:38:15.447: ERROR/ActivityThread(839):  at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1123) 
    02-07 12:38:15.447: ERROR/ActivityThread(839):  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2231) 
    02-07 12:38:15.447: ERROR/ActivityThread(839):  at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2284) 
    02-07 12:38:15.447: ERROR/ActivityThread(839):  at android.app.ActivityThread.access$1800(ActivityThread.java:112) 
    02-07 12:38:15.447: ERROR/ActivityThread(839):  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1692) 
    02-07 12:38:15.447: ERROR/ActivityThread(839):  at android.os.Handler.dispatchMessage(Handler.java:99) 
    02-07 12:38:15.447: ERROR/ActivityThread(839):  at android.os.Looper.loop(Looper.java:123) 
    02-07 12:38:15.447: ERROR/ActivityThread(839):  at android.app.ActivityThread.main(ActivityThread.java:3948) 
    02-07 12:38:15.447: ERROR/ActivityThread(839):  at java.lang.reflect.Method.invokeNative(Native Method) 
    02-07 12:38:15.447: ERROR/ActivityThread(839):  at java.lang.reflect.Method.invoke(Method.java:521) 
    02-07 12:38:15.447: ERROR/ActivityThread(839):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:782) 
    02-07 12:38:15.447: ERROR/ActivityThread(839):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:540) 
    02-07 12:38:15.447: ERROR/ActivityThread(839):  at dalvik.system.NativeStart.main(Native Method) 
    02-07 12:38:15.496: ERROR/ActivityThread(839): Activity com.micro.MyTest has leaked IntentReceiver [email protected] 
that was originally registered here. Are you missing a call to 
unregisterReceiver()? 
    02-07 12:38:15.496: ERROR/ActivityThread(839): android.app.IntentReceiverLeaked: Activity com.test.SendSMS has leaked 
IntentReceiver com.test.SendSMS [email protected] that was originally 
registered here. Are you missing a call to unregisterReceiver()? 
    02-07 12:38:15.496: ERROR/ActivityThread(839):  at android.app.ActivityThread$PackageInfo$ReceiverDispatcher.<init>(ActivityThread.java:707) 
    02-07 12:38:15.496: ERROR/ActivityThread(839):  at android.app.ActivityThread$PackageInfo.getReceiverDispatcher(ActivityThread.java:535) 
    02-07 12:38:15.496: ERROR/ActivityThread(839):  at android.app.ApplicationContext.registerReceiverInternal(ApplicationContext.java:748) 
    02-07 12:38:15.496: ERROR/ActivityThread(839):  at android.app.ApplicationContext.registerReceiver(ApplicationContext.java:735) 
    02-07 12:38:15.496: ERROR/ActivityThread(839):  at android.app.ApplicationContext.registerReceiver(ApplicationContext.java:729) 
    02-07 12:38:15.496: ERROR/ActivityThread(839):  at android.content.ContextWrapper.registerReceiver(ContextWrapper.java:278) 
    02-07 12:38:15.496: ERROR/ActivityThread(839):  at com.micro.MyTest.sendSMS(SendSMS .java:129) 
    02-07 12:38:15.496: ERROR/ActivityThread(839):  at com.micro.MyTest.onCreate(SendSMS .java:42) 
    02-07 12:38:15.496: ERROR/ActivityThread(839):  at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1123) 
    02-07 12:38:15.496: ERROR/ActivityThread(839):  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2231) 
    02-07 12:38:15.496: ERROR/ActivityThread(839):  at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2284) 
    02-07 12:38:15.496: ERROR/ActivityThread(839):  at android.app.ActivityThread.access$1800(ActivityThread.java:112) 
    02-07 12:38:15.496: ERROR/ActivityThread(839):  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1692) 
    02-07 12:38:15.496: ERROR/ActivityThread(839):  at android.os.Handler.dispatchMessage(Handler.java:99) 
    02-07 12:38:15.496: ERROR/ActivityThread(839):  at android.os.Looper.loop(Looper.java:123) 
    02-07 12:38:15.496: ERROR/ActivityThread(839):  at android.app.ActivityThread.main(ActivityThread.java:3948) 
    02-07 12:38:15.496: ERROR/ActivityThread(839):  at java.lang.reflect.Method.invokeNative(Native Method) 
    02-07 12:38:15.496: ERROR/ActivityThread(839):  at java.lang.reflect.Method.invoke(Method.java:521) 
    02-07 12:38:15.496: ERROR/ActivityThread(839):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:782) 
    02-07 12:38:15.496: ERROR/ActivityThread(839):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:540) 
    02-07 12:38:15.496: ERROR/ActivityThread(839):  at dalvik.system.NativeStart.main(Native Method) 

Il metodo che invia sms:

publicvoid 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, the following line (line 98) throws Exception 

    registerReceiver(
    new BroadcastReceiver(){ 

     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() { 

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

} 

risposta

47

nella classe di attività, dichiarare queste variabili globali:

private BroadcastReceiver sendBroadcastReceiver; 
private BroadcastReceiver deliveryBroadcastReceiver; 
String SENT = "SMS_SENT"; 
String DELIVERED = "SMS_DELIVERED"; 

esclusione onCreate della vostra attività e registrare i vostri ricevitori:

@Override 
protected void onCreate(Bundle savedInstanceState) 
{ 
    super.onCreate(savedInstanceState); 
    sendBroadcastReceiver = new BroadcastReceiver() 
    { 

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

    deliveryBroadcastReceiver = new BroadcastReceiver() 
    { 
     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; 
      } 
     } 
    }; 
registerReceiver(deliveryBroadcastReceiver, new IntentFilter(DELIVERED)); 
registerReceiver(sendBroadcastReceiver , new IntentFilter(SENT)); 
} 

prossimo, il metodo di invio SMS è lasciato con solo 6 righe di codice:

public 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); 
    SmsManager sms = SmsManager.getDefault(); 
    sms.sendTextMessage(phoneNumber, null, message, sentPI, deliveredPI); 
} 

, infine, annullare la registrazione i ricevitori sulla fermata della vostra attività:

@Override 
protected void onStop() 
{ 
    unregisterReceiver(sendBroadcastReceiver); 
    unregisterReceiver(deliveryBroadcastReceiver); 
    super.onStop(); 
} 
+0

ok thanq ... Dove dovrei aggiungere il codice per registerReceiver? – user2012

+0

scusami mi sono perso. ho aggiornato la mia risposta. (chiamare il ricevitore del registro nel metodo 'onCreate') –

+0

non ha funzionato? –

0

L'errore è molto esplicito circa il tuo problema. Non stai chiamando unregisterReceiver() per il BroadcastReceiver che hai registrato con registerReceiver().

+0

: ok, grazie per la risposta. se uso [link] (http://code.google.com/p/krvarma-android-samples/source/browse/trunk/SMSDemo/src/com/varma/samples/smsdemo/MainActivity.java) in questo esempio sto ricevendo la seguente eccezione Uncaught handler: thread main exiting a causa dell'eccezione non rilevata java.lang.RuntimeException: Errore durante la ricezione di Intent {action = SMS_SENT} in [email protected] . . . Causato da: java.lang.NullPointerException -----------> qui sto annullando la registrazione dei ricevitori, quindi anche la sua venuta. – user2012

0

durante la registrazione:

rec = new BroadcastReceiver() 
{ 
.... 
} 

per evitare ricevitore perdita:

onStop() 
{ 
super.onStop(); 
unregisterReciever(rec); 
} 
+0

grazie per la risposta, posso usare lo stesso nome broadcastReceiver per gli intenti inviati e inviati? come registerReceiver (rec = new BroadcastReceiver() ....... ..... }, nuovo IntentFilter (SENT)); e registerReceiver (rec = new BroadcastReceiver() ....... ..... }, nuovo IntentFilter (DELIVERED)); – user2012

+1

sei quasi vicino. dovrebbe essere così: 'rec = new BroadcastReceiver(); Filtro IntentFilter = new IntentFilter(); filter.addAction ("ACTION1"); filter.addAction ("ACTION2"); registerReceiver (rec, filter); ' è necessario porre questa domanda a parte. (Si prega di segnare anche la risposta per la vostra domanda originale) –

+0

ok .. può per favore dirmi dove dovrei fare modifiche nel codice di cui sopra. – user2012

1

Utilizzare i seguenti due classi per evitare questo problema

import android.app.Activity; 
import android.content.BroadcastReceiver; 
import android.content.Context; 
import android.content.Intent; 
import android.util.Log; 

public class SmsDeliveredReceiver extends BroadcastReceiver { 
    @Override 
    public void onReceive(Context context, Intent arg1) { 
     switch (getResultCode()) { 
     case Activity.RESULT_OK: 
      Log.d("httpmon", "SMS delivered"); 
      break; 
     case Activity.RESULT_CANCELED: 
      Log.d("httpmon", "SMS not delivered"); 
      break; 
     } 
    } 
} 

e questo per il destinatario di invio SMS

import java.util.Collections; 
import java.util.HashMap; 
import android.app.Activity; 
import android.content.BroadcastReceiver; 
import android.content.Context; 
import android.content.Intent; 
import android.os.PowerManager; 
import android.os.PowerManager.WakeLock; 
import android.telephony.gsm.SmsManager; 
import android.util.Log; 

public class SmsSentReceiver extends BroadcastReceiver { 
    @Override 
    public void onReceive(Context context, Intent arg1) { 
     switch (getResultCode()) { 
     case Activity.RESULT_OK: 
      Log.d("httpmon", "SMS sent"); 
      break; 
     case SmsManager.RESULT_ERROR_GENERIC_FAILURE: 
      Log.d("httpmon", "SMS generic failure"); 
      break; 
     case SmsManager.RESULT_ERROR_NO_SERVICE: 
      Log.d("httpmon", "SMS no service"); 
      break; 
     case SmsManager.RESULT_ERROR_NULL_PDU: 
      Log.d("httpmon", "SMS null PDU"); 
      break; 
     case SmsManager.RESULT_ERROR_RADIO_OFF: 
      Log.d("httpmon", "SMS radio off"); 
      break; 
     } 
    } 
} 

e, infine, il ricevitore impostato nel file manifesto

<receiver android:name=".SmsSentReceiver"> 
      <intent-filter> 
       <action android:name="SMS_SENT" /> 
      </intent-filter> 
     </receiver> 
     <receiver android:name=".SmsDeliveredReceiver"> 
      <intent-filter> 
       <action android:name="SMS_DELIVERED" /> 
      </intent-filter> 
     </receiver> 
+0

thanq ... puoi dirmi come chiamare queste classi dall'invio della funzione? – user2012

+1

Non è necessario chiamare queste classi. Queste classi riceveranno il messaggio trasmesso. È possibile ricevere gli extra di intent impostati su questi intenti in sospeso. Stringa SENT = "SMS_SENT"; String DELIVERED = "SMS_DELIVERED"; PendingIntent sentPI = PendingIntent.getBroadcast (this, 0, new Intent (SENT), 0); PendingIntent deliveryPI = PendingIntent.getBroadcast (this, 0, new Intent (DELIVERED), 0); SmsManager sms = SmsManager.getDefault(); sms.sendTextMessage (phoneNumber, null, message, sentPI, deliveredPI); –

+0

@VinothkumarArputharaj Ho implementato la tua soluzione e funziona alla grande. Ma ho incontrato un comportamento curioso. Se ho impostato su un Loop, continuo a ricevere lo stesso ID per tutti i loop 0,1,2,3,4 L'extra Intent sempre è 0 Qualsiasi idea? – eddwinpaz

0

ho risolto con questo:

@Override 
public void onReceive(Context arg0, Intent arg1) { 
    switch (getResultCode()) { 
... 
    unregisterReceiver(this); 
} 

L'ultima cosa da fare è quello di annullare la registrazione Broadcast in OnReceive

pieno :

BroadcastReceiver smsReceiver = new BroadcastReceiver() { 
      @Override 
      public void onReceive(Context arg0, Intent arg1) { 
       switch (getResultCode()) { 
       case Activity.RESULT_OK: 
        if (Settings.registrarSucesso) { 
         ... 
        } 
        break; 
       case SmsManager.RESULT_ERROR_GENERIC_FAILURE: 
        ... 
        } 
        break; 
       case SmsManager.RESULT_ERROR_NO_SERVICE: 
        ... 
        break; 
       case SmsManager.RESULT_ERROR_NULL_PDU: 
        ... 
        break; 
       case SmsManager.RESULT_ERROR_RADIO_OFF: 
        ... 
        break; 
       } 
       unregisterReceiver(this); 
       adapter.notifyDataSetChanged(); 
      } 
     }; 
0

provare

private void sendSMS() 
{ 
    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); 
    SmsManager sms = SmsManager.getDefault(); 
    sms.sendTextMessage(phoneNumber, null, message, sentPI, deliveredPI); 
    sendBroadcastReceiver = new BroadcastReceiver() 
    { 

     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; 
      } 
    unregisterReceiver(sendBroadcastReceiver);//add here 
     } 
    }; 

    deliveryBroadcastReceiver = new BroadcastReceiver() 
    { 
     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; 
      } 
    unregisterReceiver(deliveryBroadcastReceiver);//add here 
     } 

    }; 
registerReceiver(deliveryBroadcastReceiver, new IntentFilter(DELIVERED)); 
registerReceiver(sendBroadcastReceiver , new IntentFilter(SENT)); 
} 
+0

Cosa succede se l'utente apre 'Attività', ma non invia un SMS? Inoltre, non tutti i corrieri offrono rapporti di consegna e se il dispositivo non ne riceve uno, il Ricevitore di consegna non verrà mai eseguito. È meglio semplicemente annullare la registrazione dei ricevitori in un metodo del ciclo di vita 'Activity'. –

+0

Questo codice aggiunge la funzione sendSMS o sendMMS –

+0

Hai ancora lo stesso problema se uno di questi ricevitori non funziona. Come ho detto, la consegna "PendingIntent" in particolare potrebbe benissimo non sparare, e finirai con lo stesso identico problema descritto nella domanda. –

0

onCreate & onStop non sono sempre posti migliori per register & unregister quando si mantiene storia di attività. È necessario inserire registerReceiver & unregisterReceiver in onResume & onPause.

@Override 
protected void onResume() { 
    registerReceiver(deliveryBroadcastReceiver, new IntentFilter(DELIVERED)); 
    registerReceiver(sendBroadcastReceiver , new IntentFilter(SENT)); 
    super.onResume(); 
} 

@Override 
protected void onPause() { 
    try { 
     unregisterReceiver(sendBroadcastReceiver); 
     unregisterReceiver(deliveryBroadcastReceiver); 
    } catch (IllegalArgumentException ex) { 
     // If Receiver not registered 
    } 
    super.onPause(); 
} 
Problemi correlati