Como usar o LocalBroadcastManager?

452

Como usar / localizar, LocalBroadcastManagerconforme descrito no Google Docs e no Documento de transmissão de serviço ?

Tentei pesquisar no Google, mas não há código disponível para começar?

Os documentos dizem que eu devo usá-lo se quiser transmitir internamente no processo do meu aplicativo, mas não sei onde procurar isso.

Alguma ajuda / comentário?

Atualização : Eu sei como usar transmissões, mas não sei como ficar LocalBroadcastManagerdisponível no meu projeto.

waqaslam
fonte
Waqas, você registrou o receptor no manifesto. Se sim, por favor me avise como?
Mudassir
2
Não acho que você precise registrar o receptor para essas transmissões em manifesto, porque, se o fizer, esse receptor também ouvirá transmissões globais.
waqaslam
2
Verdade. Então isso significa que eu tenho que fazer isso no código, conforme indicado na resposta abaixo; LocalBroadcastManager.getInstance(this).registerReceiver(mMessageReceiver, new IntentFilter("custom-event-name"));
Mudassir
2
LocalBroadcastManagerfoi descontinuado. Substituí o meu pela biblioteca EventBus, que é muito melhor.
Kris B

Respostas:

861

Eu vou responder isso de qualquer maneira. Apenas no caso de alguém precisar.

ReceiverActivity.java

Uma atividade que procura notificações para o evento nomeado "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

A segunda atividade que envia / transmite notificações.

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

Com o código acima, toda vez que o botão R.id.button_sendé clicado, um Intent é transmitido e recebido por mMessageReceiverin ReceiverActivity.

A saída de depuração deve ficar assim:

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
fonte
7
obrigado. já funcionou. mas o problema que enfrentei foi se apossar da classe LocalBroadcastManager. Como é uma classe de pacote de suporte, não pude usá-lo no meu pacote comum até adicionar a Biblioteca de Compatibilidade nas Ferramentas do Android. Uma vez adicionado, tudo correu bem. de qualquer forma, obrigado pela resposta
waqaslam
195
Por favor, note que onDestroy()não é garantido que seja chamado !!! Você deve usar onPause()(porque só onPause()é garantida) e onResume()(porque é o jogo para onPause())
18446744073709551615
5
Pessoal, observe o que os documentos do Google dizem agora sobre uma Atividade após onPause (): Killable = Pré- mel
18446744073709551615
59
onDestroy()não é problema. O caso em que não é chamado é quando o aplicativo é encerrado e não importa se você não se registra nesse caso, pois nem mesmo a lista de receptores registrados sobrevive a isso.
Zapl 01/03
4
@Selvin Espero que você esteja ciente de que pode fazer com que o BroadcastReciever seja fracamente referenciado à atividade de recebimento e faça com que ele se cancele se ele ficar órfão. Você não precisa cancelar o registro no onPause, o onDestroy é bom, desde que você não use o BroadcastReceiver para manter sua atividade na RAM. Seu exemplo mostra uma má prática com uma classe interna vazando sua classe externa, não é exclusivo do BroadcastReceiver e é algo que os programadores sempre precisam se proteger. Quanto à modificação da GUI, você pode armazenar um estado para quando a atividade é retomada, não sendo necessário modificar a GUI.
27915 JohanShogun
133

Eu gostaria de responder de forma abrangente.

  1. LocalbroadcastManager incluído no Android 3.0 e superior, para que você tenha que usar a biblioteca de suporte v4 para versões anteriores. veja as instruções aqui

  2. Crie um receptor de transmissão:

    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 seu receptor em um currículo de atividade 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. cancele o registro do receptor no onPause:

    protected void onPause() {
      super.onPause();
      LocalBroadcastManager.getInstance(this).unregisterReceiver(onNotice);
    }
    
  5. Agora, sempre que um broadcast local for enviado da atividade ou serviço dos aplicativos, onReceive of onNotice será chamado :).

Edit: Você pode ler o tutorial completo aqui LocalBroadcastManager: Passagem de mensagens dentro do aplicativo

SohailAziz
fonte
15
+1. Se o seu receptor de transmissão está em um fragmento, registrá-lo usando LocalBroadcastManager.getInstance(getActivity()).registerReceiver(onNotice);e cancelar o registro-lo usandoLocalBroadcastManager.getInstance(getActivity()).unregisterReceiver(onNotice);
Peteh
3
Tem certeza de que o LocalBroadcastManager está incluído no Android 3.0 ou superior? Não pode encontrá-lo em qualquer lugar exceto lib apoio
mente
5
estranhamente, o LBM é incluído apenas na biblioteca de suporte.
Jeffrey Blattman
1
super.onPause () deve ser a última instrução ao substituir o método onPause. Unregister antes super.onPause para evitar erro imprevisível
Thupten
2
Acredito que você queira mudar seu ciclo de vida onStopporque, na API do Android 24+ com "Multi-Window / Split-View" (ativada por padrão na API 26+ affaicr), a atividade que não está sendo interagida está no estado de pausa. Fonte: developer.android.com/guide/topics/ui/…
Martin Marconcini
45

No final de recebimento:

  • Primeiro registro LocalBroadcast Receiver
  • Em seguida, manipule os dados de intenção de entrada no 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 
              }
          }
      };

No final do envio:

   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
fonte
No meu caso só quando eu definir a ação na intenção ao enviar transmissão funciona de outra forma OnReceive () método nunca chamada ...
Akash Bisariya
27

No Eclipse, finalmente tive que adicionar a Biblioteca de Compatibilidade / Suporte clicando com o botão direito do mouse no meu projeto e selecionando:

Android Tools -> Add Support Library

Depois de adicionado, pude usar a LocalBroadcastManagerclasse no meu código.


Biblioteca de compatibilidade do Android

waqaslam
fonte
12

Como mudar sua transmissão global para LocalBroadcast

1) Criar instância

LocalBroadcastManager localBroadcastManager = LocalBroadcastManager.getInstance(this);

2) Para registrar o BroadcastReceiver

Substituir

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

Com

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

3) Para enviar mensagem de difusão

Substituir

sendBroadcast(intent);

Com

localBroadcastManager.sendBroadcast(intent);

4) Para cancelar o registro da mensagem de difusão

Substituir

unregisterReceiver(mybroadcast);

Com

localBroadcastManager.unregisterReceiver(mybroadcast);
Rohit Singh
fonte
Como posso registrar vários IntentFilter?
Parikshit Chalke
@ParikshitChalke: link
XMAN 8/08/18
12

localbroadcastmanager foi descontinuado, use implementações do padrão observável.

androidx.localbroadcastmanager está sendo reprovado na versão 1.1.0

Razão

LocalBroadcastManageré um barramento de eventos para todo o aplicativo e abrange violações de camada no seu aplicativo; qualquer componente pode ouvir eventos de qualquer outro componente. Ele herda limitações desnecessárias de casos de uso do BroadcastManager do sistema; os desenvolvedores precisam usar o Intent, mesmo que os objetos vivam em apenas um processo e nunca o abandonem. Por esse mesmo motivo, ele não segue o BroadcastManager.

Isso resulta em uma experiência confusa para o desenvolvedor.

Substituição

Você pode substituir o uso LocalBroadcastManagerpor outras implementações do padrão observável. Dependendo do seu caso de uso, as opções adequadas podem ser LiveDataou fluxos reativos.

Vantagem do LiveData

Você pode estender um LiveDataobjeto usando o padrão singleton para agrupar os serviços do sistema para que eles possam ser compartilhados no seu aplicativo. O LiveDataobjeto se conecta ao serviço do sistema uma vez e, em seguida, qualquer observador que precise do recurso pode apenas observar o 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.
        });
    }
}

O observe()método passa o fragmento, que é uma instância de LifecycleOwner, como o primeiro argumento. Fazer isso indica que esse observador está vinculado ao Lifecycleobjeto associado ao proprietário, o que significa:

  • Se o objeto Ciclo de Vida não estiver em um estado ativo, o observador não será chamado, mesmo que o valor seja alterado.

  • Após a destruição do objeto Ciclo de Vida, o observador é removido automaticamente

O fato de os LiveDataobjetos reconhecerem o ciclo de vida significa que você pode compartilhá-los entre várias atividades, fragmentos e serviços.

Darish
fonte
1
você está certo sobre o vazamento de contextos para o mundo inteiro, mas eu gostaria de saber o que seria um substituto adequado quando eu quiser me comunicar de um serviço em primeiro plano que esteja sendo executado mesmo sem uma atividade, mas quando a atividade entrar, eles precisam se comunicar?
ateebahmed
1
Crie uma classe singleton com um objeto LiveData e publique seus dados no serviço. Depois que a atividade é iniciada, a atividade pode facilmente observar os LiveData sem nenhum dano. . por exemplo: MyServiceData.getInstance () getMyData () observam ....
Darish
3
Sentirei falta do LocalBroadcastManager. Se isso foi confuso para os desenvolvedores do Google, talvez eles precisem parar de fazer coisas demais?
AFD
@Darish Essa classe singleton seria equivalente a armazená-la no objeto Application? Por que esse tipo de estado global nesses casos não é considerado uma má prática?
xuiqzy
6

Quando você jogar o suficiente com LocalBroadcastReceiver, sugiro que você experimente o EventBus da Green Robot - você definitivamente perceberá a diferença e a utilidade dele em comparação com o LBR. Menos código personalizável sobre o encadeamento do receptor (UI / Bg), verificação da disponibilidade do receptor, eventos persistentes, eventos podem ser usados ​​como entrega de dados, etc.

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

Ao declarar um no seu arquivo AndroidManifest.xml com a tag (também chamada 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>

Você notará que o receptor de transmissão declarado acima possui uma propriedade exported = ”true”. Este atributo informa ao receptor que ele pode receber transmissões de fora do escopo do aplicativo.
2. Ou dinamicamente, registrando uma instância com registerReceiver (o que é conhecido como contexto registrado)

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

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

Há três maneiras de enviar transmissões:
O método sendOrderedBroadcast, garante a transmissão de transmissões para apenas um receptor por vez. Cada transmissão, por sua vez, pode repassar dados para quem segue ou interromper a propagação da transmissão para os receptores a seguir.
O sendBroadcast é semelhante ao método mencionado acima, com uma diferença. Todos os receptores de transmissão recebem a mensagem e não dependem um do outro.
O método LocalBroadcastManager.sendBroadcast envia apenas transmissões para receptores definidos dentro do seu aplicativo e não excede o escopo do seu aplicativo.

Seroj Grigoryan
fonte
-4

Também podemos usar a interface para o mesmo que o broadcastManger. Aqui, estou compartilhando o código testd do broadcastManager, mas pela interface.

primeiro faça uma interface como:

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

2 - esta é a primeira classe que precisa de implementação

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-aqui é a segunda classe que implementa a mesma interface cuja chamada de método automaticamente

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

portanto, com essa abordagem, podemos usar a interface funcionando da mesma forma que o broadcastManager.

padmender singh
fonte