2012-06-06 11 views
5

Hace poco hice una pregunta sobre la comprobación del estado de un SMS enviado y la respuesta fue un fragmento de código que registró dos 'anónimos internos' (corrija mi terminología si es incorrecta) BroadcastReceivers para escuchar transmisiones enviadas/entregadas por SMS. Estos receptores solo tenían que recibir datos sobre el SMS que acababa de enviar mi aplicación, por lo que no estaban obligados a escuchar de forma permanente.Necesito cancelar el registro de BroadcastReceiver 'anónimo'

Mi pensamiento inmediato fue "bueno, tendré que cancelar el registro después de que haya terminado con ellos", pero ¿es esto correcto? Le pregunté al póster esto porque no había incluido ningún código para anular el registro, pero no obtuve respuesta. El código parece ser una forma bastante estándar de hacer lo que quiero, ya que aparece en numerosos sitios de desarrollo de Android. Aquí está:

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

El código funciona bien.

Además, no recibe ninguna notificación de ningún evento enviado/entregado por SMS que ocurra fuera de mi aplicación. P.ej. Puedo enviar un SMS después de que se hayan registrado estos BroadcastReceivers y no vea ningún mensaje Toast.

lo tanto, tengo dos preguntas:

  1. Qué necesito para anular el registro de estos BroadcastReceivers?
  2. Si no, ¿por qué no?

Respuesta

0

Necesitarás cancelar el registro. De lo contrario, probablemente se bloquee. Estoy bastante seguro de eso. Pero si dices que no está fallando, entonces, bueno, necesitas investigarlo :)

Porque, Android pensará que olvidaste anular el registro. Espera que canceles el registro. "Nota: si registra un receptor en su implementación de Activity.onResume(), debe anular el registro en Activity.onPause(). (No recibirá los intentos cuando esté en pausa, y esto reducirá la sobrecarga innecesaria del sistema). No lo haga anular el registro en Activity.onSaveInstanceState(), porque no se invocará si el usuario se mueve de nuevo en la pila del historial. " < ===== Desde los documentos

+0

¿Por qué crees que debería bloquearse? – barry

+0

Actualización de mi respuesta. –

+0

Bueno, el código está en un BroadcastReceiver diferente (despertado por AlarmManager) por lo que no tengo ningún método de ciclo de vida para hacer mi anulación de registro. Me gustaría poner el anulando el registro al final de onReceive() si es necesario – barry

1

Basta con guardar su BroadcastReceiver a una instancia de modo que son capaces de anular el registro ;-)

acaba de cambiar esta línea de:

registerReceiver(new BroadcastReceiver(){ 

a:

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

Más tarde se puede ejecutar que:

unregisterReceiver(smsReceiver); 

Recuerde guardar el smsReceiver como miembro de la clase.

+0

No creo que tenga que guardar el BroadcastReceiver en una instancia; podría anular el registro al final de onReceive() si es necesario. Solo me gustaría saber si es necesario. ¡Como digo, este código está salpicado en Internet sin que nada de anular el registro continúe! – barry

0

Así que si entiendo lo que has escrito correctamente, parece que la única BroadcastReceiver debe existir dentro de la llamada sendSMS(), por lo que a pesar de que están registrados para los SENT o DELIVERED Propósitos, no puede haber en torno a recibirlos. Además, creo que siempre deseas anular el registro de receptores cuando termines con ellos, he visto al depurador advertir sobre receptores con fugas.

¿Funcionaría mejor si tuviera parámetros de clase para sent_broadcast_receiver y que contienen una referencia a los receptores que está registrando, de esa manera los objetos persisten, y pueden ser no registrados después de que hayan terminado.

EDIT: Cualquiera que sea objeto contiene los BroadcastReceivers para SENT y DELIVERED debe persistir hasta que los intentos de retorno o de los intentos (ya que son PendingIntents) se puede desviar hacia algo que puede ser despertada, si eso es lo que desea.

+0

SMS BroadcastReceivers se crean en un BroadcastReceiver diferente al que llama el AlarmManager, es decir, se produce una alarma y deseo enviar un SMS para ejecutar el fragmento de código en el BroadcastReceiver que se registró con el AlarmManager. Sugiere almacenar los receptores como variables en este receptor para que persistan, pero ¿qué pasa si el receptor de alarma no está presente cuando ocurre la transmisión? ¿Necesito un servicio? – barry

+0

No me refería a lo que registra con el AlarmManager, sino a los "nuevos rectores de BroadcastReceiver". En realidad, parece que no hay ningún registro con el AlarmManager en su código. Crea dos PendingIntents para SENT y ENTREGADO, registra el alcance del método BroadcastReceivers para esos Intents y luego usa SmsManager. –

+0

Lo siento, pero su edición no tiene sentido para mí: "... o los Intents (ya que son PendingIntents) tan directos a algo que puede despertarse, si eso es lo que desea". ¿Puedes explicar más? – barry

1

Además, no se notifica de ningún SMS enviado/entregado eventos que ocurren de forma externa a mi aplicación.

Está registrando dinámicamente los receptores. Si desea escuchar las intenciones de otras aplicaciones, debe registrar su receptor en el archivo de manifiesto. De esa manera siempre estará activo. Y no necesitarás anular el registro.

Cuestiones relacionadas