Récepteurs de diffusion dans Xamarin.Android

Cette section explique comment utiliser un récepteur de diffusion.

Vue d’ensemble du récepteur de diffusion

Un récepteur de diffusion est un composant Android qui permet à une application de répondre aux messages (android Intent) qui sont diffusés par le système d’exploitation Android ou par une application. Les diffusions suivent un modèle de publication-abonnement : un événement entraîne la publication et la réception d’une diffusion par les composants intéressés par l’événement.

Android identifie deux types de diffusions :

  • Diffusion explicite : ces types de diffusions ciblent une application spécifique. L’utilisation la plus courante d’une diffusion explicite consiste à démarrer une activité. Exemple de diffusion explicite lorsqu’une application doit composer un numéro de téléphone ; il distribuera une intention qui cible l’application Téléphone sur Android et transmettra le numéro de téléphone à composer. Android acheminera ensuite l’intention vers l’application Téléphone.
  • Diffusion implicite : ces diffusions sont distribuées à toutes les applications sur l’appareil. L’intention est un ACTION_POWER_CONNECTED exemple de diffusion implicite. Cette intention est publiée chaque fois qu’Android détecte que la batterie de l’appareil est en cours de chargement. Android acheminera cette intention vers toutes les applications qui se sont inscrites pour cet événement.

Le récepteur de diffusion est une sous-classe du BroadcastReceiver type et il doit remplacer la OnReceive méthode. Android s’exécute OnReceive sur le thread main. Cette méthode doit donc être conçue pour s’exécuter rapidement. Soyez prudent lors de la génération de threads dans OnReceive , car Android peut arrêter le processus à la fin de la méthode. Si un récepteur de diffusion doit effectuer un travail de longue durée, il est recommandé de planifier un travail à l’aide de JobScheduler ou du répartiteur de travaux Firebase. La planification du travail avec un travail sera abordée dans un guide distinct.

Un filtre d’intention est utilisé pour inscrire un récepteur de diffusion afin qu’Android puisse acheminer correctement les messages. Le filtre d’intention peut être spécifié au moment de l’exécution (il est parfois appelé récepteur inscrit dans le contexte ou inscription dynamique) ou il peut être défini de manière statique dans le manifeste Android ( récepteur inscrit dans un manifeste). Xamarin.Android fournit un attribut C#, IntentFilterAttribute, qui inscrit statiquement le filtre d’intention (ceci sera abordé plus en détail plus loin dans ce guide). À compter d’Android 8.0, il n’est pas possible pour une application de s’inscrire statiquement pour une diffusion implicite.

La principale différence entre le récepteur inscrit au manifeste et le récepteur inscrit dans le contexte est qu’un récepteur inscrit dans le contexte répond uniquement aux diffusions pendant l’exécution d’une application, tandis qu’un récepteur inscrit au manifeste peut répondre aux diffusions même si l’application n’est pas en cours d’exécution.

Il existe deux ensembles d’API pour la gestion d’un récepteur de diffusion et l’envoi de diffusions :

  1. Context : la Android.Content.Context classe peut être utilisée pour inscrire un récepteur de diffusion qui répondra aux événements à l’échelle du système. Est Context également utilisé pour publier des diffusions à l’échelle du système.
  2. LocalBroadcastManager – Il s’agit d’une API disponible via le package NuGet de la bibliothèque de support Xamarin v4. Cette classe est utilisée pour maintenir les diffusions et les récepteurs de diffusion isolés dans le contexte de l’application qui les utilise. Cette classe peut être utile pour empêcher d’autres applications de répondre aux diffusions d’applications uniquement ou d’envoyer des messages à des récepteurs privés.

Un récepteur de diffusion peut ne pas afficher de boîtes de dialogue, et il est fortement déconseillé de démarrer une activité à partir d’un récepteur de diffusion. Si un récepteur de diffusion doit avertir l’utilisateur, il doit publier une notification.

Il n’est pas possible de lier ou de démarrer un service à partir d’un récepteur de diffusion.

Ce guide explique comment créer un récepteur de diffusion et comment l’inscrire afin qu’il puisse recevoir des émissions.

Création d’un récepteur de diffusion

Pour créer un récepteur de diffusion dans Xamarin.Android, une application doit sous-classer la BroadcastReceiver classe, l’orner avec le BroadcastReceiverAttributeet remplacer la OnReceive méthode :

[BroadcastReceiver(Enabled = true, Exported = false)]
public class SampleReceiver : BroadcastReceiver
{
    public override void OnReceive(Context context, Intent intent)
    {
        // Do stuff here.

        String value = intent.GetStringExtra("key");
    }
}

Lorsque Xamarin.Android compile la classe, il met également à jour l’AndroidManifest avec les métadonnées nécessaires pour inscrire le récepteur. Pour un récepteur de diffusion inscrit de manière statique, le Enabled doit être défini sur true, sinon Android ne sera pas en mesure de créer une instance du récepteur.

La Exported propriété contrôle si le récepteur de diffusion peut recevoir des messages provenant de l’extérieur de l’application. Si la propriété n’est pas définie explicitement, la valeur par défaut de la propriété est déterminée par Android en fonction des filtres d’intention associés au récepteur de diffusion. S’il existe au moins un filtre d’intention pour le récepteur de diffusion, Android suppose que la Exported propriété est true. Si aucun filtre d’intention n’est associé au récepteur de diffusion, Android suppose que la valeur est false.

La OnReceive méthode reçoit une référence à qui Intent a été envoyée au récepteur de diffusion. Cela permet à l’expéditeur de l’intention de transmettre des valeurs au récepteur de diffusion.

Inscription statique d’un récepteur de diffusion avec un filtre d’intention

Lorsqu’un BroadcastReceiver est décoré avec , IntentFilterAttributeXamarin.Android ajoute l’élément nécessaire <intent-filter> au manifeste Android au moment de la compilation. L’extrait de code suivant est un exemple de récepteur de diffusion qui s’exécutera quand un appareil a terminé le démarrage (si les autorisations Android appropriées ont été accordées par l’utilisateur) :

[BroadcastReceiver(Enabled = true)]
[IntentFilter(new[] { Android.Content.Intent.ActionBootCompleted })]
public class MyBootReceiver : BroadcastReceiver
{
    public override void OnReceive(Context context, Intent intent)
    {
        // Work that should be done when the device boots.     
    }
}

Notes

Dans Android 8.0 (API 26 et versions ultérieures), Google a placé des limitations sur ce que les applications peuvent faire alors que les utilisateurs n’interagissent pas directement avec eux. Ces limitations affectent les services en arrière-plan et les récepteurs de diffusion implicites tels que Android.Content.Intent.ActionBootCompleted. En raison de ces limitations, vous pouvez avoir des difficultés à inscrire un Boot Completed récepteur de diffusion sur les versions plus récentes d’Android. Si c’est le cas, notez que ces restrictions ne s’appliquent pas aux services de premier plan, qui peuvent être appelés à partir de votre récepteur de diffusion.

Il est également possible de créer un filtre d’intention qui répondra aux intentions personnalisées. Prenons l’exemple suivant :

[BroadcastReceiver(Enabled = true)]
[IntentFilter(new[] { "com.xamarin.example.TEST" })]
public class MySampleBroadcastReceiver : BroadcastReceiver
{
    public override void OnReceive(Context context, Intent intent)
    {
        // Do stuff here
    }
}

Les applications qui ciblent Android 8.0 (niveau d’API 26) ou une version ultérieure peuvent ne pas s’inscrire statiquement pour une diffusion implicite. Les applications peuvent toujours s’inscrire statiquement pour une diffusion explicite. Il existe une petite liste de diffusions implicites qui sont exemptées de cette restriction. Ces exceptions sont décrites dans le guide Des exceptions de diffusion implicite dans la documentation Android. Les applications qui s’intéressent aux diffusions implicites doivent le faire dynamiquement à l’aide de la RegisterReceiver méthode . Ceci est décrit ci-dessous.

Context-Registering un récepteur de diffusion

L’inscription contextuelle (également appelée inscription dynamique) d’un récepteur est effectuée en appelant la RegisterReceiver méthode, et le récepteur de diffusion doit être désinscrit avec un appel à la UnregisterReceiver méthode. Pour éviter les fuites de ressources, il est important de désinscrire le récepteur lorsqu’il n’est plus pertinent pour le contexte (l’activité ou le service). Par exemple, un service peut diffuser une intention d’informer une activité que des mises à jour peuvent être affichées pour l’utilisateur. Lorsque l’activité démarre, elle s’inscrit pour ces intentions. Lorsque l’activité est déplacée en arrière-plan et n’est plus visible par l’utilisateur, elle doit annuler l’inscription du récepteur, car l’interface utilisateur permettant d’afficher les mises à jour n’est plus visible. L’extrait de code suivant est un exemple d’inscription et de désinscription d’un récepteur de diffusion dans le contexte d’une activité :

[Activity(Label = "MainActivity", MainLauncher = true, Icon = "@mipmap/icon")]
public class MainActivity: Activity
{
    MySampleBroadcastReceiver receiver;

    protected override void OnCreate(Bundle savedInstanceState)
    {
        base.OnCreate(savedInstanceState);
        receiver = new MySampleBroadcastReceiver();

        // Code omitted for clarity
    }

    protected override void OnResume()
    {
        base.OnResume();
        RegisterReceiver(receiver, new IntentFilter("com.xamarin.example.TEST"));
        // Code omitted for clarity
    }

    protected override void OnPause()
    {
        UnregisterReceiver(receiver);
        // Code omitted for clarity
        base.OnPause();
    }
}

Dans l’exemple précédent, lorsque l’activité entre au premier plan, elle inscrit un récepteur de diffusion qui écoute une intention personnalisée à l’aide de la méthode de cycle de OnResume vie. Lorsque l’activité se déplace en arrière-plan, la OnPause() méthode annule l’inscription du récepteur.

Publication d’une diffusion

Une diffusion peut être publiée sur toutes les applications installées sur l’appareil en créant un objet Intent et en le répartissant avec la SendBroadcastSendOrderedBroadcast méthode ou.

  1. Méthodes Context.SendBroadcast : il existe plusieurs implémentations de cette méthode. Ces méthodes diffusent l’intention à l’ensemble du système. Diffuser les récepteurs qui recevront l’intention dans un ordre indéterminé. Cela offre une grande flexibilité, mais signifie qu’il est possible pour d’autres demandes de s’inscrire et de recevoir l’intention. Cela peut présenter un risque de sécurité potentiel. Les applications peuvent avoir besoin d’implémenter une sécurité supplémentaires pour empêcher tout accès non autorisé. Une solution possible consiste à utiliser le qui distribuera uniquement les LocalBroadcastManager messages dans l’espace privé de l’application. Cet extrait de code est un exemple de répartition d’une intention à l’aide de l’une SendBroadcast des méthodes suivantes :

    Intent message = new Intent("com.xamarin.example.TEST");
    // If desired, pass some values to the broadcast receiver.
    message.PutExtra("key", "value");
    SendBroadcast(message);
    

    Cet extrait de code est un autre exemple d’envoi d’une diffusion à l’aide de la Intent.SetAction méthode permettant d’identifier l’action :

    Intent intent = new Intent();
    intent.SetAction("com.xamarin.example.TEST");
    intent.PutExtra("key", "value");
    SendBroadcast(intent);
    
  2. Context.SendOrderedBroadcast : cette méthode est très similaire à Context.SendBroadcast, à la différence que l’intention sera publiée un à la fois sur les récepteurs, dans l’ordre dans lequel les récepteurs ont été inscrits.

LocalBroadcastManager

La bibliothèque de support Xamarin v4 fournit une classe d’assistance appelée LocalBroadcastManager. LocalBroadcastManager est destiné aux applications qui ne souhaitent pas envoyer ou recevoir de diffusions d’autres applications sur l’appareil. le LocalBroadcastManager publiera uniquement les messages dans le contexte de l’application, et uniquement sur les récepteurs de diffusion inscrits auprès de LocalBroadcastManager. Cet extrait de code est un exemple d’inscription d’un récepteur de diffusion avec LocalBroadcastManager:

Android.Support.V4.Content.LocalBroadcastManager.GetInstance(this). RegisterReceiver(receiver, new IntentFilter("com.xamarin.example.TEST"));

Les autres applications sur l’appareil ne peuvent pas recevoir les messages publiés avec .LocalBroadcastManager Cet extrait de code montre comment distribuer une intention à l’aide de :LocalBroadcastManager

Intent message = new Intent("com.xamarin.example.TEST");
// If desired, pass some values to the broadcast receiver.
message.PutExtra("key", "value");
Android.Support.V4.Content.LocalBroadcastManager.GetInstance(this).SendBroadcast(message);