Registrar programaticamente um receptor de transmissão

149

Gostaria de saber qual é a melhor prática / maneira de registrar programaticamente um receptor de transmissão. Quero registrar receptores específicos de acordo com a escolha do usuário.

Como o registro é feito através do arquivo de manifesto, estou pensando se existe uma maneira adequada de conseguir isso no código.

CoolStraw
fonte
2
CoderzPassion Transmissão Reciever melhor tutorial detalhado sempre
karanatwal.github.io

Respostas:

64

Parece que você deseja controlar se os componentes publicados em seu manifesto estão ativos, e não registram dinamicamente um receptor (via Context.registerReceiver ()) durante a execução.

Nesse caso, você pode usar PackageManager.setComponentEnabledSetting () para controlar se esses componentes estão ativos:

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

Observe que se você estiver interessado apenas em receber uma transmissão enquanto estiver executando, é melhor usar o registerReceiver (). Um componente receptor é útil principalmente para quando você precisa garantir que seu aplicativo seja iniciado toda vez que a transmissão for enviada.

hackbod
fonte
1
Inteligente ! Você me entendeu direito. Muito obrigado
CoolStraw
Nice one - não tinha idéia de que você poderia fazer isso :)
Chris Noldus
É semelhante stackoverflow.com/questions/24140894/… #
Ankit Srivastava
1
@hackbod Como adicionar meta-data tag no receptor personalizado? Você tem alguma ideia !! Preciso adicionar uma tag de metadados que usamos no androidmanifest.xml.
Zala Janaksinh
1
Melhor tutorial até a data coderzpassion.com/implement-broadcastreceiver-android e em linguagem simples
Jagjit Singh
269

No seu onCreatemétodo, você pode registrar um 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);
}

Lembre-se de executar isso no onDestroymétodo:

 @Override
 protected void onDestroy() {
  if (receiver != null) {
   unregisterReceiver(receiver);
   receiver = null;
  }
  super.onDestroy();
 }
Eric Nordvik
fonte
19
Obrigado, isso funcionou muito bem. Para enviar a transmissão, usei o código Intent i = new Intent ("SOME_ACTION"); sendBroadcast (i);
Ben Clayton
7
por que não entrar no currículo e começar?
Syed Raza Mehdi
O que aconteceria se eu não cancelar o registro do receptor de transmissão? Deixaria o receptor de transmissão registrado, mesmo após a reinicialização?
jaydev
5
Não é garantido que onDestroy()isso será chamado, criando um possível vazamento de memória. É melhor registrar / cancelar o registro em onStart()/ onStop().
Neria Nachum
Isso significa que não preciso criar uma classe de receptor de transmissão? Eu poderia apenas colocar todo o meu código onReceive () aqui e funcionaria?
Taslim Oseni
70

Um ponto importante que as pessoas esquecem de mencionar é o tempo de vida do Broadcast Receiver. A diferença de registrá-lo programaticamente de registrar no AndroidManifest.xml é essa. No arquivo de manifesto, não depende do tempo de vida do aplicativo. Enquanto que, ao registrá-lo programaticamente, depende do tempo de vida do aplicativo. Isso significa que, se você se registrar no AndroidManifest.xml , poderá capturar as intenções transmitidas, mesmo quando o aplicativo não estiver em execução.

Editar: a nota mencionada não é mais verdadeira a partir do Android 3.1, o sistema Android exclui todos os destinatários de receber intenções por padrão se o aplicativo correspondente nunca tiver sido iniciado pelo usuário ou se o usuário interrompeu explicitamente o aplicativo através do menu Android (em Gerenciar → Aplicativo). https://developer.android.com/about/versions/android-3.1.html

Esse é um recurso de segurança adicional, pois o usuário pode ter certeza de que apenas os aplicativos que ele iniciou receberão intenções de transmissão.

Portanto, pode ser entendido que os receptores registrados programaticamente nos aplicativos onCreate()teriam o mesmo efeito com os declarados no AndroidManifest.xml do Android 3.1 acima.

Krypton
fonte
1
Esta é uma boa nota. Na verdade, estou olhando para um livro que estou lendo sobre o Android e me perguntando por que os dois métodos de implementação da transmissão foram executados. Parece-me que é para compatibilidade com versões anteriores. Mas não tenho certeza.
21715 Neon Warge
Bem, você realmente acha que a edição é verdadeira? Quero dizer a última frase. O Android provavelmente matará seu aplicativo a qualquer momento, o que fará com que seus receptores registrados programaticamente não funcionem mais, mas o manifesto registrado ainda funcionará.
JacksonOnF1re:
40

Defina um receptor de transmissão em qualquer lugar em Atividade / Fragmento como este:

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

Definir IntentFilter em onCreate()

mIntentFilter=new IntentFilter("action_name");

Agora registre o BroadcastReciever em onResume()e cancele o registro em onPause()[porque não há uso de broadcast se a atividade estiver em pausa].

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

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

Para um tutorial detalhado, dê uma olhada no receptor de transmissão - duas maneiras de implementar .

SohailAziz
fonte
melhor exemplo até agora que eu encontrei! Obrigado!
Ayush Goyal
1
@SohailAziz O link fornece uma boa resposta. Você poderia colocar o contexto do link em sua resposta, para que, se o link for desativado, sua resposta permaneça relevante?
iRuth 28/02
na minha opinião pessoal, a transmissão deve ser registrada em onResume e onPause, como você sugeriu, mas algumas pessoas dizem que deve estar em onCreate e onDestroy, você pode explicar os prós e os contras de ambos?
Syed Raza Mehdi
2
@SyedRazaMehdi se a transmissão for usada para atualizar a interface do usuário [que é na maioria dos casos], você deve registrá-la no onResume e cancelar o registro na onPause porque a transmissão será inútil.
precisa saber é o seguinte
Obrigado. Esta é a melhor resposta.
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
fonte
1
Você pode explicar ao OP por que essa é a melhor prática?
Martin Prikryl
1
Eles não explicam, "eles" sempre postam código, porque é muito melhor você saber. -sarcasmo
Neon Warge
2

De acordo com a escuta e a transmissão de mensagens globais e a configuração de alarmes em tarefas comuns e como executá-las no Android :

Se a classe de recebimento não estiver registrada usando em seu manifesto, você poderá instanciar e registrar dinamicamente um receptor chamando Context.registerReceiver () .

Dê uma olhada no registerReceiver (receptor BroadcastReceiver, filtro IntentFilter) para obter mais informações.

McStretch
fonte
1
Eu tentei ligar, context.registerReceivermas não está sendo chamado, você pode olhar para esta questão stackoverflow.com/questions/13238600/…
Hunt
2

É uma prática recomendada sempre fornecer a permissão ao registrar o receptor, caso contrário você receberá qualquer aplicativo que envie uma intenção correspondente. Isso pode permitir que aplicativos maliciosos sejam transmitidos para o seu receptor.

ChopperCharles
fonte
1

para LocalBroadcastManager

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

e registre-se onResume

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

e cancele o registro onStop

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

e receba ..

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

onde IntentFilter é

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

Duas escolhas

1) Se você quiser ler Transmissão somente quando a Atividade estiver visível,

registerReceiver(...) dentro onStart()e unregisterReceiver(...)dentroonStop()

2) Se você quiser ler Transmissão, mesmo que a Atividade esteja em segundo plano,

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

Bônus:

Se você é preguiçoso

Se você não deseja escrever um código padrão para registrar e cancelar o registro de um BroadcastReceiver repetidamente em cada Atividade,

  1. Criar uma atividade abstrata
  2. Escreva o código padrão na Atividade
  3. Deixe a implementação como métodos abstratos

Aqui está o trecho de código:

Atividade abstrata

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

}

Usando essa abordagem, você pode escrever mais códigos padrão, como escrever animações comuns, vincular a um serviço etc.

Veja o código completo:

AQUI

Rohit Singh
fonte
0

Crie um receptor de transmissão

[BroadcastReceiver (Ativado = true, Exportado = false)]

public class BCReceiver : BroadcastReceiver
{

    BCReceiver receiver;

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

Da sua atividade, adicione este código:

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