Les applications Android peuvent envoyer ou recevoir des annonces depuis le système Android et d'autres applications Android, semblables à publish-subscribe modèle de conception. Ces annonces sont envoyées lorsqu'un événement intéressant se produit. Par exemple, le système Android envoie des annonces lorsque divers événements système (par exemple, lorsque le système démarre ou que l'appareil commence à se recharger). Applications peut également envoyer des annonces personnalisées, par exemple pour avertir d'autres applications quelque chose qui pourrait les intéresser (par exemple, certaines nouvelles données téléchargé).
Le système optimise la diffusion des diffusions afin de maintenir l'état optimal du système. Par conséquent, les délais de livraison des diffusions ne sont pas sont garantis. Les applications nécessitant une communication inter-processus à faible latence doivent pensez aux services liés.
Les applications peuvent s'inscrire pour recevoir des annonces spécifiques. Lorsqu'une diffusion est envoyée, le système achemine automatiquement les annonces vers les applications qui se sont abonnées recevoir ce type particulier de diffusion.
De manière générale, les annonces peuvent être utilisées comme un système de messagerie pour toutes les applications. et en dehors du flux utilisateur normal. Toutefois, vous devez veiller à ne pas utiliser possibilité de répondre aux annonces et d'exécuter des jobs en arrière-plan peut contribuer à la lenteur des performances du système.
À propos des diffusions système
Le système envoie automatiquement des annonces lorsque divers événements système se produisent, comme lorsque le système passe en mode Avion et le quitte. Système les annonces sont envoyées à toutes les applications auxquelles vous êtes abonné pour recevoir les .
Le message de diffusion lui-même est encapsulé dans un Intent
.
objet dont la chaîne d'action identifie l'événement qui s'est produit (par exemple,
android.intent.action.AIRPLANE_MODE
). L'intention peut également inclure
des informations supplémentaires
rgroupées dans son champ supplémentaire. Par exemple, l'avion
inclut un extra booléen qui indique si le mode Avion est défini ou non
Le mode est activé.
Pour savoir comment lire les intents et obtenir la chaîne d'action à partir de un intent, consultez la section Intents Filtres.
Pour obtenir la liste complète des actions de diffusion du système, consultez la
BROADCAST_ACTIONS.TXT
dans le SDK Android. Chaque action de diffusion possède un
constante qui lui est associée. Par exemple, la valeur de la constante
ACTION_AIRPLANE_MODE_CHANGED
correspond à
android.intent.action.AIRPLANE_MODE
Documentation sur chaque action de diffusion
est disponible dans le champ de constante associé.
Modifications apportées aux diffusions système
À mesure que la plate-forme Android évolue, elle modifie régulièrement la façon dont le système diffuse et le comportement de l'utilisateur. Tenez compte des modifications suivantes pour assurer la compatibilité avec toutes les versions d'Android.
Android 14
Lorsque les applications sont en cache
, la diffusion de diffusion est
optimisé pour l'état du système. Par exemple, les annonces
système moins importantes
que ACTION_SCREEN_ON
sont
reporté tant que l'application est en cache. Une fois que l'application passe du cache
l'état en un processus actif
cycle de vie, le système livre
les diffusions différées.
Annonces importantes déclarées dans le fichier manifeste supprimer temporairement des applications du cache pour la diffusion.
Android 9
À partir d'Android 9 (niveau d'API 28),
NETWORK_STATE_CHANGED_ACTION
ne reçoit aucune information sur la position de l'utilisateur ou sur
des données identifiables.
De plus, si votre application est installée sur un appareil équipé d'Android 9 ou version ultérieure,
les diffusions du système à partir du Wi-Fi ne contiennent pas de SSID, BSSID,
des informations ou des résultats d'analyse. Pour obtenir ces informations, appelez
getConnectionInfo()
à la place.
Android 8.0
À partir d'Android 8.0 (niveau d'API 26), le système impose des des restrictions sur les récepteurs déclarés par le fichier manifeste.
Si votre application cible Android 8.0 ou une version ultérieure, vous ne pouvez pas utiliser le fichier manifeste pour déclarer un récepteur pour la plupart des diffusions implicites (annonces qui ne ciblent pas spécifiquement pour votre application). Vous pouvez toujours utiliser un destinataire enregistré en contexte lorsque le utilise activement votre application.
Android 7.0
Android 7.0 (niveau d'API 24) ou version ultérieure n'envoie pas le système suivant diffusions:
De plus, les applications ciblant Android 7.0 ou version ultérieure doivent enregistrer la diffusion CONNECTIVITY_ACTION
.
avec registerReceiver(BroadcastReceiver, IntentFilter)
.
La déclaration d'un destinataire dans le fichier manifeste ne fonctionne pas.
Recevoir des annonces
Les applications peuvent recevoir des annonces de deux manières: via des récepteurs déclarés dans le fichier manifeste. et les récepteurs enregistrés en contexte.
Destinataires déclarés dans le fichier manifeste
Si vous déclarez un broadcast receiver dans votre fichier manifeste, le système lance votre application (si elle n'est pas déjà en cours d'exécution) lors de l'envoi de la diffusion.
Pour déclarer un broadcast receiver dans le fichier manifeste, procédez comme suit:
Spécifiez la
<receiver>
dans le fichier manifeste de votre application.<!-- If this receiver listens for broadcasts sent from the system or from other apps, even other apps that you own, set android:exported to "true". --> <receiver android:name=".MyBroadcastReceiver" android:exported="false"> <intent-filter> <action android:name="APP_SPECIFIC_BROADCAST" /> </intent-filter> </receiver>
Les filtres d'intent spécifient les actions de diffusion auxquelles votre récepteur s'abonne.
Sous-classe
BroadcastReceiver
et implémentezonReceive(Context, Intent)
. La broadcast receiver dans les exemples de journaux suivants et affiche le contenu de la diffusion:Kotlin
private const val TAG = "MyBroadcastReceiver" class MyBroadcastReceiver : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { StringBuilder().apply { append("Action: ${intent.action}\n") append("URI: ${intent.toUri(Intent.URI_INTENT_SCHEME)}\n") toString().also { log -> Log.d(TAG, log) val binding = ActivityNameBinding.inflate(layoutInflater) val view = binding.root setContentView(view) Snackbar.make(view, log, Snackbar.LENGTH_LONG).show() } } } }
Java
public class MyBroadcastReceiver extends BroadcastReceiver { private static final String TAG = "MyBroadcastReceiver"; @Override public void onReceive(Context context, Intent intent) { StringBuilder sb = new StringBuilder(); sb.append("Action: " + intent.getAction() + "\n"); sb.append("URI: " + intent.toUri(Intent.URI_INTENT_SCHEME).toString() + "\n"); String log = sb.toString(); Log.d(TAG, log); ActivityNameBinding binding = ActivityNameBinding.inflate(layoutInflater); val view = binding.root; setContentView(view); Snackbar.make(view, log, Snackbar.LENGTH_LONG).show(); } }
Pour activer la liaison de vue, configurer viewBinding au niveau du module build.gradle.
Le gestionnaire de packages système enregistre le récepteur lorsque l'application est installée. Le récepteur devient alors un point d'entrée distinct dans votre application, ce qui signifie que le système puisse lancer l'application et diffuser la diffusion si l'application n'est pas en cours d'exécution.
Le système crée un composant BroadcastReceiver
.
pour gérer chaque annonce qu'il reçoit. Cet objet n'est valide que
pendant la durée de l'appel à onReceive(Context, Intent)
. Une fois que votre code
renvoyées par cette méthode, le système considère que le composant n'est plus
actif.
Récepteurs enregistrés en contexte
Les récepteurs enregistrés en contexte reçoivent des annonces à condition que leur enregistrement
le contexte est valide. Par exemple, si vous vous inscrivez au sein d'un
Activity
vous recevez des annonces tant que l'activité n'est pas détruite. Si vous
s'inscrire dans le contexte de l'application, vous recevez des annonces à condition que l'application
est en cours d'exécution.
Pour enregistrer un récepteur avec un contexte, procédez comme suit:
Dans le fichier de compilation au niveau du module de votre application, incluez la version 1.9.0 ou ultérieure de la bibliothèque AndroidX Core:
Groovy
dependencies { def core_version = "1.13.1" // Java language implementation implementation "androidx.core:core:$core_version" // Kotlin implementation "androidx.core:core-ktx:$core_version" // To use RoleManagerCompat implementation "androidx.core:core-role:1.0.0" // To use the Animator APIs implementation "androidx.core:core-animation:1.0.0" // To test the Animator APIs androidTestImplementation "androidx.core:core-animation-testing:1.0.0" // Optional - To enable APIs that query the performance characteristics of GMS devices. implementation "androidx.core:core-performance:1.0.0" // Optional - to use ShortcutManagerCompat to donate shortcuts to be used by Google implementation "androidx.core:core-google-shortcuts:1.1.0" // Optional - to support backwards compatibility of RemoteViews implementation "androidx.core:core-remoteviews:1.1.0" // Optional - APIs for SplashScreen, including compatibility helpers on devices prior Android 12 implementation "androidx.core:core-splashscreen:1.2.0-alpha01" }
Kotlin
dependencies { val core_version = "1.13.1" // Java language implementation implementation("androidx.core:core:$core_version") // Kotlin implementation("androidx.core:core-ktx:$core_version") // To use RoleManagerCompat implementation("androidx.core:core-role:1.0.0") // To use the Animator APIs implementation("androidx.core:core-animation:1.0.0") // To test the Animator APIs androidTestImplementation("androidx.core:core-animation-testing:1.0.0") // Optional - To enable APIs that query the performance characteristics of GMS devices. implementation("androidx.core:core-performance:1.0.0") // Optional - to use ShortcutManagerCompat to donate shortcuts to be used by Google implementation("androidx.core:core-google-shortcuts:1.1.0") // Optional - to support backwards compatibility of RemoteViews implementation("androidx.core:core-remoteviews:1.1.0") // Optional - APIs for SplashScreen, including compatibility helpers on devices prior Android 12 implementation("androidx.core:core-splashscreen:1.2.0-alpha01") }
Créer une instance de
BroadcastReceiver
:Kotlin
val br: BroadcastReceiver = MyBroadcastReceiver()
Java
BroadcastReceiver br = new MyBroadcastReceiver();
Créer une instance de
IntentFilter
:Kotlin
val filter = IntentFilter(APP_SPECIFIC_BROADCAST)
Java
IntentFilter filter = new IntentFilter(APP_SPECIFIC_BROADCAST);
Indiquez si le broadcast receiver doit être exporté et visible par d'autres applications sur l'appareil. Si ce destinataire écoute les annonces envoyées du système ou d'autres applications, ou même d'autres applications dont vous êtes le propriétaire, utilisent le
RECEIVER_EXPORTED
. Si, au contraire, ce récepteur n'écoute que les annonces envoyées par votre application, utilisez l'indicateurRECEIVER_NOT_EXPORTED
.Kotlin
val listenToBroadcastsFromOtherApps = false val receiverFlags = if (listenToBroadcastsFromOtherApps) { ContextCompat.RECEIVER_EXPORTED } else { ContextCompat.RECEIVER_NOT_EXPORTED }
Java
boolean listenToBroadcastsFromOtherApps = false; if (listenToBroadcastsFromOtherApps) { receiverFlags = ContextCompat.RECEIVER_EXPORTED; } else { receiverFlags = ContextCompat.RECEIVER_NOT_EXPORTED; }
Enregistrez le récepteur en appelant
registerReceiver()
:Kotlin
ContextCompat.registerReceiver(context, br, filter, receiverFlags)
Java
ContextCompat.registerReceiver(context, br, filter, receiverFlags);
Pour ne plus recevoir d'annonces, appelez
unregisterReceiver(android.content.BroadcastReceiver)
. Pensez à annuler l'enregistrement du récepteur lorsque vous n'en avez plus besoin le contexte n'est plus valide.Faites attention à l'emplacement où vous enregistrez ou annulez l'enregistrement du récepteur, Par exemple, si vous enregistrez un récepteur dans
onCreate(Bundle)
à l'aide du contexte de l'activité, vous doit annuler son enregistrement dansonDestroy()
pour empêcher la fuite du récepteur hors du contexte de l'activité. Si vous vous inscrivez un récepteur dansonResume()
, vous devez annulez-le dansonPause()
pour empêcher en l'enregistrant plusieurs fois (si vous ne voulez pas recevoir d'annonces lorsqu'elles sont mises en pause, ce qui permet de réduire les frais généraux inutiles sur le système). À ne pas faire se désinscrire deonSaveInstanceState(Bundle)
car elle n'est pas appelée si l'utilisateur revient dans la pile de l'historique.
Effets sur l'état du processus
Que votre BroadcastReceiver
fonctionne ou n'affecte pas le processus qu'il contient, ce qui peut altérer son
la probabilité de suppression du système. Un processus de premier plan exécute la méthode onReceive()
d'un récepteur. La
système exécute le processus, sauf
en cas de pression extrême de la mémoire.
BroadcastReceiver est désactivé après onReceive()
. Hôte du destinataire
n'est importante que pour ses composants d'application. Si ce processus n'héberge que
un destinataire déclaré dans le fichier manifeste (ce qui arrive fréquemment pour les applications que l'utilisateur n'a jamais
ou avec lesquelles vous n'avez pas interagi récemment), le système peut la fermer après onReceive()
pour
ressources disponibles pour
d’autres processus plus critiques.
Ainsi, les broadcast receivers ne doivent pas lancer de threads de longue durée en arrière-plan.
Le système peut arrêter le processus à tout moment après onReceive()
pour récupérer
mémoire, mettant fin au thread créé. Pour que le processus reste actif, planifiez une
JobService
à partir du récepteur à l'aide de JobScheduler
afin que le système sache que
le processus fonctionne toujours.
La page Présentation des tâches en arrière-plan fournit plus de détails.
Envoyer des annonces
Android propose trois façons pour les applications d'envoyer une diffusion:
sendOrderedBroadcast(Intent, String)
envoie des annonces à un destinataire à la fois. Lorsque chaque récepteur exécute à son tour, il peut propager un résultat au destinataire suivant ou annuler complètement la diffusion afin qu'elle ne soit pas transmise à d'autres récepteurs. L'ordre dans lequel les récepteurs s'exécutent peut être contrôlé Attribut android:Priority de l'intent-filter correspondant récepteurs avec même priorité seront exécutées dans un ordre arbitraire.- La méthode
sendBroadcast(Intent)
envoie diffuse des annonces à tous les récepteurs dans un ordre indéterminé. C'est ce que l'on appelle Diffuser. C'est plus efficace, mais cela signifie que les récepteurs ne peuvent pas lire des résultats provenant d'autres récepteurs, de propager les données reçues de la diffusion ou annuler la diffusion.
L'extrait de code suivant montre comment envoyer une diffusion en créant une
Intention et appel de sendBroadcast(Intent)
.
Kotlin
Intent().also { intent -> intent.setAction("com.example.broadcast.MY_NOTIFICATION") intent.putExtra("data", "Nothing to see here, move along.") sendBroadcast(intent) }
Java
Intent intent = new Intent(); intent.setAction("com.example.broadcast.MY_NOTIFICATION"); intent.putExtra("data", "Nothing to see here, move along."); sendBroadcast(intent);
Le message de diffusion est encapsulé dans un objet Intent
.
La chaîne d'action de l'intent doit fournir la syntaxe du nom de package Java de l'application et
identifier de manière unique
l'événement de diffusion. Vous pouvez joindre des informations
à l'intent avec putExtra(String, Bundle)
.
Vous pouvez également limiter une diffusion à un ensemble d'applications de la même organisation en
en appelant setPackage(String)
sur l'intent.
Limiter les diffusions avec des autorisations
Les autorisations vous permettent de limiter les diffusions à l'ensemble des applications qui contiennent certaines autorisations. Vous pouvez appliquer des restrictions à l'expéditeur ou le destinataire d'une diffusion.
Envoyer avec des autorisations
Lorsque vous appelez le sendBroadcast(Intent, String)
ou
sendOrderedBroadcast(Intent, String, BroadcastReceiver, Handler, int, String, Bundle)
, vous pouvez spécifier
d'autorisation. Seuls les destinataires qui ont demandé cette autorisation avec
la balise
Kotlin
sendBroadcast(Intent(BluetoothDevice.ACTION_FOUND), Manifest.permission.BLUETOOTH_CONNECT)
Java
sendBroadcast(new Intent(BluetoothDevice.ACTION_FOUND), Manifest.permission.BLUETOOTH_CONNECT)
Pour recevoir la diffusion, l'application réceptrice doit demander l'autorisation en tant que comme indiqué ci-dessous:
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT"/>
Vous pouvez spécifier une
autorisation système existante, comme
BLUETOOTH_CONNECT
ou définissez une autorisation personnalisée
<permission>
. Pour
des informations sur les autorisations et la sécurité en général, consultez la page
Autorisations.
Réception avec autorisations
Si vous spécifiez un paramètre d'autorisation lors de l'enregistrement d'un broadcast receiver
(avec registerReceiver(BroadcastReceiver, IntentFilter, String, Handler)
ou dans
Balise <receiver>
dans votre
manifeste), seuls les diffuseurs ayant demandé l'autorisation
Balise <uses-permission>
dans leur fichier manifeste (et qui ont ensuite reçu l'autorisation
dangereux) peut envoyer un intent au récepteur.
Par exemple, supposons que votre application réceptrice dispose d'un destinataire déclaré dans le fichier manifeste, comme indiqué ci-dessous:
<receiver android:name=".MyBroadcastReceiver"
android:permission="android.permission.BLUETOOTH_CONNECT">
<intent-filter>
<action android:name="android.intent.action.ACTION_FOUND"/>
</intent-filter>
</receiver>
Ou votre application réceptrice dispose d'un récepteur enregistré en contexte, comme indiqué ci-dessous:
Kotlin
var filter = IntentFilter(Intent.ACTION_FOUND) registerReceiver(receiver, filter, Manifest.permission.BLUETOOTH_CONNECT, null )
Java
IntentFilter filter = new IntentFilter(Intent.ACTION_FOUND); registerReceiver(receiver, filter, Manifest.permission.BLUETOOTH_CONNECT, null );
Ensuite, pour pouvoir envoyer des annonces à ces récepteurs, l'application émettrice doit demandez l'autorisation comme indiqué ci-dessous:
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT"/>
Remarques sur la sécurité et bonnes pratiques
Voici quelques considérations de sécurité et les meilleures pratiques pour l'envoi et recevoir des diffusions:
Si de nombreuses applications se sont inscrites pour recevoir la même annonce le fichier manifeste, cela peut amener le système à lancer un grand nombre d'applications, ce qui provoque une un impact important sur les performances des appareils et sur l'expérience utilisateur. Pour éviter utilisez plutôt l'enregistrement du contexte plutôt que la déclaration du fichier manifeste. Parfois, le système Android impose lui-même l'utilisation de données de contexte enregistrées récepteurs. Par exemple, l'annonce
CONNECTIVITY_ACTION
est diffusée. uniquement pour les récepteurs enregistrés en contexte.Ne diffusez pas d'informations sensibles à l'aide d'un intent implicite. La les informations peuvent être lues par toute application qui s'inscrit pour recevoir la diffusion. Il existe trois façons de contrôler qui peut recevoir vos annonces:
- Vous pouvez spécifier une autorisation lorsque vous envoyez une diffusion.
- Dans Android 4.0 et versions ultérieures, vous pouvez spécifier un
package avec
setPackage(String)
lors de l'envoi d'un annonce. Le système limite la diffusion à l'ensemble des applications correspondent au package.
Lorsque vous enregistrez un récepteur, toute application peut envoyer diffuse des annonces au récepteur de votre application. Il existe plusieurs façons de limiter que votre application reçoit:
- Vous pouvez spécifier une autorisation lors de l'enregistrement d'un broadcast receiver.
- Pour les destinataires déclarés dans le fichier manifeste, vous pouvez définir android:exported Attribut sur "false" dans le fichier manifeste. Le récepteur ne reçoit pas les annonces à partir de sources externes à l'application.
L'espace de noms des actions de diffusion est global. Assurez-vous que les noms des actions et d'autres chaînes sont écrites dans un espace de noms qui vous appartient. Sinon, vous pouvez en conflit avec d'autres applications.
Comme la méthode
onReceive(Context, Intent)
d'un destinataire s'exécute sur le thread principal, il devrait s'exécuter et revenir rapidement. Si vous avez besoin de des tâches de longue durée, évitez de générer des threads ou de démarrer les services d’arrière-plan car le système peut tuer l’ensemble du processus après Retours deonReceive()
. Pour plus d'informations, consultez la section Effet sur le processus Pour effectuer un travail de longue durée, recommandent:- Vous appelez
goAsync()
dans votre la méthodeonReceive()
du récepteur et transmettre leBroadcastReceiver.PendingResult
à un thread d'arrière-plan. La diffusion reste ainsi active après son retour depuisonReceive()
. Cependant, même avec cette approche, le système s'attend à ce que vous terminiez la diffusion très rapidement (moins de 10 secondes). Cela vous permet de déplacer travailler sur un autre thread pour éviter de perturber le thread principal. - Planifier une tâche avec
JobScheduler
Pour plus pour plus d'informations, consultez la page Planification.
- Vous appelez
Ne pas démarrer les activités des broadcast receivers, car l'expérience utilisateur est bouleversant. surtout s'il y a plusieurs destinataires. Envisagez plutôt affichant une notification.