¿Cómo usar LocalBroadcastManager?

452

¿Cómo usar / localizar LocalBroadcastManagercomo se describe en Google Docs y Service Broadcast Doc ?

Intenté buscarlo en Google, pero ¿no hay un código disponible para comenzar?

Los documentos dicen que debería usarlo si quiero hacer una transmisión interna en el proceso de mi aplicación, pero no sé dónde buscar esto.

¿Alguna ayuda / comentario?

Actualización : sé cómo usar transmisiones pero no sé cómo estar LocalBroadcastManagerdisponible en mi proyecto.

waqaslam
fuente
Waqas, ¿has registrado el receptor en manifiesto? En caso afirmativo, hágame saber cómo.
Mudassir
2
No creo que necesite registrar el receptor para tales transmisiones en manifiesto, porque si lo hace, ese receptor también escuchará las transmisiones globales.
waqaslam
2
Cierto. Entonces esto significa que tengo que hacerlo en código como se indica en la respuesta a continuación; LocalBroadcastManager.getInstance(this).registerReceiver(mMessageReceiver, new IntentFilter("custom-event-name"));
Mudassir
2
LocalBroadcastManagerha quedado en desuso Reemplacé la mía con la biblioteca EventBus, que es mucho mejor, en mi opinión.
Kris B

Respuestas:

862

Contestaré esto de todos modos. Por si acaso alguien lo necesita.

ReceiverActivity.java

Una actividad que busca notificaciones para el evento nombrado "custom-event-name".

@Override
public void onCreate(Bundle savedInstanceState) {

  ...

  // Register to receive messages.
  // We are registering an observer (mMessageReceiver) to receive Intents
  // with actions named "custom-event-name".
  LocalBroadcastManager.getInstance(this).registerReceiver(mMessageReceiver,
      new IntentFilter("custom-event-name"));
}

// Our handler for received Intents. This will be called whenever an Intent
// with an action named "custom-event-name" is broadcasted.
private BroadcastReceiver mMessageReceiver = new BroadcastReceiver() {
  @Override
  public void onReceive(Context context, Intent intent) {
    // Get extra data included in the Intent
    String message = intent.getStringExtra("message");
    Log.d("receiver", "Got message: " + message);
  }
};

@Override
protected void onDestroy() {
  // Unregister since the activity is about to be closed.
  LocalBroadcastManager.getInstance(this).unregisterReceiver(mMessageReceiver);
  super.onDestroy();
}

SenderActivity.java

La segunda actividad que envía / difunde notificaciones.

@Override
public void onCreate(Bundle savedInstanceState) {

  ...

  // Every time a button is clicked, we want to broadcast a notification.
  findViewById(R.id.button_send).setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
      sendMessage();
    }
  });
}

// Send an Intent with an action named "custom-event-name". The Intent sent should 
// be received by the ReceiverActivity.
private void sendMessage() {
  Log.d("sender", "Broadcasting message");
  Intent intent = new Intent("custom-event-name");
  // You can also include some extra data.
  intent.putExtra("message", "This is my message!");
  LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}

Con el código anterior, cada vez que R.id.button_sendse hace clic en el botón , se transmite una Intención y se recibe mMessageReceiveren ReceiverActivity.

La salida de depuración debería verse así:

01-16 10:35:42.413: D/sender(356): Broadcasting message
01-16 10:35:42.421: D/receiver(356): Got message: This is my message! 
Shiki
fuente
77
Gracias. Lo tengo funcionando ya. pero el problema que enfrenté fue conseguir la clase LocalBroadcastManager. Como es una clase de paquete de soporte, no pude usarlo en mi paquete normal hasta que agregué la Biblioteca de compatibilidad de las Herramientas de Android. Una vez que se agrega, todo salió bien. de todos modos, gracias por la respuesta
waqaslam
195
tenga en cuenta que onDestroy()no se garantiza que se llame !!! Debe usar onPause()(porque solo onPause()está garantizado) y onResume()(porque es el partido para onPause())
18446744073709551615
55
Amigos, tengan en cuenta lo que ahora dicen los documentos de Google sobre una Actividad después de onPause (): Killable = Pre-HONEYCOMB Comenzando con Honeycomb, una aplicación no está en estado matable hasta que su onStop () haya regresado.
18446744073709551615
59
onDestroy()no es problema. El caso en el que no se llama es cuando se mata la aplicación, y no importa si no cancela el registro en ese caso, ya que ni siquiera la lista de receptores registrados sobrevive.
zapl
44
@Selvin Espero que sepa que puede hacer que el BroadcastReciever haga una referencia débil de la actividad receptora y que se anule el registro si se ha quedado huérfano. No es necesario que lo anule en onPause, onDestroy está bien siempre que no utilice su BroadcastReceiver para mantener su actividad en la RAM. Su ejemplo muestra una mala práctica con una clase interna que pierde su clase externa, no es exclusiva de BroadcastReceiver y es algo contra lo que los programadores siempre tienen que protegerse. En cuanto a la modificación de la GUI, puede almacenar un estado para cuando se reanude la actividad, no tiene que modificar la GUI.
JohanShogun
133

Prefiero responder de manera integral.

  1. LocalbroadcastManager incluido en Android 3.0 y superior, por lo que debe usar la biblioteca de soporte v4 para las versiones anteriores ver instrucciones aquí

  2. Crear un receptor de difusión:

    private BroadcastReceiver onNotice= new BroadcastReceiver() {
    
        @Override
        public void onReceive(Context context, Intent intent) {
            // intent can contain anydata
            Log.d("sohail","onReceive called");
            tv.setText("Broadcast received !");
    
        }
    };
  3. Registre su receptor en onResume de actividad como:

    protected void onResume() {
            super.onResume();
    
            IntentFilter iff= new IntentFilter(MyIntentService.ACTION);
            LocalBroadcastManager.getInstance(this).registerReceiver(onNotice, iff);
        }
    
    //MyIntentService.ACTION is just a public static string defined in MyIntentService.
  4. cancelar el registro del receptor en onPause:

    protected void onPause() {
      super.onPause();
      LocalBroadcastManager.getInstance(this).unregisterReceiver(onNotice);
    }
  5. Ahora, cada vez que se envía una transmisión local desde la actividad o el servicio de las aplicaciones, se llamará a onReceive of onNotice :).

Editar: puede leer el tutorial completo aquí LocalBroadcastManager: pasar el mensaje de la aplicación Intra

SohailAziz
fuente
15
+1. si su Broadcast Receiver está en un fragmento, regístrelo usando LocalBroadcastManager.getInstance(getActivity()).registerReceiver(onNotice);y LocalBroadcastManager.getInstance(getActivity()).unregisterReceiver(onNotice);
anule
3
¿Estás seguro de que LocalBroadcastManager está incluido en Android 3.0 y versiones posteriores? No puedo encontrarlo en ninguna parte, excepto support lib
mente
55
curiosamente, LBM solo se incluye en la biblioteca de soporte.
Jeffrey Blattman
1
super.onPause () debería ser la última instrucción al sobrescribir el método onPause. Anular el registro antes de super.onPause para evitar errores impredecibles
Thupten
2
Creo que es posible que desee cambiar su ciclo de vida onStopporque en Android API 24+ con "Multi-Window / Split-View" (habilitado por defecto en API 26+ affaicr), la actividad con la que no se interactúa está en estado de pausa. Fuente: developer.android.com/guide/topics/ui/…
Martin Marconcini
45

En el extremo receptor:

  • Primero registre LocalBroadcast Receiver
  • Luego maneje los datos de intención entrantes en onReceive.

      @Override
      protected void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
    
          LocalBroadcastManager lbm = LocalBroadcastManager.getInstance(this);
          lbm.registerReceiver(receiver, new IntentFilter("filter_string"));
      }
    
      public BroadcastReceiver receiver = new BroadcastReceiver() {
          @Override
          public void onReceive(Context context, Intent intent) {
              if (intent != null) {
                  String str = intent.getStringExtra("key");
                  // get all your data from intent and do what you want 
              }
          }
      };

Al finalizar el envío:

   Intent intent = new Intent("filter_string");
   intent.putExtra("key", "My Data");
   // put your all data using put extra 

   LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
waqas ali
fuente
En mi caso, sólo cuando me puse en acción intención al enviar emisión funciona de otro modo OnReceive () método nunca llamó ...
Akash Bisariya
27

En Eclipse, eventualmente tuve que agregar la Biblioteca de compatibilidad / soporte haciendo clic derecho en mi proyecto y seleccionando:

Android Tools -> Add Support Library

Una vez que se agregó, pude usar LocalBroadcastManagerclass en mi código.


Biblioteca de compatibilidad de Android

waqaslam
fuente
12

Cómo cambiar su transmisión global a LocalBroadcast

1) Crear instancia

LocalBroadcastManager localBroadcastManager = LocalBroadcastManager.getInstance(this);

2) Para registrar BroadcastReceiver

Reemplazar

registerReceiver(new YourReceiver(),new IntentFilter("YourAction"));

Con

localBroadcastManager.registerReceiver(new YourReceiver(),new IntentFilter("YourAction"));

3) Para enviar mensajes de difusión

Reemplazar

sendBroadcast(intent);

Con

localBroadcastManager.sendBroadcast(intent);

4) Para cancelar el registro del mensaje de difusión

Reemplazar

unregisterReceiver(mybroadcast);

Con

localBroadcastManager.unregisterReceiver(mybroadcast);
Rohit Singh
fuente
¿Cómo puedo registrar múltiples IntentFilter?
Parikshit Chalke
@ParikshitChalke: enlace
XMAN
12

localbroadcastmanager está en desuso, utilice implementaciones del patrón observable en su lugar.

androidx.localbroadcastmanager está en desuso en la versión 1.1.0

Razón

LocalBroadcastManageres un bus de eventos para toda la aplicación y abarca las infracciones de capa en su aplicación; cualquier componente puede escuchar eventos de cualquier otro componente. Hereda limitaciones innecesarias de casos de uso del sistema BroadcastManager; los desarrolladores tienen que usar Intent aunque los objetos vivan en un solo proceso y nunca lo abandonen. Por esta misma razón, no sigue a BroadcastManager en cuanto a funciones.

Estos se suman a una experiencia confusa del desarrollador.

Reemplazo

Puede reemplazar el uso de LocalBroadcastManagercon otras implementaciones del patrón observable. Dependiendo de su caso de uso, las opciones adecuadas pueden ser LiveDatao flujos reactivos.

Ventaja de LiveData

Puede extender un LiveDataobjeto usando el patrón singleton para ajustar los servicios del sistema para que puedan compartirse en su aplicación. El LiveDataobjeto se conecta al servicio del sistema una vez, y luego cualquier observador que necesite el recurso puede simplemente observar el LiveDataobjeto.

 public class MyFragment extends Fragment {
    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        LiveData<BigDecimal> myPriceListener = ...;
        myPriceListener.observe(this, price -> {
            // Update the UI.
        });
    }
}

El observe()método pasa el fragmento, que es una instancia de LifecycleOwner, como primer argumento. Hacerlo indica que este observador está vinculado al Lifecycleobjeto asociado con el propietario, lo que significa:

  • Si el objeto del ciclo de vida no está en un estado activo, no se llama al observador incluso si el valor cambia.

  • Después de que se destruye el objeto del ciclo de vida, el observador se elimina automáticamente

El hecho de que los LiveDataobjetos sean conscientes del ciclo de vida significa que puede compartirlos entre múltiples actividades, fragmentos y servicios.

Darish
fuente
1
tiene razón acerca de filtrar contextos a todo el mundo, pero me gustaría saber cuál sería un reemplazo adecuado cuando quiero comunicarme desde un servicio en primer plano que se ejecuta incluso sin una actividad, pero cuando la actividad entra, ¿necesitan comunicarse?
ateebahmed
1
Cree una clase singleton con un objeto LiveData y publique sus datos del servicio. Una vez que se inicia la actividad, la actividad puede observar fácilmente los LiveData sin ningún daño. por ejemplo: MyServiceData.getInstance (). getMyData (). observe ...
Darish
3
Extrañaré LocalBroadcastManager. Si les resultaba confuso a los desarrolladores de Google, ¿tal vez deberían dejar de diseñar demasiado?
AFD
@ Darish ¿Esta clase de singleton sería equivalente a almacenarla en el objeto Aplicación? ¿Por qué este tipo de estado global en estos casos no se considera una mala práctica?
xuiqzy
6

Cuando juegues lo suficiente con LocalBroadcastReceiver, te sugiero que pruebes el EventBus de Green Robot: definitivamente te darás cuenta de la diferencia y la utilidad de este en comparación con LBR. Menos código, personalizable sobre el hilo del receptor (UI / Bg), verificando la disponibilidad de los receptores, eventos fijos, eventos podrían usarse como entrega de datos, etc.

Stan
fuente
0
enter code here if (createSuccses){
                        val userDataChange=Intent(BRODCAST_USER_DATA_CHANGE)
                        LocalBroadcastManager.getInstance(this).sendBroadcast(
                            userDataChange
                        )
                        enableSpinner(false)
                        finish()
Seroj Grigoryan
fuente
0

Al declarar uno en su archivo AndroidManifest.xml con la etiqueta (también llamada estática)

<receiver android:name=".YourBrodcastReceiverClass"  android:exported="true">
<intent-filter>
    <!-- The actions you wish to listen to, below is an example -->
    <action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>

Notará que el receptor de difusión declarado anteriormente tiene una propiedad de exported = "true". Este atributo le dice al receptor que puede recibir transmisiones desde fuera del alcance de la aplicación.
2. O dinámicamente registrando una instancia con registerReceiver (lo que se conoce como contexto registrado)

public abstract Intent registerReceiver (BroadcastReceiver receiver, 
            IntentFilter filter);

public void onReceive(Context context, Intent intent) {
//Implement your logic here
}

Hay tres formas de enviar transmisiones:
El método sendOrderedBroadcast se asegura de enviar transmisiones a un solo receptor a la vez. A su vez, cada transmisión puede transmitir datos a la siguiente o detener la propagación de la transmisión a los receptores que siguen.
SendBroadcast es similar al método mencionado anteriormente, con una diferencia. Todos los receptores de difusión reciben el mensaje y no dependen unos de otros.
El método LocalBroadcastManager.sendBroadcast solo envía transmisiones a receptores definidos dentro de su aplicación y no excede el alcance de su aplicación.

Seroj Grigoryan
fuente
-4

También podemos usar la interfaz para broadcastManger aquí. Estoy compartiendo el código probado para broadcastManager pero por interfaz.

primero crea una interfaz como:

public interface MyInterface {
     void GetName(String name);
}

2-esta es la primera clase que necesita implementación

public class First implements MyInterface{

    MyInterface interfc;    
    public static void main(String[] args) {
      First f=new First();      
      Second s=new Second();
      f.initIterface(s);
      f.GetName("Paddy");
  }
  private void initIterface(MyInterface interfc){
    this.interfc=interfc;
  }
  public void GetName(String name) {
    System.out.println("first "+name);
    interfc.GetName(name);  
  }
}

3-aquí está la segunda clase que implementa la misma interfaz cuyo método llama automáticamente

public class Second implements MyInterface{
   public void GetName(String name) {
     System.out.println("Second"+name);
   }
}

por este enfoque podemos usar la interfaz que funciona igual que broadcastManager.

padmender singh
fuente