Gestion du Bluetooth au sein d’une application Windows Phone 8
Récemment j’ai été confronté à plusieurs problématiques liées au Bluetooth au sein d’une application Windows Phone 8.
- Au démarrage de l’application, détecter si le Bluetooth est actif.
- Si oui, rechercher un périphérique et s’y connecter via une socket.
- Si aucun périphérique n’est détecté, rechercher des périphériques tant qu’un appareil du type souhaité n’est pas connecté.
- Si le Bluetooth n’est pas activé, attendre que l’utilisateur l’active.
L’architecture du projet
J’ai fait le choix de distinguer deux choses :
- L’état du Bluetooth au niveau du téléphone lui-même (si celui-ci est activé ou non)
- L’état de la connexion entre le téléphone et le périphérique Bluetooth connecté (appareil connecté, en cours de connexion, déconnecté, etc.)
L’implémentation de ces deux composants pouvant évoluer, et certaines parties de notre application n’ayant pas besoin d’être fortement liées à ces implémentations. J’ai choisi d’utiliser un pattern permettant l’abstraction et la centralisation du changement d’état de ceux-ci. Voyons quel pattern va nous permettre de réaliser ceci.
Le pattern “Mediator”.
Le pattern Mediator est comme son nom l’indique, un médiateur entre les différents objets de notre application, certains d’entres eux vont s’inscrire aux évènements, d’autres vont les déclencher.
Mais attention, il faut bien comprendre la dangerosité d’un tel pattern. Si grâce à lui il est plus simple de gérer des évènements en les broadcastant, il est aussi plus simple de s’y perdre et de se retrouver avec des problèmes de fuite mémoire (ses évènements étant statiques, vos objets abonnés resteront en vie pendant toute la durée de vie de votre application si vous ne les désabonnez pas).
Vous l’aurez compris, notre Mediator aura donc pour but la centralisation des évènements liés au Bluetooth :
- Changement d’état du Bluetooth(activation, désactivation, état inconnu?)
- Changement d’état de notre appareil BT connecté (connexion, déconnexion “propre”, déconnexion impromptue, déconnexion édulcorée)
Place au code !
Comme dit plus haut, le Mediator n’est rien d’autre qu’un conteneur d’évènements.
public static class Mediator { public enum BluetoothState { Connected, Disconnected, Unknown } public static event EventHandler<BluetoothState> BluetoothStateChanged; public static void RaiseBluetoothStateChanged(BluetoothState newState) { var handler = BluetoothStateChanged; if (handler != null) { handler.Invoke(null, newState); } } public enum BluetoothDeviceState { ConnectedToPhone, SocketOpened, Disconnected, Unknown } public static event EventHandler<BluetoothDevice> BluetoothDeviceStateChanged; public static void RaiseBluetoothDeviceStateChanged(BluetoothState newState) { var handler = BluetoothDeviceStateChanged; if (handler != null) { handler.Invoke(null, newState); } } }
Ce code est assez simple à comprendre, il est découpé en deux parties contenant pour chacune :
- Un évènement (BluetoothStateChanged, BluetoothDeviceStateChanged)
- Une méthode de déclenchement de cet event (RaiseBluetoothStateChanged, RaiseBluetoothDeviceStateChanged)
- Une énumération (BluetoothState, BluetoothDeviceState) permettant de décrire un état
Il suffira donc de s’inscrire au lancement de l’application aux évènements qui nous intéressent afin de pouvoir être notifié de tout changement!
Passons maintenant au cœur du sujet, la gestion du Bluetooth.
Comment gérer l’activation/désactivation du Bluetooth au sein d’une application?
Si vous pensiez qu’une méthode du genre : “BluetoothInterface.GetIsBluetoothAvailable()” existe. Je suis navré mais ce n’est pas le cas.
Il va nous falloir lancer une détection des appareils Bluetooth à l’aide de la classe PeerFinder, puis catcher l’exception si quelque chose se passe mal (pratique non?). C’est donc ici que va rentrer en jeu notre architecture évènementielle orchestrée par notre fameux Mediator (En ré mineur s’il vous plait!).
Nous allons donc nous créer une classe BluetoothHelper, qui va se charger de nous renvoyer si oui ou non notre Bluetooth est bien actif.
public class BluetoothHelper { public static async Task<bool> IsBluetoothEnable() { bool isEnable = true; Windows.Networking.Proximity.PeerFinder.Start(); try { var peers = await Windows.Networking.Proximity.PeerFinder.FindAllPeersAsync(); } catch (Exception ex) { //Ne pas oublier de stoper la recherche de peers //si le BT n'est pas actif. Windows.Networking.Proximity.PeerFinder.Stop(); if ((uint)ex.HResult == 0x8007048F) { isEnable = false; } } return isEnable; } }
Vous l’aurez compris, il suffira ensuite d’appeler le BluetootHelper à deux moments clés de l’exécution de notre application, dans le application_launching, et dans le application_activated, et de déclencher notre Mediator en conséquence.
private async void Application_Launching(object sender, LaunchingEventArgs e) { bool btIsEnable = await BluetoothHelper.CheckBluetoothIsEnable(); if (btIsEnable) Mediator.RaiseBluetoothStateChanged(Mediator.BluetoothState.Connected); else Mediator.RaiseBluetoothStateChanged(Mediator.BluetoothState.Disconnected); //Executer le même code dans la méthode Application_Activating }
Commentaires