Broadcast receiver
Les broadcasts receivers sont des programmes capables de traiter une intention envoyée par un broadcaster.
Déclarer/enregistrer les broadcasts receivers de votre application
Deux cas sont possibles:
Soit vous voulez toujours être informé:
Votre application peut ne pas être lancée lorsque les intentions sont diffusées. Pourtant, celle-ci doit être avertie lorsqu'il s'agit d'intentions particulières qu'elle est en mesure et doit gérer.
Pour que le système Android sâche que votre application gère des broadcast receivers, il est nécessaire de le préciser dans le fichier AndroidManifest.xml en indiquant un filtre sur les intentions pouvant être traitées par votre "receiver". Cela permettra à Android de lancer le traitement dans le cas où le type d'intention correspond au filtre positionné.
<receiver android:name="MonIntentReceiver">
<intent-filter>
<action android:name="fr.free.supertos.monbroadcastaction" />
</intent-filter>
</receiver>
La balise <receiver></receiver>
doit être déclarée dans la balise <application></application>
Soit ce n'est pas grave que vous ratiez certains messages ou le broadcast receveur doit mettre à jour l'interface utilisateur:
Votre application peut déclarer les broadcasts receivers qu'au moment où celle-ci est active (dynamiquement). En somme, vous voulez un BroadCastReceiver pour votre thread principal.
Dans ce cas, dans le onResume() de votre activité, vous pouvez enregistrer votre broadcast receiver et le filtre d'intention en utilisant la méthode
abstract Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter)
Il ne faudra pas oublier de se désabonner lorsque votre activité ne sera plus active via la méthode onPause():
unregisterReceiver(BroadcastReceiver receiver)
Pour un exemple: Cf. réception de SMS en dynamique.
N'oubliez pas les
éventuelles permissions dans le fichier AndroidManifest.xml !
Vous ne raterez
pas tous les évènements qui se sont produits avant la création
de votre broadcast receiver. En effet, bien qu'ayant fait "tardivement"
une déclaration dynamique de broadcast receiver, vous pourrez recevoir
des broadcasts antérieures à votre déclaration. Il s'agit
de "sticky broadcast", soit des messages pour lesquels le système
ne considère pas qu'il est grave pour application de les recevoir en
retard, mais au contraire qu'il est plus important qu'une application reçoive
ce message.
Quand ne pas enregistrer de BroadcastReceiver
Dans certains cas, il ne sera pas nécessaire d'enregistrer un BroadcastReceiver. En fait, l'enregistrement est nécessaire pour les broadcast intents, mais pas pour les sticky intents, des broadcast intents particulières.
Dans ce cas, vous passerez null à la place de receiver:
Intent intent = context.registerReceiver(null, filter);
Exemple la récupérations des informations sur la batterie
Dans ce cas, la
création du broadcast receiver (chapitre suivant) deviendra de fait inutile...
Créer un broadcast receiver
Il est possible d'envoyer des évènements, il est donc maintenant intéressant de voir comment récupérer ces évènements ! C'est le rôle des broadcast Receivers.
Les broadcast receivers appelés plus simplement receveurs vont étendre la classe BroadcastReceiver()
Cette classe ne comprend qu'une méthode:
public void onReceive(Context context, Intent intent) qu'il faudra surcharger ! Car c'est ici qu'il y aura du code pour traiter l'intention reçue.
Les broadcast receivers
doivent terminer leur traitement dans les 5 secondes. Sans quoi, le système
considère qu'ils sont plantés et affichera la dialogue proposant
d'arrêter l'application...
Il ne reste plus qu'à récupérer les informations éventuellement passées dans l'instance de l'intention.
La durée
de vie d'un receveur est limitée à la durée d'exécution
du onReceive.
Cf. L'exemple de broadcast et broadcast receiver
Permission sur les intentions
Comme déjà vu, il est possible de définir des permissions sur les intentions qui seront diffusées. Ainsi, seules les broadcast receivers avec cette permission définie pourront recevoir ces intentions.
Pour déclarer cette permission:
<uses-permission android:name="fr.free.supertos.MON_BROADCAST_PERMISSION"/>
Il est théoriquement possible de définir la permission directement dans le receiver (si vous voulez limiter la portée). Mais là, je n'ai pas du tout comprendre...Car cela ne fonctionne pas sous émulateur AVD:
<receiver android:name="MonIntentReceiver"
android:permission="fr.free.supertos.MON_BROADCAST_PERMISSION">
[...]
</receiver>
La déclaration
d'une permission personnelle doit être faite dans le fichier AndroidManifest.xml,
sinon vous allez obtenir un message d'erreur:
- Si la déclaration n'est pas faite dans le broadcaster:
permission denial: broadcasting intent {act=...le nom de l'intention...} from l'émetteur requires la permission due to receiver nom du receiver
Le mieux étant de définir tout cela à partir de l'onglet permissions.
- Si la déclaration n'est pas faite dans le broadcast receiver:
permission denial: receiving intent {act=...le nom de l'intention...} to le récepteur requires la permission due to sender nom de l'émetteur.
Cf. L'exemple de broadcast et broadcast receiver
Priorisation de l'ordre d'appel des broadcast receivers
Enfin, si vous voulez ordonner l'ordre d'appel des receveurs, vous pouvez positionner une priorité dans le filtre des receveurs.
<intent-filter android:priority="100">
<action android:name="fr.free.supertos.monbroadcastaction" />
</intent-filter>
Plus la valeur est grande, plus la priorité est forte, plus votre receveur sera appelé tôt par Android.
Cf. l'exemple avec le code de réception de SMS. Dans ce code, des sms avec une signature particulière seront traités uniquement par votre application. Les autres applications qui auraient pu traiter les SMS ne seront pas averties de ce SMS particulier. Pour cette raison, il est indispensable que notre code s'exécute en premier.
Si vous êtes
passé par l'enregistrement dynamique
de votre BroadcastReceiver, vous pouvez modifier la priorité directement
dans le filtre d'intention en utilisant la méthode
setPriority(). Cf. L'exemple de broadcast et broadcast
receiver ou l'exemple de réception
de SMS en dynamique.
Annuler la diffusion d'un broadcast
Il est possible d'interrompre un broadcast lancé par un Context.sendOrderedBroadcast().
Il suffit d'utiliser la méthode: final void abortBroadcast()
Cf. l'exemple avec le code de réception de SMS. Dans ce code, des sms avec une signature particulière seront traités uniquement par votre application. Les autres applications qui auraient pu traiter les SMS ne seront pas averties de ce SMS particulier.
Annuler un broadcast receiver
Il est donc possible de déclarer un broadcast receiver via le fichier AndroidManifest.xml, mais aussi dynamiquement. Dans les deux cas, il peut être nécessaire de désactiver un receiver.
Dans le cas d'une déclaration dynamique, c'est simple: unregisterReceiver(BroadcastReceiver receiver).
Mais dans le cas d'une décalartion depuis le fichier AndroidManifest.xml, l'opération est possible aussi via le PackageManager:
PackageManager pm = getPackageManager();
Pour désactiver le receiver déclarer dans le Manifest:
pm.setComponentEnabledSetting(monReceiver, PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP);
où monReceiver est défini comme suit:
ComponentName monReceiver = new ComponentName(this, MonReceiver.class);
Il sera possible de le réactiver ensuite:
pm.setComponentEnabledSetting(monReceiver, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP);