Enregistrer par programme un récepteur de diffusion

149

J'aimerais savoir quelle est la meilleure pratique / manière d'enregistrer par programmation un récepteur de diffusion. Je souhaite enregistrer des récepteurs spécifiques selon le choix de l'utilisateur.

Comme l'enregistrement se fait via le fichier manifeste, je me demande s'il existe un moyen approprié d'y parvenir dans le code.

CoolStraw
la source
2
CoderzPassion Broadcast Reciever, meilleur tutoriel détaillé de tous les temps
karanatwal.github.io
Veuillez vous référer à ce lien stackoverflow.com/questions/15698790/…

Réponses:

64

Il semble que vous souhaitiez contrôler si les composants publiés dans votre manifeste sont actifs, et non enregistrer dynamiquement un récepteur (via Context.registerReceiver ()) lors de l'exécution.

Si tel est le cas, vous pouvez utiliser PackageManager.setComponentEnabledSetting () pour contrôler si ces composants sont actifs:

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

Notez que si vous souhaitez uniquement recevoir une diffusion pendant que vous exécutez, il est préférable d'utiliser registerReceiver (). Un composant récepteur est principalement utile lorsque vous devez vous assurer que votre application est lancée à chaque fois que la diffusion est envoyée.

hackbod
la source
1
Intelligent ! Vous m'avez bien compris. Merci beaucoup
CoolStraw
Nice one - je ne
savais
c'est similaire stackoverflow.com/questions/24140894/…
Ankit Srivastava
1
@hackbod Comment ajouter une balise de méta-données dans un récepteur personnalisé? As-tu une idée !! Je dois ajouter une balise de méta-données que nous utilisons dans androidmanifest.xml.
Zala Janaksinh
1
Meilleur tutoriel jusqu'à ce jour coderzpassion.com/implement-broadcastreceiver-android et en langage simple
Jagjit Singh
269

Dans votre onCreateméthode, vous pouvez enregistrer un récepteur comme ceci:

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

N'oubliez pas d'exécuter ceci dans la onDestroyméthode:

 @Override
 protected void onDestroy() {
  if (receiver != null) {
   unregisterReceiver(receiver);
   receiver = null;
  }
  super.onDestroy();
 }
Eric Nordvik
la source
19
Merci, cela a très bien fonctionné. Pour envoyer la diffusion, j'ai utilisé le code Intent i = new Intent ("SOME_ACTION"); sendBroadcast (i);
Ben Clayton
7
pourquoi pas au CV et au démarrage?
Syed Raza Mehdi
Que se passerait-il si je ne désenregistre pas le récepteur de diffusion? Laisserait-il le récepteur de diffusion enregistré, même après le redémarrage?
Jaydev
5
Ce n'est pas garanti qui onDestroy()sera appelé, créant ainsi une fuite de mémoire potentielle. Il est préférable de s'inscrire / se désinscrire dans onStart()/ onStop().
Neria Nachum
Cela signifie-t-il que je n'ai pas à créer de classe de récepteur de diffusion? Je pourrais juste mettre tout mon code onReceive () ici et ça marcherait?
Taslim Oseni
70

Un point important que les gens oublient de mentionner est la durée de vie du Broadcast Receiver. La différence entre son enregistrement par programme et son enregistrement dans AndroidManifest.xml est la suivante. Dans le fichier manifeste, cela ne dépend pas de la durée de vie de l'application. Lors de son enregistrement par programme, cela dépend de la durée de vie de l'application. Cela signifie que si vous vous inscrivez dans AndroidManifest.xml , vous pouvez capturer les intentions diffusées même lorsque votre application n'est pas en cours d'exécution.

Edit: La note mentionnée n'est plus vraie à partir d'Android 3.1, le système Android exclut tous les récepteurs de recevoir des intentions par défaut si l'application correspondante n'a jamais été démarrée par l'utilisateur ou si l'utilisateur a explicitement arrêté l'application via le menu Android (dans Gérer → Application). https://developer.android.com/about/versions/android-3.1.html

Il s'agit d'une fonction de sécurité supplémentaire car l'utilisateur peut être sûr que seules les applications qu'il a démarrées recevront des intentions de diffusion.

On peut donc comprendre que les récepteurs enregistrés par programme dans l'application onCreate()auraient le même effet que ceux déclarés dans AndroidManifest.xml à partir d'Android 3.1 ci-dessus.

Krypton
la source
1
C'est une bonne note. Je regarde en fait un livre que je lis sur Android et je me demande pourquoi les deux méthodes de mise en œuvre de la diffusion ont été appliquées. Il me semble que c'est pour la rétrocompatibilité. Mais je n'en suis pas sûr.
Neon Warge
Eh bien, pensez-vous vraiment que la modification est vraie? Je veux dire la dernière phrase. Android est susceptible de tuer votre application à tout moment, ce qui empêchera vos récepteurs enregistrés par programmation de ne plus fonctionner, mais le manifeste enregistré fonctionnera toujours.
JacksOnF1re
40

Définissez un récepteur de diffusion n'importe où dans Activité / Fragment comme ceci:

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

Définir IntentFilter dans onCreate()

mIntentFilter=new IntentFilter("action_name");

Enregistrez maintenant le BroadcastReciever dans onResume()et désenregistrez-le dans onPause()[car il n'y a aucune utilisation de diffusion si l'activité est interrompue].

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

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

Pour un didacticiel détaillé, jetez un œil aux deux façons de mettre en œuvre le récepteur de diffusion .

SohailAziz
la source
meilleur exemple que j'ai trouvé jusqu'ici! Merci!
Ayush Goyal
1
@SohailAziz Le lien fournit une bonne réponse. Pourriez-vous mettre le contexte du lien dans votre réponse, de sorte que si le lien tombe en panne, votre réponse reste pertinente?
iRuth
dans mon opinion personnelle, la diffusion devrait être enregistrée dans onResume et onPause comme vous l'avez suggéré, mais certaines personnes disent qu'elle doit être sur onCreate et onDestroy, pouvez-vous expliquer les avantages et les inconvénients des deux?
Syed Raza Mehdi
2
@SyedRazaMehdi si la diffusion est utilisée pour mettre à jour l'interface utilisateur [ce qui est dans la plupart des cas], vous devez l'enregistrer dans onResume et vous désinscrire dans onPause car la diffusion sera inutile sinon.
SohailAziz
Merci, c'est la meilleure réponse.
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
la source
1
Pouvez-vous expliquer à OP pourquoi il s'agit de la meilleure pratique?
Martin Prikryl
1
Ils n'expliquent pas, «ils» affichent toujours le code, parce que c'est beaucoup mieux que vous le savez. -sarcasm
Neon Warge
2

Selon Écouter et diffuser des messages globaux, définir des alarmes dans les tâches courantes et comment les faire sous Android :

Si la classe réceptrice n'est pas enregistrée en utilisant dans son manifeste, vous pouvez instancier et enregistrer dynamiquement un récepteur en appelant Context.registerReceiver () .

Jetez un œil à registerReceiver (récepteur BroadcastReceiver, filtre IntentFilter) pour plus d'informations.

McStretch
la source
1
J'ai essayé d'appeler context.registerReceivermais il n'est pas appelé, pouvez-vous s'il vous plaît regarder cette question stackoverflow.com/questions/13238600/…
Chasse
2

Il est recommandé de toujours fournir l'autorisation lors de l'enregistrement du récepteur, sinon vous recevrez pour toute application qui envoie une intention correspondante. Cela peut permettre à des applications malveillantes de diffuser sur votre récepteur.

ChopperCharles
la source
1

pour LocalBroadcastManager

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

et inscrivez-vous onResume

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

et désenregistrer onStop

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

et recevez-le ..

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

où IntentFilter est

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

Deux choix

1) Si vous souhaitez lire la diffusion uniquement lorsque l'activité est visible,

registerReceiver(...) dans onStart()et unregisterReceiver(...)dansonStop()

2) Si vous souhaitez lire la diffusion même si l'activité est en arrière-plan,

registerReceiver(...)dans onCreate(...)et unregisterReceiver(...)dansonDestroy()

Prime:

Si tu es paresseux

Si vous ne voulez pas écrire de code standard pour enregistrer et désenregistrer un BroadcastReceiver encore et encore dans chaque activité, alors,

  1. Créer une activité abstraite
  2. Écrire un code standard dans l'activité
  3. Laissez l'implémentation en tant que méthodes abstraites

Voici l'extrait de code:

Activité abstraite

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

}

En utilisant cette approche, vous pouvez écrire plus de code standard tel que l'écriture d'animations courantes, la liaison à un service, etc.

Voir le code complet:

ICI

Rohit Singh
la source
0

Créer un récepteur de diffusion

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

public class BCReceiver : BroadcastReceiver
{

    BCReceiver receiver;

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

Depuis votre activité, ajoutez ce code:

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