Registrar programáticamente un receptor de difusión

149

Me gustaría saber cuál es la mejor práctica / forma de registrar mediante programación un receptor de transmisión. Quiero registrar receptores específicos según la elección del usuario.

Como el registro se realiza a través del archivo de manifiesto, me pregunto si hay una manera adecuada de lograr esto en el código.

CoolStraw
fuente
2
CoderzPassion Broadcast Reciever es el mejor tutorial detallado de la historia
karanatwal.github.io

Respuestas:

64

Parece que desea controlar si los componentes publicados en su manifiesto están activos, no registrar dinámicamente un receptor (a través de Context.registerReceiver ()) mientras se ejecuta.

Si es así, puede usar PackageManager.setComponentEnabledSetting () para controlar si estos componentes están activos:

http://developer.android.com/reference/android/content/pm/PackageManager.html#setComponentEnabledSetting(android.content.ComponentName, int, int)

Tenga en cuenta que si solo está interesado en recibir una transmisión mientras se está ejecutando, es mejor usar registerReceiver (). Un componente receptor es principalmente útil para cuando necesita asegurarse de que su aplicación se inicia cada vez que se envía la transmisión.

hackbod
fuente
1
Listo! Me entendiste bien. Muchas gracias
CoolStraw
Nice one - no tenía idea de que podrías hacer esto :)
Chris Noldus
es similar stackoverflow.com/questions/24140894/…
Ankit Srivastava
1
@hackbod ¿Cómo se puede agregar una etiqueta de metadatos en un receptor personalizado? Tienes alguna idea !! Necesito agregar una etiqueta de metadatos que usamos en androidmanifest.xml.
Zala Janaksinh
1
El mejor tutorial hasta la fecha coderzpassion.com/implement-broadcastreceiver-android y en lenguaje simple
Jagjit Singh
269

En su onCreatemétodo, puede registrar un receptor como este:

private BroadcastReceiver receiver;

@Override
public void onCreate(Bundle savedInstanceState){

  // your oncreate code should be

  IntentFilter filter = new IntentFilter();
  filter.addAction("SOME_ACTION");
  filter.addAction("SOME_OTHER_ACTION");

  receiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
      //do something based on the intent's action
    }
  };
     registerReceiver(receiver, filter);
}

Recuerde ejecutar esto en el onDestroymétodo:

 @Override
 protected void onDestroy() {
  if (receiver != null) {
   unregisterReceiver(receiver);
   receiver = null;
  }
  super.onDestroy();
 }
Eric Nordvik
fuente
19
Gracias, esto funcionó muy bien. Para enviar la transmisión utilicé el código Intent i = new Intent ("SOME_ACTION"); sendBroadcast (i);
Ben Clayton
77
¿Por qué no en currículum vitae y en inicio?
Syed Raza Mehdi
¿Qué pasaría si no cancelo el registro del receptor de transmisión? ¿Dejaría el receptor de transmisión registrado, incluso después de reiniciar?
Jaydev
55
No se garantiza que onDestroy()se llamará, creando así una posible pérdida de memoria. Es mejor registrarse / cancelar el registro en onStart()/ onStop().
Neria Nachum
¿Esto significa que no tengo que crear una clase de receptor de difusión? ¿Podría poner todo mi código onReceive () aquí y funcionaría?
Taslim Oseni
70

Un punto importante que la gente olvida mencionar es el tiempo de vida del Broadcast Receiver. La diferencia de registrarlo programáticamente con respecto al registro en AndroidManifest.xml es esa. En el archivo de manifiesto, no depende del tiempo de vida de la aplicación. Mientras que al registrarlo programáticamente depende del tiempo de vida de la aplicación. Esto significa que si se registra en AndroidManifest.xml , puede captar las intenciones emitidas incluso cuando su aplicación no se está ejecutando.

Editar: la nota mencionada ya no es cierta a partir de Android 3.1, el sistema Android excluye a todos los receptores de recibir intenciones de forma predeterminada si el usuario nunca ha iniciado la aplicación correspondiente o si el usuario la detuvo explícitamente a través del menú de Android (en Gestionar → Aplicación). https://developer.android.com/about/versions/android-3.1.html

Esta es una característica de seguridad adicional ya que el usuario puede estar seguro de que solo las aplicaciones que inició recibirán intenciones de transmisión.

Por lo tanto, puede entenderse que los receptores registrados mediante programación en la aplicación onCreate()tendrían el mismo efecto que los declarados en AndroidManifest.xml de Android 3.1 anterior.

Criptón
fuente
1
Esta es una buena nota. De hecho, estoy mirando un libro que estoy leyendo sobre Android y me pregunto por qué se han realizado los dos métodos para implementar la transmisión. Me parece que es por compatibilidad con versiones anteriores. Pero no estoy seguro sin embargo.
Neon Warge
Bueno, ¿realmente crees que la edición es verdadera? Me refiero a la última oración. Es probable que Android elimine su aplicación en cualquier momento, lo que provocará que sus receptores registrados mediante programación ya no funcionen, pero el manifiesto registrado seguirá funcionando.
JacksOnF1re
40

Defina un receptor de difusión en cualquier lugar de Actividad / Fragmento como este:

mReceiver = new BroadcastReceiver() {
 @Override
 public void onReceive(Context context, Intent intent) {
     Log.d(TAG," onRecieve"); //do something with intent
   }
 };

Definir IntentFilter en onCreate()

mIntentFilter=new IntentFilter("action_name");

Ahora registre el BroadcastReciever en onResume()y anule el registro en onPause()[porque no hay uso de la transmisión si la actividad está en pausa].

@Override
protected void onResume() {
     super.onResume();
     registerReceiver(mReceiver, mIntentFilter);
}

@Override
protected void onPause() {
    if(mReceiver != null) {
            unregisterReceiver(mReceiver);
            mReceiver = null;
    }
    super.onPause();
}

Para un tutorial detallado, eche un vistazo al receptor de transmisión: dos formas de implementarlo .

SohailAziz
fuente
¡El mejor ejemplo que he encontrado hasta ahora! ¡Gracias!
Ayush Goyal
1
@SohailAziz El enlace proporciona una buena respuesta. ¿Podría poner el contexto del enlace en su respuesta, de modo que si el enlace se cae, su respuesta sigue siendo relevante?
iRuth
En mi opinión personal, la transmisión debe registrarse en onResume y onPause como sugirió, pero algunas personas dicen que debe estar en onCreate y onDestroy, ¿puede explicar los pros y los contras de ambos?
Syed Raza Mehdi
2
@SyedRazaMehdi si la transmisión se usa para actualizar la interfaz de usuario [que es en la mayoría de los casos], debe registrarla en onResume y anular el registro en onPause porque la transmisión será inútil de lo contrario.
SohailAziz
Gracias, esta es la mejor respuesta.
Saeid Z
4
package com.example.broadcastreceiver;


import android.app.Activity;
import android.content.IntentFilter;
import android.os.Bundle;
import android.view.Menu;
import android.view.View;
import android.widget.Toast;

public class MainActivity extends Activity {

   UserDefinedBroadcastReceiver broadCastReceiver = new UserDefinedBroadcastReceiver();

   @Override
   public void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main);
   }

   @Override
   public boolean onCreateOptionsMenu(Menu menu) {
      getMenuInflater().inflate(R.menu.main, menu);
      return true;
   }

   /**
    * This method enables the Broadcast receiver for
    * "android.intent.action.TIME_TICK" intent. This intent get
    * broadcasted every minute.
    *
    * @param view
    */
   public void registerBroadcastReceiver(View view) {

      this.registerReceiver(broadCastReceiver, new IntentFilter(
            "android.intent.action.TIME_TICK"));
      Toast.makeText(this, "Registered broadcast receiver", Toast.LENGTH_SHORT)
            .show();
   }

   /**
    * This method disables the Broadcast receiver
    *
    * @param view
    */
   public void unregisterBroadcastReceiver(View view) {

      this.unregisterReceiver(broadCastReceiver);

      Toast.makeText(this, "unregistered broadcst receiver", Toast.LENGTH_SHORT)
            .show();
   }
}
Sunil Pandey
fuente
1
¿Puede explicarle a OP por qué esta es la mejor práctica?
Martin Prikryl
1
No explican, "ellos" siempre publican código, porque es mucho mejor lo sabes. -sarcasm
Neon Warge
2

Según escuchar y transmitir mensajes globales y configurar alarmas en tareas comunes y cómo hacerlas en Android :

Si la clase receptora no está registrada utilizando su manifiesto, puede crear instancias y registrar dinámicamente un receptor llamando a Context.registerReceiver () .

Eche un vistazo a registerReceiver (receptor BroadcastReceiver, filtro IntentFilter) para obtener más información.

McStretch
fuente
1
Traté de llamar, context.registerReceiverpero no se llama, ¿puedes mirar esta pregunta? stackoverflow.com/questions/13238600/…
Caza el
2

Es una buena práctica proporcionar siempre el permiso al registrar el receptor; de lo contrario, recibirá cualquier solicitud que envíe una intención coincidente. Esto puede permitir que las aplicaciones maliciosas se transmitan a su receptor.

ChopperCharles
fuente
1

para LocalBroadcastManager

   Intent intent = new Intent("any.action.string");
   LocalBroadcastManager.getInstance(context).
                                sendBroadcast(intent);

y registrarse en onResume

LocalBroadcastManager.getInstance(
                    ActivityName.this).registerReceiver(chatCountBroadcastReceiver, filter);

y anular el registro onStop

LocalBroadcastManager.getInstance(
                ActivityName.this).unregisterReceiver(chatCountBroadcastReceiver);

y recíbelo ..

mBroadcastReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            Log.e("mBroadcastReceiver", "onReceive");
        }
    };

donde IntentFilter es

 new IntentFilter("any.action.string")
Zar E Ahmer
fuente
1

Dos opciones

1) Si desea leer Broadcast solo cuando la Actividad está visible, entonces,

registerReceiver(...) en onStart()y unregisterReceiver(...)enonStop()

2) Si desea leer Broadcast, incluso si la Actividad está en segundo plano, entonces,

registerReceiver(...)dentro onCreate(...)y unregisterReceiver(...)dentroonDestroy()

Prima:

Si eres vago

Si no desea escribir código repetitivo para registrar y anular el registro de un BroadcastReceiver una y otra vez en cada Actividad, entonces,

  1. Crear una actividad abstracta
  2. Escribir código repetitivo en la actividad
  3. Deje la implementación como métodos abstractos.

Aquí está el fragmento de código:

Actividad abstracta

public abstract class BasicActivity extends AppCompatActivity {

    private BroadcastReceiver broadcastReceiver;
    private IntentFilter filter;
    private static final String TAG = "BasicActivity";

    /**********************************************************************
    *                   Boilerplate code
    **********************************************************************/

    @Override
    public void onCreate(Bundle sis){
        super.onCreate(sis);
        broadcastReceiver = getBroadcastReceiver();
        filter = getFilter();
    }

    @Override
    public void onStart(){
        super.onStart();
        register();
    }

    @Override
    public void onStop(){
        super.onStop();
        unregister();
    }

    private void register(){
        registerReceiver(broadcastReceiver,filter);
    }

    private void unregister(){
        unregisterReceiver(broadcastReceiver);
    }

    /**********************************************************************
    *                   Abstract methods
    **********************************************************************/

    public abstract BroadcastReceiver getBroadcastReceiver();

    public abstract IntentFilter getFilter();

}

Con este enfoque, puede escribir más código repetitivo, como escribir animaciones comunes, vincular a un servicio, etc.

Ver código completo:

AQUÍ

Rohit Singh
fuente
0

Crear un receptor de difusión

[BroadcastReceiver (Habilitado = verdadero, Exportado = falso)]

public class BCReceiver : BroadcastReceiver
{

    BCReceiver receiver;

    public override void OnReceive(Context context, Intent intent)
    {
        //Do something here
    }
}

Desde su actividad agregue este código:

LocalBroadcastManager.getInstance(ApplicationContext)
    .registerReceiver(receiver, filter);
fulgen
fuente