Registrazione programmatica di un ricevitore broadcast


149

Mi piacerebbe sapere qual è la migliore pratica / il modo di registrare programmaticamente un ricevitore di trasmissione. Voglio registrare ricevitori specifici in base alla scelta dell'utente.

Mentre la registrazione viene effettuata tramite il file manifest, mi chiedo se esiste un modo corretto per ottenere ciò nel codice.


2
CoderzPassion Broadcast Reciever il miglior tutorial dettagliato di sempre
karanatwal.github.io

Si prega di fare riferimento Link stackoverflow.com/questions/15698790/...

Risposte:


64

Sembra che tu voglia controllare se i componenti pubblicati nel tuo manifest sono attivi, non registrare dinamicamente un ricevitore (tramite Context.registerReceiver ()) durante l'esecuzione.

In tal caso, è possibile utilizzare PackageManager.setComponentEnabledSetting () per controllare se questi componenti sono attivi:

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

Nota se sei interessato a ricevere una trasmissione solo mentre sei in esecuzione, è meglio usare registerReceiver (). Un componente ricevitore è utile soprattutto quando è necessario assicurarsi che l'app venga avviata ogni volta che viene inviata la trasmissione.


1
Intelligente! Mi hai messo dritto. Grazie mille
CoolStraw,

Bello - non avevo idea che tu potessi farlo :)
Chris Noldus,


1
@hackbod Come si può aggiungere un tag metadati nel ricevitore personalizzato? Hai qualche idea !! Ho bisogno di aggiungere un tag meta-data quale usiamo in androidmanifest.xml.
Zala Janaksinh,

1
Miglior tutorial fino ad oggi coderzpassion.com/implement-broadcastreceiver-android e in un linguaggio semplice
Jagjit Singh,

269

Nel tuo onCreatemetodo puoi registrare un ricevitore in questo modo:

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

Ricordati di eseguirlo nel onDestroymetodo:

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

19
Grazie, ha funzionato alla grande. Per inviare la trasmissione ho usato il codice Intent i = new Intent ("SOME_ACTION"); sendBroadcast (i);
Ben Clayton,

7
perché non in su curriculum e su start?
Syed Raza Mehdi,

Cosa accadrebbe se non annullassi la registrazione del ricevitore di trasmissione? Lascerebbe registrato il ricevitore di trasmissione, anche dopo il riavvio?
Jaydev,

5
Non è garantito che onDestroy()verrà chiamato, creando così una potenziale perdita di memoria. È meglio registrarsi / annullare la registrazione in onStart()/ onStop().
Neria Nachum,

Questo significa che non devo creare una classe di ricevitori broadcast? Potrei semplicemente mettere tutto il mio codice onReceive () qui e funzionerebbe?
Taslim Oseni,

70

Un punto importante che le persone dimenticano di menzionare è il tempo di vita di Broadcast Receiver. La differenza della registrazione programmatica dalla registrazione in AndroidManifest.xml è quella. Nel file manifest, non dipende dalla durata dell'applicazione. Mentre la registrazione a livello di codice dipende dalla durata dell'applicazione. Ciò significa che se ti registri in AndroidManifest.xml , puoi catturare gli intenti trasmessi anche quando l'applicazione non è in esecuzione.

Modifica: la nota menzionata non è più vera a partire da Android 3.1, il sistema Android esclude tutti i ricevitori dalla ricezione degli intenti di default se l'applicazione corrispondente non è mai stata avviata dall'utente o se l'utente ha interrotto esplicitamente l'applicazione tramite il menu Android (in Gestisci → Applicazione). https://developer.android.com/about/versions/android-3.1.html

Questa è una funzione di sicurezza aggiuntiva in quanto l'utente può essere sicuro che solo le applicazioni che ha avviato riceveranno intenti di trasmissione.

Quindi si può capire che i ricevitori registrati a livello di codice nell'applicazione onCreate()avrebbero lo stesso effetto con quelli dichiarati in AndroidManifest.xml da Android 3.1 sopra.


1
Questa è una buona nota In realtà sto guardando un libro che sto leggendo su Android e mi chiedo perché sono stati fatti entrambi i 2 metodi per implementare la trasmissione. Mi sembra che sia per compatibilità con le versioni precedenti. Ma non ne sono sicuro.
Neon Warge,

Bene, pensi davvero che la modifica sia vera? Intendo l'ultima frase. È probabile che Android uccida la tua applicazione in qualsiasi momento, il che farà sì che i tuoi ricevitori registrati a livello di codice non funzionino più, ma il manifest registrato continuerà a funzionare.
JacksOnF1re

40

Definisci un ricevitore di trasmissione ovunque in Attività / Frammento in questo modo:

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

Definisci IntentFilter in onCreate()

mIntentFilter=new IntentFilter("action_name");

Ora registra BroadcastReciever onResume()e Annulla la registrazione in onPause()[perché non è possibile utilizzare la trasmissione se l'attività è in pausa].

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

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

Per un'esercitazione dettagliata, dai un'occhiata al ricevitore di trasmissione in due modi per implementarlo .


miglior esempio finora ho trovato! Grazie!
Ayush Goyal

1
@SohailAziz Il link fornisce una buona risposta. Potresti inserire il contesto del collegamento nella tua risposta, in modo che se il collegamento si interrompe, la tua risposta rimane rilevante?
iRuth,

nelle mie opinioni personali, la trasmissione dovrebbe essere registrata in onResume e onPause come hai suggerito, ma alcune persone dicono che deve essere su onCreate e onDestroy, puoi spiegare i pro e i contro di entrambi?
Syed Raza Mehdi,

2
@SyedRazaMehdi se la trasmissione viene utilizzata per aggiornare l'interfaccia utente [che è nella maggior parte dei casi], è necessario registrarla su onResume e annullare la registrazione su onPause perché altrimenti la trasmissione sarà inutile.
SohailAziz,

Grazie. Questa è la risposta migliore.
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();
   }
}

1
Puoi spiegare all'OP perché questa è la migliore pratica?
Martin Prikryl,

1
Non spiegano "inviano" sempre il codice, perché è molto meglio che tu lo sappia. -sarcasm
Neon Warge

2

Secondo l'ascolto e la trasmissione di messaggi globali e l'impostazione di allarmi in attività comuni e come eseguirli in Android :

Se la classe ricevente non è registrata usando nel suo manifest, è possibile creare un'istanza e registrare dinamicamente un ricevitore chiamando Context.registerReceiver () .

Dai un'occhiata a registerReceiver (ricevitore BroadcastReceiver, filtro IntentFilter) per maggiori informazioni.


1
ho provato a chiamare context.registerReceiverma non viene chiamato, per favore, guarda questa domanda stackoverflow.com/questions/13238600/…
Caccia

2

È consigliabile fornire sempre l'autorizzazione quando si registra il destinatario, altrimenti si riceverà per qualsiasi applicazione che invia un intento corrispondente. Ciò può consentire alle app dannose di trasmettere al tuo ricevitore.


1

per LocalBroadcastManager

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

e registrati onResume

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

e Annulla la registrazione onStop

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

e riceverlo ..

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

dove si trova IntentFilter

 new IntentFilter("any.action.string")

1

Due scelte

1) Se desideri leggere la trasmissione solo quando l'attività è visibile,

registerReceiver(...) in onStart()e unregisterReceiver(...)inonStop()

2) Se desideri leggere la trasmissione anche se l'attività è in background,

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

Bonus:

Se sei pigro

Se non si desidera scrivere il codice boilerplate per la registrazione e l'annullamento della registrazione di un BroadcastReceiver ancora e ancora in ciascuna attività,

  1. Crea un'attività astratta
  2. Scrivi il codice del boilerplate in Activity
  3. Lasciare l'implementazione come metodi astratti

Ecco il frammento di codice:

Attività astratta

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 questo approccio è possibile scrivere più codice boilerplate come scrivere animazioni comuni, associare a un servizio, ecc.

Vedi il codice completo:

QUI


0

Crea un ricevitore broadcast

[BroadcastReceiver (Enabled = true, Exported = false)]

public class BCReceiver : BroadcastReceiver
{

    BCReceiver receiver;

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

Dalla tua attività aggiungi questo codice:

LocalBroadcastManager.getInstance(ApplicationContext)
    .registerReceiver(receiver, filter);
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.