• Facile

Ce cours est visible gratuitement en ligne.

Vous pouvez être accompagné et mentoré par un professeur particulier par visioconférence sur ce cours.

J'ai tout compris !

Mis à jour le 29/04/2014

Les notifications

Connectez-vous ou inscrivez-vous gratuitement pour bénéficier de toutes les fonctionnalités de ce cours !

Le principe des notifications n’est pas vraiment nouveau mais est globalement plutôt simple. Imaginons que j’installe une application qui me permette de consulter les cours de la plateforme OpenClassrooms. Ca y est, j’ai lu tous les cours qui m’intéressent et j’ai hâte que de nouveaux cours voient le jour pour que je puisse assouvir ma soif d’apprendre. Sauf que je ne vais pas démarrer l’application toutes les 5 minutes histoire de voir si un nouveau cours est en ligne … ça serait bien si quelqu’un me prévenait dès qu’un nouveau cours est mis en ligne. Et tout ça, même si l’application n’est pas démarrée ou épinglée …

Voilà, le principe de la notification. Cela consiste en la réception d’un petit message sur notre téléphone avec une information. La réception du message peut être signalée par un bruit ou une vibration, puis le message reste affiché quelques secondes pour nous donner le temps de le lire. Mieux, si nous cliquons sur le message, notre application est automatiquement démarrée.
En revanche, un des inconvénients est justement que la notification ne s’affiche que quelques secondes et si on est loin du téléphone, il n’y a aucun moyen pour voir le contenu si on l’a raté (en tout cas à l'heure où j'écris ces lignes, car il y aurait des rumeurs de création de centre de notification ...).

Mais les notifications sont tout de même bien pratiques, donc plongeons nous tout de suite dans le vif du sujet pour créer nos propres alertes et rester au courant des nouveautés de nos applications préférées !

Le principe d’architecture des notifications

Pour recevoir une notification, il faut que quelqu’un l’envoie. Forcément !
Et pour que ce quelqu’un l’envoie, il faut qu’on lui dise que ça nous intéresse de recevoir des notifications.
Donc, le principe global peut se résumer dans les étapes suivantes :

  • L’application Windows Phone déclare un canal pour recevoir des notifications.

  • L’application Windows Phone indique à l’émetteur (le créateur de l’application) qu’elle souhaite recevoir des notifications et lui donne l’identifiant unique du téléphone sur lequel elle tourne ainsi que le canal.

  • L’émetteur enregistre l’identifiant et le canal et l’ajoute à la liste des toutes les applications souhaitant recevoir des notifications.

  • L’émetteur souhaite envoyer un message : pour chaque téléphone souhaitant recevoir des notifications, le message est envoyé au service de notification de Microsoft (le Microsoft Push Notification Service) grâce au canal.

  • Le service de notification envoi le message à chaque téléphone.

  • Le message s'affiche sur le téléphone de l'utilisateur.

Il y a donc trois intervenants dans ce mécanisme :

  • Le téléphone, qui reçoit les notifications, ainsi que l'application installée dessus (votre application !),

  • Le service de notification, créé par le développeur qui souhaite envoyer des notifications (VOUS !),

  • Le service de notification de Microsoft, qui s’occupe d’envoyer vraiment le message au téléphone.

Sachez que le message peut être de plusieurs types.

  • Cela peut être un message système qui apparaît même si l’application n’a pas démarrée. Il apparaît en haut du téléphone et si l’on clique dessus alors l’application démarre. Il s’agit des notifications Toast.

  • Cela peut être un message qui va modifier l’apparence d’une tuile. Ce message a peu d’intérêt depuis Mango car les tuiles peuvent être pilotées par code facilement, comme nous l’avons vu précédemment, mais il peut quand même trouver son intérêt. Il s’agit des notifications Tile.

  • Enfin, cela peut être un message qui apparaît alors que l’application est en cours d’utilisation. Si l’application n’est pas lancée, alors le message est ignoré. Il s’agit des notifications Raw.

On peut résumer l'architecture avec le schéma suivant, qui comprend 4 grandes étapes :

  • 1. La connexion s'établit et une URL est créée pour la communication.

  • 2. Communication de l'URL.

  • 3. Envoi du message.

  • 4. Envoi du message sur le téléphone.

Architecture des notifications
Architecture des notifications

Le principe de création du serveur de notification

Je vais décrire ici le principe de création du serveur de notification sachant que nous n’allons pas le réaliser car il sort de la portée de ce cours. Mais ne vous inquiétez pas, dans ce chapitre nous ferons comme si le serveur avait été créé et nous nous occuperons de ce qui se passe juste après un envoi de notification.
Ce serveur de notification consiste en général en un site web ou des services web, car ceux-ci doivent être toujours disponibles en ligne, à n’importe quel moment. Celui-ci peut-être bien sûr un serveur à base de produits Microsoft (avec un logiciel de serveur IIS et des composants WCF), mais il peut tout aussi bien être en PHP, Ruby ou ce que vous maîtrisez.
Le principe est de fournir une URL permettant d’enregistrer un identifiant unique de téléphone ainsi que le canal (en fait, seul le canal est vraiment indispensable). Un téléphone souhaitant recevoir des notifications va s’enregistrer auprès du service de notification de Microsoft et recevra une URL identifiant le canal en retour. L’URL est de la forme :

http://db3.notify.live.net/throttledthirdparty/01.00/AAE17kNJdrSwXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXQTg1QkZDMkUxREQ

Le téléphone appelle ensuite le serveur de notification pour lui fournir cette URL ainsi que son identifiant unique. Le serveur devra être capable de stocker cet identifiant ainsi que l’URL et devra également permettre de modifier l’URL si l’identifiant est déjà stocké. Le serveur va donc servir à stocker une liste d’identifiants associés à des URL et à la maintenir à jour.
Puis, lorsque nous voudrons envoyer une notification à tous les utilisateurs de notre application, il suffira de parcourir cette liste et d’envoyer un message au serveur de Microsoft, via l’URL du canal, contenant le message. C’est ensuite le serveur de Microsoft qui s’occupe d’envoyer la notification à chaque téléphone, grâce à ce canal.

Et voilà, en fait c’est très simple.

Dans l’idéal, le serveur devra également permettre de désabonner un téléphone ne souhaitant plus recevoir de notifications, car il est indispensable que votre application propose à son utilisateur un moyen d’arrêter de recevoir des notifications. De même, lorsque le serveur de notification envoie la requête à Microsoft permettant l’envoi du message, ce dernier lui répond en lui indiquant notamment si le téléphone est injoignable. Cela pourra correspondre au fait que l’application est désinstallée par exemple. À ce moment-là, il faudra mettre à jour la liste des identifiants et des URL afin de supprimer le couple identifiant-canal, pour ne plus tenter de lui envoyer de notifications.

N’hésitez pas à créer votre propre serveur de notification, avec le langage de votre choix, et pourquoi pas à proposer les sources d’un tel serveur afin que chacun puisse s’en servir pour héberger son serveur de notification.

Les différents messages de notifications

Nous avons vu les différents types de notification :

  • Toast,

  • Tile,

  • Raw.

Pour déclencher une telle notification, il faut envoyer un message au serveur de Microsoft contenant du XML, ou du texte simple, en fonction du type de notification. Ce message devra être envoyé avec la méthode POST, dans un format XML (content-type="text/xml") et contenir des en-têtes HTTP personnalisées. Il y a plusieurs éléments à passer dans les en-têtes HTTP, plus ou moins obligatoires. Par exemple, il est possible et facultatif de fournir un identifiant de message via l’en-tête HTTP MessageID. En revanche, nous devons obligatoirement fournir dans l’en-tête le type de notification. Cela se fait avec l'attribut X-Windows-Phone-Target. Par exemple, on ajoute le code ci-dessous dans l'en-tête pour une notification de type toast :

X-WindowsPhone-Target:type

Le message de notification envoyé au serveur de Microsoft peut être de trois types différents :

  • Message de type toast, pour les notifications toast.

  • Message de type token, pour les notifications tile.

  • Message de type raw, pour les notifications raw.

Nous devons également indiquer le délai d’envoi, qui varie selon le type de notification comme le montre le tableau suivant.

-

Envoi immédiat

Délai de 450 secondes (7 minutes et demie)

Délai de 15 minutes

Tile

1

11

21

Toast

2

12

22

Raw

3

13

23

Par exemple, pour envoyer une notification Toast immédiatement, je devrais avoir l’en-tête HTTP suivante :

X-WindowsPhone-Target:toast
X-NotificationClass:2

Ensuite, reste le corps du message.

  • Pour envoyer un message de type raw, c’est très simple. Il suffit d’envoyer le message tel quel, pas besoin d’XML.

  • Pour envoyer un message de type toast, nous aurons besoin de démarrer l'application dans un contexte particulier. Pour cela, il nous faudra exécuter une requête query string dans une page XAML de l'application. Il faudra envoyer le XML suivant avec cette page XAML comme Paramètre :

    <?xml version="1.0" encoding="utf-8"?>
    <wp:Notification xmlns:wp="WPNotification">
      <wp:Toast>
        <wp:Text1>Titre</wp:Text1>
        <wp:Text2>Sous titre</wp:Text2>
        <wp:Param>paramètre</wp:Param>
      </wp:Toast>
    </wp:Notification>
    
  • Enfin, pour envoyer un message de type tile, nous aurons le XML suivant :

    <?xml version="1.0" encoding="utf-8"?>
    <wp:Notification xmlns:wp="WPNotification">
      <wp:Tile>
        <wp:BackgroundImage>Url image de fond</wp:BackgroundImage>
        <wp:Count>Numéro en haut à droite</wp:Count>
        <wp:Title>Titre</wp:Title>
        <wp:BackBackgroundImage>Url image de fond du dos de la tuile</wp:BackBackgroundImage>
        <wp:BackTitle>Titre du dos de la tuile</wp:BackTitle>
        <wp:BackContent>Contenu du dos de la tuile</wp:BackContent>
      </wp:Tile>
    </wp:Notification>
    

Nous allons voir dans le chapitre suivant comment envoyer ces beaux messages et surtout ce qu’il faut faire côté Windows Phone pour créer un canal et réagir aux notifications.

Création du client Windows Phone recevant la notification

Avant toute chose, vous devez déclarer que votre application utilise des notifications. Cela se fait en utilisant la capacité ID_CAP_PUSH_NOTIFICATION que nous allons voir à l'œuvre dans cette section.
Il faut ensuite créer ou utiliser un canal depuis notre application Windows Phone. Un canal est identifié par son nom. La première chose est de tenter de le récupérer s’il existe déjà, sinon il faut le créer.
Voici comment utiliser un canal pour recevoir une notification Toast :

public MainPage()
{
    InitializeComponent();

    string nomCanal = "TestCanalOpenClassroomsNico";
    HttpNotificationChannel canal = HttpNotificationChannel.Find(nomCanal);

    if (canal == null)
    {
        // si le canal n'est pas trouvé, on le crée
        canal = new HttpNotificationChannel(nomCanal);

        canal.ChannelUriUpdated += canal_ChannelUriUpdated;
        canal.ErrorOccurred += canal_ErrorOccurred;

        // On s'abonne à cet événement si on veut être averti de la reception de la notification toast lorsque l'application
        // est ouverte, sinon on ne la recoit pas
        canal.ShellToastNotificationReceived += canal_ShellToastNotificationReceived;

        canal.Open();

        // Permet de déclarer le canal pour recevoir les toasts
        canal.BindToShellToast();
    }
    else
    {
        // le canal est déjà créé, on l'utilise
        canal.ChannelUriUpdated +=canal_ChannelUriUpdated;
        canal.ErrorOccurred +=canal_ErrorOccurred;
        canal.ShellToastNotificationReceived += canal_ShellToastNotificationReceived;

        // On affiche le canal dans la console de sortie pour pouvoir l'exploiter ensuite dans notre appli de test d'envoi
        // normalement, on l'aurait envoyé à notre serveur de notification, avec l'identifiant unique du téléphone
        Debug.WriteLine(canal.ChannelUri.ToString());
    }
}

Si le canal existe déjà, alors on obtient son URL qui normalement devra être envoyée à notre serveur de notififcation. Ici, je vais simplement l’afficher dans la console de sortie pour éviter de devoir créer un serveur de notification. Je vais ainsi pouvoir récupérer l’URL et l’utiliser dans une application tierce qui enverra la requête au serveur de notification de Microsoft.
Pour l’instant, implémentez les événements ainsi :

private void canal_ShellToastNotificationReceived(object sender, NotificationEventArgs e)
{
    // optionnel, cet événement est levé quand l'appli est ouverte et qu'on recoit la notif
}

private void canal_ErrorOccurred(object sender, NotificationChannelErrorEventArgs e)
{
    Dispatcher.BeginInvoke(() => MessageBox.Show(string.Format("Une erreur est survenue {0}, {1} ({2}) {3}", e.ErrorType, e.Message, e.ErrorCode, e.ErrorAdditionalData)) );
}

private void canal_ChannelUriUpdated(object sender, NotificationChannelUriEventArgs e)
{
    // On affiche le canal dans la console de sortie pour pouvoir l'exploiter ensuite dans notre appli de test d'envoi
    // normalement, on l'aurait envoyé à notre serveur de notification, avec l'identifiant unique du téléphone
    Debug.WriteLine(e.ChannelUri.ToString());
}

Vous aurez besoin de :

using Microsoft.Phone.Notification;

Puis démarrez l’application en debug, l’URL s’affiche dans la fenêtre de sortie de Visual Studio comme dans la figure suivante.

Url du canal dans la fenêtre de sortie
Url du canal dans la fenêtre de sortie

Je l’ai un peu masquée ici, mais elle a la forme :

http://db3.notify.live.net/throttledthirdparty/01.00/AAHmJDXpe47LTI0ct6NNXXXXXXXXXXXXXXXXXXXXXXXXXXXXXg1QTg1QkZDMkUxREQ

Sauvegardez cette URL dans un coin, nous allons en avoir besoin. Nous pouvons arrêter l’application mais sans arrêter l’émulateur. Le canal est créé. Remarquez que si vous redémarrez l’application, nous récupérrons le canal déjà créé et obtenons à nouveau la même URL.

Si vous vous souvenez de ce dont nous avons parlé juste avant, c’est cette URL qui devra être utilisée pour envoyer un message au serveur de notification de Microsoft.
Par souci de simplicité, ici je vais utiliser directement l’URL pour envoyer ma requête en POST, mais vous aurez compris que le rôle de notre serveur est de stocker ces URL dans une liste et d’envoyer le message à toutes les URL que nous avons stockées, correspondant aux utilisateurs qui souhaitent recevoir nos notifications.

Nous devons donc envoyer désormais une requête en POST à cette url, pour cela nous allons créer une petite application console grâce à Visual Studio Express 2012 pour Windows Desktop, que vous pouvez télécharger gratuitement à cet emplacement (je vous fait grâce de l'installation qui ne devrait pas poser de problème).

Ici, vu que je me suis abonné aux notifications toast (grâce à canal.BindToShellToast()), il faut que j’envoie un message toast, par exemple :

<?xml version="1.0" encoding="utf-8"?>
<wp:Notification xmlns:wp="WPNotification">
   <wp:Toast>
      <wp:Text1>Texte 1 youpi</wp:Text1>
      <wp:Text2>Texte 2 joie</wp:Text2>
      <wp:Param>/MainPage.xaml?cle=parametre</wp:Param>
   </wp:Toast>
</wp:Notification>

Le principe est donc de faire une requête POST, avec les bons headers, contenant le message de type toast, et de le poster à l’url récupérée. Voici le code C# permettant de réaliser ceci dans une application console :

try
{
    // url où envoyer le message
    // normalement, il faudrait récupérer la liste des urls stockées sur le serveur de notification
    // et envoyer le message à toutes ces urls
    string urlOuEnvoyerMessage = "http://db3.notify.live.net/throttledthirdparty/01.00/AAHmJDXpe47LTI0ct6NNXXXXXXXXXXXXXXXXXXXXXXXXXXXXXg1QTg1QkZDMkUxREQ";

    HttpWebRequest requete = (HttpWebRequest)WebRequest.Create(urlOuEnvoyerMessage);
    requete.Method = "POST"; // envoi en POST
    string messageToastAEnvoyer = @"<?xml version=""1.0"" encoding=""utf-8""?>
        <wp:Notification xmlns:wp=""WPNotification"">
            <wp:Toast>
                <wp:Text1>Texte 1 youpi</wp:Text1>
                <wp:Text2>Texte 2 joie</wp:Text2>
                <wp:Param>/MainPage.xaml?cle=parametre</wp:Param>
            </wp:Toast>
        </wp:Notification>";

    byte[] message = Encoding.Default.GetBytes(messageToastAEnvoyer);
    requete.ContentLength = message.Length;
    requete.ContentType = "text/xml";
    requete.Headers.Add("X-WindowsPhone-Target", "toast"); // notification de type toast
    requete.Headers.Add("X-NotificationClass", "2"); // envoi immédiat

    using (Stream requestStream = requete.GetRequestStream())
    {
        requestStream.Write(message, 0, message.Length);
    }

    // envoi de la notification, et récupération du retour
    HttpWebResponse response = (HttpWebResponse)requete.GetResponse();
    string statutNotification = response.Headers["X-NotificationStatus"];
    string statutCanal = response.Headers["X-SubscriptionStatus"];
    string statutMateriel = response.Headers["X-DeviceConnectionStatus"];

    // affiche le résultat de la requête
    Console.WriteLine(statutNotification + " | " + statutMateriel + " | " + statutCanal);

    // gestion d'erreur ultra simplifiée :)
    if (string.Compare(statutNotification, "Dropped", StringComparison.CurrentCultureIgnoreCase) == 0)
    {
        // il faut arrêter de tenter d'envoyer des messages à ce téléphone
    }
}
catch (Exception ex)
{
    Console.WriteLine("Erreur d'envoi : " + ex);
}

Et nous verrons la notification Toast s'afficher sur notre Windows Phone (voir figure suivante).

La notification Toast s'affiche dans l'émulateur
La notification Toast s'affiche dans l'émulateur

Et ce qui est intéressant, c’est que si l’on clique sur la notification toast, alors notre application se lance et navigue sur la page passée en paramètre. Ceci nous permet également de récupérer les paramètres de la query string (voir code et figure qui suivent).

protected override void OnNavigatedTo(NavigationEventArgs e)
{
    string valeur;
    if (NavigationContext.QueryString.TryGetValue("cle", out valeur))
    {
        MessageBox.Show(valeur);
    }
    base.OnNavigatedTo(e);
}

Pour avoir :

Utilisation de la query string
Utilisation de la query string

À noter que si l’application est ouverte, alors le message toast ne s’affiche pas en haut de l’écran. L’application peut cependant être notifiée de la réception d’un message toast en s’abonnant à l’événement ShellToastNotificationReceived et ainsi faire ce qu’elle désire, par exemple afficher le message :

private void canal_ShellToastNotificationReceived(object sender, NotificationEventArgs e)
{
    // optionnel, cet événement est levé quand l'appli est ouverte et qu'on recoit la notif
    string message = e.Collection["wp:Text1"] + e.Collection["wp:Text2"];
    Dispatcher.BeginInvoke(() => MessageBox.Show(message));
}

Ici, nous utilisons simplement la boîte de message MessageBox.Show pour afficher le message de la notification reçue. Vous pouvez en faire ce que vous voulez, l'afficher dans un TextBlock, ou juste traiter le message.

Pour les autres types de notifications, le principe est le même. Veuillez toujours à faire attention au type de notifications que vous envoyez dans les en-têtes HTTP, ainsi qu’au délai d’envoi. De même, pour qu’un téléphone puisse recevoir les notifications d’un certain type, pensez à déclarer le canal comme tel. Par exemple, nous avons vu que pour recevoir des notifications toasts, nous utilisions :

canal.BindToShellToast();

Pour les notifications tiles, il faudra utiliser :

canal.BindToShellTile();

Pour les notifications raw, il n’y a rien de spécial à faire sur le canal. Il faudra par contre s’abonner à l’événement HttpNotificationReceived :

[…]
canal.HttpNotificationReceived += canal_HttpNotificationReceived;
[…]
private void canal_HttpNotificationReceived(object sender, HttpNotificationEventArgs e)
{
    using (System.IO.StreamReader reader = new System.IO.StreamReader(e.Notification.Body))
    {
        string message = reader.ReadToEnd();
        Dispatcher.BeginInvoke(() => MessageBox.Show("Notification raw reçue : " + message));
    }
}
  • Les notifications permettent d’envoyer un message ou une demande de mise à jour de tuile.

  • La notification de type toast peut-être reçue même si l’application n’est pas démarrée.

  • Le développeur aura besoin de créer un serveur de notification, accessible à tout moment, afin de maintenir une liste de canaux de communication avec les téléphones intéressés pour recevoir des notifications.

Exemple de certificat de réussite
Exemple de certificat de réussite