Voller Aktivität, Teil 3: Pushbenachrichtigungen und Windows Azure Mobile Services

In Teil 1 dieser Reihe haben wir erläutert, was ein „lebendiges und dynamisches System“ für den Benutzer bedeutet und was Apps dafür leisten können. In Teil 2 haben wir uns angesehen, wie sich Webdienste schreiben und debuggen lassen, um regelmäßige Updates für Live-Kacheln zu unterstützen. In Teil 3 hier geht es nun zum Abschluss darum, wie Sie Updates, Popups und unformatierte Benachrichtigungen für bestimmte Clientgeräte über den Windows-Pushbenachrichtigungsdienst (WNS) bedarfsweise bereitstellen können und wie Windows Azure Mobile Services den gesamten Prozess vereinfacht.

Pushbenachrichtigungen

Regelmäßige Updates werden, wie wir in Teil 2 gesehen haben, clientseitig vorgenommen und stellen eine Abruf-oder „Pull“-Methode der Aktualisierung von Kacheln oder Signalen dar. Bei „Push“-Benachrichtigungen sendet ein Dienst ein Update direkt an ein Gerät, auf dem dieses Update spezifisch für einen Benutzer, eine App und sogar eine sekundäre Kachel sein kann.

Pushbenachrichtigungen können im Gegensatz zu Abrufen jederzeit und viel häufiger gesendet werden. Denken Sie aber daran, dass Windows die Menge an Benachrichtigungsverkehr auf einem Gerät drosselt, wenn sich dieses im verbundenen Standbymodus befindet oder wenn der Benachrichtigungsverkehr zu stark zunimmt. Das heißt, es gibt keine Garantie, dass alle Benachrichtigungen übermittelt werden (insbesondere wenn das Gerät ausgeschaltet ist).

Gehen Sie deshalb nicht davon aus, dass Sie mithilfe einer Pushbenachrichtigung eine Uhr-Kachel oder andere Kachel-Gadgets mit einer ähnlichen Häufigkeit oder Zeitauflösung implementieren können Überlegen Sie sich stattdessen vielmehr, wie Sie mithilfe von Pushbenachrichtigungen Kacheln und Benachrichtigungen mit einem Backend-Dienst verbinden können, der dem Benutzer so interessante und sinnvolle Informationen bietet, dass er Ihre App häufiger nutzen will.

Bevor wir hier ins Detail gehen, sollte noch einmal erwähnt werden, dass es zwei verschiedene Pushbenachrichtigungen gibt:

  1. XML-Updates, die Kachel- bzw. Signalupdates enthalten, oder Popupbenachrichtigungsnutzlasten: Windows kann solche Pushbenachrichtigungen verarbeiten und das Update oder das Popup im Namen einer App ausgeben. Eine App kann diese Benachrichtigungen, falls gewünscht, auch direkt verarbeiten.
  2. Binäre oder unformatierte Benachrichtigungen, die all die Daten enthalten, die der Dienst senden möchte: diese müssen durch App-spezifischen Code verarbeitet werden, weil Windows nicht weiß, was es ansonsten mit den Daten machen soll. Weitere Informationen, z. B. zu Größenbeschränkungen (5 KB) und Codierung (base64), finden Sie unter Richtlinien und Prüfliste für unformatierte Benachrichtigungen.

In beiden Fällen kann eine aktive (im Vordergrund ausgeführte) App Pushbenachrichtigungen direkt über die PushNotificationChannel-Klasse und ihr PushNotificationReceived-Ereignis verarbeiten. Bei XML-Nutzlasten kann die App die Inhalte modifizieren, Tags ändern und so weiter, bevor sie die Benachrichtigungen lokal ausgibt (oder ignoriert). Bei unformatierten Benachrichtigungen verarbeitet die App die Inhalte und entscheidet dann, welche (und ob) Benachrichtigungen ausgegeben werden.

Wenn die App angehalten wurde oder nicht aktiv ist, kann sie auch eine Hintergrundaufgabe für eben diesen Zweck bereitstellen. Die App muss Zugriff auf den Sperrbildschirm anfordern und er muss ihr erteilt werden. Dadurch kann solch App-spezifischer Code beim Empfang einer Benachrichtigung ausgeführt werden.

Eine Hintergrundaufgabe macht in der Regel ein oder zwei Dinge, wenn die Benachrichtigung eingeht. Zuerst speichert sie eventuell einige wichtige Informationen aus der Benachrichtigung in lokale App-Daten, aus denen die App sie abrufen kann, wenn sie das nächste Mal aktiviert wird oder fortgesetzt wird. Zweitens kann die Hintergrundaufgabe lokale Kachel- und Signalupdates und/oder Popupbenachrichtigungen ausgeben.

Um unformatierte Benachrichtigungen besser zu verstehen, sehen wir uns eine typische E-Mail-App an. Wenn ihr Backend-Dienst neue Nachrichten für einen Benutzer entdeckt, sendet er eine unformatierte Pushbenachrichtigung an WNS, die eine Reihe von E-Mail-Nachrichtenheader enthält. Dazu verwendet der Dienst einen Kanal-URI, der mit der spezifischen App auf dem spezifischen Gerät dieses Benutzers verbunden ist.

WNS versucht dann, diese Benachrichtigung an den Client zu „pushen“. Wenn dies klappt, empfängt Windows diese Benachrichtigung und sucht nach der App, die dem fraglichen Kanal-URI zugeordnet ist. Wenn keine passende App gefunden werden kann, wird die Benachrichtigung ignoriert. Wenn eine vorhandene App aktiv ist, löst Windows das PushNotificationReceived-Ereignis aus. Andernfalls sucht Windows nach einer verfügbaren Hintergrundaufgabe für diese App und ruft sie auf.

In beiden Fällen landet die unformatierte Benachrichtigung bei irgendeinem App-Code, der dann die Daten verarbeitet, ein Signalupdate an die App-Kachel ausgibt, um die Anzahl der neuen Nachrichten anzugeben, und bis zu fünf wechselnde Kachelupdates mit Nachrichtenheadern ausgibt. Die App kann außerdem auch Popupbenachrichtigungen für jede neue eingehende Nachricht oder wenigstens eine einzelne Nachricht mit dem Hinweis auf vorliegende neue Nachrichten ausgeben.

Als Ergebnis teilen Popups dem Benutzer mit, dass neue E-Mail-Nachrichten eingegangen sind. Die Kachel der App auf dem Startbildschirm bietet hier eine schnelle und direkte Ansicht der neuen Mailaktivitäten.

Weitere Informationen zu diesen clientseitigen Ereignishandlern und Hintergrundaufgaben finden Sie im Beispiel für unformatierte Benachrichtigungen, im Beitrag Produktivität im Hintergrund – Hintergrundaufgaben in diesem Blog und im Whitepaper zu Hintergrundnetzwerken. Wenden wir uns nun in unserem Fall der Dienstseite der Angelegenheit zu.

Arbeiten mit dem Windows-Pushbenachrichtigungsdienst (WNS)

Aufgrund der Zusammenarbeit von Windows, Apps, Diensten und WNS ist es möglich, benutzerspezifische Daten für eine spezifische App-Kachel (oder ein Popup oder einen Handler für unformatierte Benachrichtigungen) auf einem spezifischen Gerät für einen spezifischen Benutzer bereitzustellen. Die Beziehungen zwischen all diesen Komponenten sehen Sie in dieser Darstellung:

 

Flussdiagramm, in dem das Zusammenarbeiten von Windows, Apps, Diensten und WNS zur Bereitstellung von Daten für eine spezifische App-Kachel dargestellt ist

 

Natürlich ist einiges an Verdrahtungsarbeit notwendig, damit das alles harmonisch funktioniert:

  1. Sie (der Entwickler) registrieren die App im Windows Store zur Verwendung von Pushbenachrichtigungen. Dadurch werden eine SID und ein geheimer Clientschlüssel bereitgestellt, mit denen sich der Dienst bei WNS authentifiziert (diese Informationen sollten aus Gründen der Sicherheit in keinem Fall auf dem Clientgerät gespeichert werden).
  2. Zur Laufzeit fordert die App für jede ihrer Live-Kacheln (primär und sekundär) einen WNS-Kanal-URI von Windows an, oder sie fordert einen einzigen URI für unformatierte Benachrichtigungen an. Eine App muss diese Kanal-URIs außerdem alle 30 Tage aktualisieren. Dazu können Sie eine andere Hintergrundaufgabe verwenden.
  3. Der Dienst der App stellt einen URI bereit, über den die App diese Kanal-URIs zusammen mit allen Daten, die deren Verwendung beschreiben (z. B. der Standort für aktuelle Wetterdaten oder ein spezifisches Benutzerkonto bzw. eine spezifisch Benutzeraktivität), hochladen kann. Bei Erhalt speichert der Dienst diese Kanal-URIs und die zugehörigen Daten für die spätere Verwendung.
  4. Der Dienst überwacht sein Backend auf Änderungen, die für die einzelnen Benutzer-/Geräte-/App-/Kachelkombinationen gelten. Wenn der Dienst eine Bedingung erkennt, die eine Benachrichtigung für einen bestimmten Kanal auslöst, erstellt er den Inhalt dieser Benachrichtigung (XML oder unformatiert), authentifiziert sich bei WNS mithilfe der SID und des geheimen Clientschlüssels und sendet dann die Benachrichtigung zusammen mit dem Kanal-URI an WNS.

Sehen wir uns die einzelnen Schritte genauer an. (Und wie im Falle einer Vorschau, falls Sie sich beim Umgang mit HTTP-Anforderungen etwas unsicher fühlen, nimmt Ihnen Windows Azure Mobile Services auch hier viel Kleinarbeit ab. Doch dazu später mehr.)

App-Registrierung beim Windows Store

Informationen zum Erhalt der SID und des geheimen Clientschlüssels finden Sie im Windows Developer Center unter How to authenticate with the Windows Push Notification Service (WNS). Anhand der SID wird Ihre App bei WNS identifiziert. Mir dem geheimen Clientschlüssel teilt Ihr Dienst WNS mit, dass das Senden von Benachrichtigungen für Ihre App zulässig ist. Noch einmal, beide sollten nur im Dienst gespeichert sein.

Beachten Sie, dass Schritt 4 unter How to authenticate with the Windows Push Notification Service (WNS), das Senden der Anmeldeinformationen des Cloudservers an WNS, eine Aktion ist, die Sie nur ausführen, wenn Ihr Dienst eine Pushbenachrichtigung sendet. Wir kommen darauf in Kürze zurück, da Ihrem Dienst in diesem Stadium noch das Kernstück fehlt, das er zum Senden einer Benachrichtigung benötigt, ein Kanal-URI.

Abrufen und Aktualisieren von Kanal-URIs

Die Client-App ruft Kanal-URIs zur Laufzeit über das Windows.Networking.PushNotifications.PushNotificationChannelManager-Objekt ab. Diese Objekt verfügt nur über zwei Methoden:

  • createPushNotificationChannelForApplicationAsync: erstellt einen Kanal-URI für die primäre Kachel der App sowie Popups und unformatierte Benachrichtigungen.
  • createPushNotificationChannelForSecondaryTileAsync: erstellt einen Kanal-URI für eine spezifische sekundäre Kachel, die durch ein tileId-Argument identifiziert wird.

Das Ergebnis der beiden asynchronen Vorgänge ist ein PushNotificationChannel-Objekt. Dieses Objekt enthält einen Kanal-URI in seiner Uri -Eigenschaft zusammen mit einer ExpirationTime, um die Frist für das Aktualisieren dieses Kanals anzugeben Eine Close-Methode beendet ganz spezifisch den Kanal, sofern erforderlich. Noch wichtiger ist das PushNotificationReceived-Ereignis. Dies ist das Ereignis, das ausgelöst wird, wenn die App im Vordergrund ausgeführt und eine Pushbenachrichtigung über diesen Kanal empfangen wird.

Die Gültigkeitsdauer eines Kanal-URI beträgt 30 Tage. Danach lehnt WNS alle Anforderungen für diesen Kanal ab. Deshalb muss App-Code diese URIs mithilfe der create-Methoden oben mindestens alle 30 Tage aktualisieren und diese URIs an den Dienst der App senden. Hier ist eine a gute Strategie:

  • Fordern Sie beim ersten Starten einen Kanal-URI an und speichern Sie die Zeichenfolge in der Uri-Eigenschaft in Ihren lokalen App-Daten. Da Kanal-URIs spezifisch für ein Gerät sind, dürfen Sie diese nicht in Ihren App-Roamingdaten speichern.
  • Fordern Sie bei nachfolgenden Startvorgängen erneut einen Kanal-URI an und vergleichen Sie diesen mit dem zuvor gespeicherten. Wenn er sich unterscheidet, senden Sie ihn an den Dienst und lassen Sie den Dienst bei Bedarf einen älteren URI ersetzen.
  • Führen Sie außerdem die vorherigen Schritte im Resuming-Handler Ihrer App durch (siehe Starten, Fortsetzen und Multitasking in den Dokumenten), da es möglich ist, dass die App möglicherweise mehr als 30 Tage lang angehalten war.
  • Wenn Sie denken, dass die App nicht innerhalb von 30 Tagen ausgeführt wird, implementieren Sie eine Hintergrundaufgabe mit einem Wartungsauslöser, aufgrund dessen die App dann alle paar Tage oder einmal die Woche ausgeführt wird. Informationen hierzu finden Sie ebenfalls unter Produktivität im Hintergrund – Hintergrundaufgaben; die Hintergrundaufgabe in diesem Fall führt genau denselben Code wie die App aus, um einen Kanal anzufordern und ihn an den Dienst zu senden.

Senden von Kanal-URIs an den Dienst

In der Regel arbeiten die Pushbenachrichtigungskanäle mit benutzerspezifischen Updates wie E-Mail-Status, Sofortnachrichten und anderen personalisierten Informationen. Es ist unwahrscheinlich, dass Ihr Dienst die gleiche Benachrichtigung an jeden Benutzer und/oder jede Kachel übertragen muss. Aus diesem Grund muss der Dienst den einzelnen Kanal-URIs spezifischere Informationen zuordnen. Bei einer E-Mail-App ist die ID des Benutzers von überragender Bedeutung, da darüber das zu überprüfende Konto angegeben wird. Bei einer Wetter-App dagegen würde wahrscheinlich jeder Kanal-URI einem bestimmten Breiten- und Längengrad zugeordnet werden, sodass jede Kachel (primär und sekundär) einen bestimmten Ort darstellen würde.

Die App muss dann diese Details einschließen, wenn sie einen Kanal-URI an ihren Dienst sendet, und der Dienst muss sie für die spätere Verwendung speichern.

In Szenarien, in denen die Benutzeridentität vertraulich sein muss, sollte die App den Benutzer über dienstspezifische Anmeldeinformationen oder über einen OAuth-Anbieter wie Facebook, Twitter, Google oder das Microsoft-Konto des Benutzers (die Verwendung von OAuth ist hilfreich bei Windows Azure Mobile Services, wie wir später sehen werden) separat beim Dienst authentifizieren. Wenn das aus irgendeinem Grund nicht möglich ist, sollten Sie unbedingt jede Benutzer-ID, die Sie an den Dienst senden, verschlüsseln oder sicherstellen, dass Sie sie über HTTPS senden.

In allen Fällen bleibt aber die Art und Weise, wie Sie all diese Informationen an den Dienst senden (in Headern, über die Daten im Nachrichtentext oder als Parameter für den Dienst-URI), Ihnen überlassen. Dieser Teil der Kommunikation wird ausschließlich zwischen App und deren Dienst geregelt.

Nehmen wir als einfaches Beispiel einen Dienst mit einer Seite namens receiveuri.aspx (wie wir im nächsten Abschnitt sehen), bei der die vollständige Adresse in einer Variable namens url angegeben ist. Der folgende Code fordert einen primären Kanal-URI von Windows für die App an und veröffentlicht diesen über HTTP auf der Seite. (Dieser Code ist aus dem Beispiel für clientseitige Push- und regelmäßige Benachrichtigungen abgeleitet und vereinfacht, wobei die (an anderer Stelle definierte) itemId-Variable zum Identifizieren der sekundären Kacheln verwendet wird; das Beispiel besitzt außerdem auch eine C++ Variante, die hier nicht dargestellt wird):

JavaScript:

 

 Windows.Networking.PushNotifications.PushNotificationChannelManager
    .createPushNotificationChannelForApplicationAsync()
    .done(function (channel) {
        //Typically save the channel URI to appdata here.
        WinJS.xhr({ type: "POST", url:url,
            headers: { "Content-Type": "application/x-www-form-urlencoded" },
            data: "channelUri=" + encodeURIComponent(channel.uri) 
                + "&itemId=" + encodeURIComponent(itemId)
        }).done(function (request) {
            //Typically update the channel URI in app data here.
        }, function (e) {
            //Error handler
        });
    });

           

C#:

 

 using Windows.Networking.PushNotifications;

PushNotificationChannel channel = await PushNotificationChannelManager.CreatePushNotificationChannelForApplicationAsync();
HttpWebRequest webRequest = (HttpWebRequest)HttpWebRequest.Create(url);
webRequest.Method = "POST";
webRequest.ContentType = "application/x-www-form-urlencoded";
byte[] channelUriInBytes = Encoding.UTF8.GetBytes("ChannelUri=" + WebUtility.UrlEncode(newChannel.Uri) + "&ItemId=" + WebUtility.UrlEncode(itemId));

Task<Stream> requestTask = webRequest.GetRequestStreamAsync();
using (Stream requestStream = requestTask.Result)
{
    requestStream.Write(channelUriInBytes, 0, channelUriInBytes.Length);
}

Der folgende ASP.NET-Code ist eine grundlegende Implementierung einer receiveuri.aspx-Seite, die dieses HTTP POST verarbeitet und dabei sicherstellt, dass sie einen gültigen Kanal-URI, einen Benutzer und irgendeinen Bezeichner für das Element empfangen hat.

Ich betone hier den „grundlegenden“ Charakter dieses Codes, weil, wie Sie sehen, die SaveChannel-Funktion einfach die Inhalte der Anforderung in eine feste Textdatei schreibt, die eindeutig nicht über einen einzelnen Benutzer hinaus skaliert werden kann! Ein richtiger Dienst würde natürlich eine Datenbank zu diesem Zweck heranziehen, aber die Struktur hier ist ähnlich.

 <%@ Page Language="C#" AutoEventWireup="true" %>

<script runat="server">

protected void Page_Load(object sender, EventArgs e)
{
    //Output page header
    Response.Write("<!DOCTYPE html>\n<head>\n<title>Register Channel URI</title>\n</head>\n<html>\n<body>");
    
    //If called with HTTP GET (as from a browser), just show a message.
    if (Request.HttpMethod == "GET")
    {
        Response.StatusCode = 400;
        Response.Write("<p>This page is set up to receive channel URIs from a push notification client app.</p>");
        Response.Write("</body></html>");
        return;
    }

    if (Request.HttpMethod != "POST") {
        Response.StatusCode = 400;
        Response.Status = "400 This page only accepts POSTs.";
        Response.Write("<p>This page only accepts POSTs.</p>");
        Response.Write("</body></html>");        
        return;
    }
    
    //Otherwise assume a POST and check for parameters    
    try
    {
        //channelUri and itemId are the values posted from the Push and Periodic Notifications Sample in the Windows 8 SDK
        if (Request.Params["channelUri"] != null && Request.Params["itemId"] != null)
        {
            // Obtain the values, along with the user string
            string uri = Request.Params["channelUri"];
            string itemId = Request.Params["itemId"];
            string user = Request.Params["LOGON_USER"];
                 
            //TODO: validate the parameters and return 400 if not.
            
            //Output in response
            Response.Write("<p>Saved channel data:</p><p>channelUri = " + uri + "<br/>" + "itemId = " + itemId + "user = " + user + "</p>");

            //The service should save the URI and itemId here, along with any other unique data from the app such as the user;
            SaveChannel(uri, itemId, user);

            Response.Write("</body></html>");
        }
    }
    catch (Exception ex)
    {
        Trace.Write(ex.Message);
        Response.StatusCode = 500;
        Response.StatusDescription = ex.Message; 
        Response.End();
    }
}
</script>

protected void SaveChannel(String uri, String itemId, String user)
{
    //Typically this would be saved to a database of some kind; to keep this demonstration very simple, we'll just use
    //the complete hack of writing the data to a file, paying no heed to overwriting previous data.
    
    //If running in the debugger on localhost, this will save to the project folder
    string saveLocation = Server.MapPath(".") + "\\" + "channeldata_aspx.txt";
    string data = uri + "~" + itemId + "~" + user;

    System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();
    byte[] dataBytes = encoding.GetBytes(data);

    using (System.IO.FileStream fs = new System.IO.FileStream(saveLocation, System.IO.FileMode.Create))
    {
        fs.Write(dataBytes, 0, data.Length);
    }

    return;
}

Den Code für diesen Dienst finden Sie in Kapitel 13 meines kostenlosen eBooks, Programming Windows 8 Apps in HTML, CSS, and JavaScript , insbesondere im HelloTiles-Beispiel des begleitenden Inhalts. Er ist so entworfen, dass er mit dem clientseitigen SDK-Beispiel von oben funktioniert. Wenn Sie HelloTiles im Debugger (Visual Studio 2012 Ultimate oder Visual Studio Express 2012 für das Web) mit aktiviertem Localhost ausführen, bekommen Sie eine URL wie https://localhost:52568/HelloTiles/receiveuri.aspx, die Sie in das clientseitige SDK-Beispiel einfügen können. Wenn das Beispiel dann diese URL anfordert, wird bei jedem Breakpoint im Dienst gestoppt und Sie können schrittweise durch den Code gehen.

Senden der Benachrichtigung

In einem richtigen Dienst werden dessen Datenquellen durch irgendeine Form von fortlaufendem Prozess überwacht und ggf. Pushbenachrichtigungen an spezifische Benutzer gesendet. Dies kann auf verschiedene Art und Weise geschehen:

  • Mit einem geplanten Auftrag kann auf Wetterwarnungen für einen bestimmten Ort in einem bestimmten Intervall, z B. alle 15 bis 30 Minuten überprüft werden, je nachdem wie oft diese Meldungen ausgegeben werden, und als Reaktion darauf Pushbenachrichtigungen ausgeben.
  • Ein anderer Dienst, z. B. ein Nachrichten-Backend, fordert möglicherweise eine Seite auf Ihrem Server an, wenn eine neue Nachricht verfügbar ist. Diese Seite kann dann die passende Benachrichtigung ausgeben.
  • Benutzer können mit Webseiten auf Ihrem Server interagieren und deren Aktivitäten lösen Pushbenachrichtigungen an spezifische Kanäle aus.

Kurz gesagt, es gibt eine Reihe von Auslösern für Pushbenachrichtigungen, je nach der Beschaffenheit Ihres Backend-Diensts oder der Website. Gehen wir für diesen Artikel davon aus, dass derselbe HelloTiles-Beispieldienst aus Kapitel 13 von Programming Windows 8 Apps in HTML, CSS, and JavaScript eine Seite namens sendBadgeToWNS.aspx aufgerufen hat, die bei jedem Ihrer Besuche der Seite in einem Browser mithilfe des jeweils zuvor in der Textdatei gespeicherten Kanal-URI eine Pushbenachrichtigung sendet. Ein richtiger Dienst führt eine Form von Datenbanksuche aus, um Kanal-URIs abzurufen, und würde nicht die Inhalte einer Datei lesen. Aber auch hier gilt, dass die allgemeine Struktur sehr ähnlich ist.

ASP.NET-Seite:

 <%@ Page Language="C#" AutoEventWireup="true" CodeFile="sendBadgeToWNS.aspx.cs" Inherits="sendBadgeToWNS" %>

<!DOCTYPE html>

<html xmlns="https://www.w3.org/1999/xhtml">
<head runat="server">    
    <title>Send WNS Update</title>
</head>
<body>
    <p>Sending badge update to WNS</p>    
</body>
</html>

 

C#-Hintergrundcode:

 using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Net;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;
using System.Text;

public partial class sendBadgeToWNS : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        //Load our data that was previously saved. A real service would do a database lookup here
        //with user- or tile-specific criteria.
        string loadLocation = Server.MapPath(".") + "\\" + "channeldata_aspx.txt
        byte[] dataBytes;
        
        using (System.IO.FileStream fs = new System.IO.FileStream(loadLocation, System.IO.FileMode.Open))
        {
            dataBytes = new byte[fs.Length];
            fs.Read(dataBytes, 0, dataBytes.Length);
        }

        if (dataBytes.Length == 0)
        {
            return;
        }
        
        System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();

        string data = encoding.GetString(dataBytes);
        string[] values = data.Split(new Char[] { '~' });
        string uri = values[0]; //Channel URI
        string secret = "9ttsZT0JgHAFveYahK1B6jQbvMOIWYbm";
        string sid = "ms-app://s-1-15-2-2676450768-845737348-110814325-22306146-1119600341-293560589-2707026538";
        
        //Create some simple XML for a badge update
        string xml = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>";
        xml += "<badge value='alert'/>";
                    
        PostToWns(secret, sid, uri, xml, "wns/badge");
    }
}

 

Alles was wir hier tun, ist den Kanal-URI abzurufen, die XML-Nutzlast zu erstellen und uns dann bei WNS zu authentifizieren und ein HTTP POST an diesen Kanal-URI vorzunehmen. Die letzten zwei Schritte erfolgen in der PostToWns-Funktion aus dem Thema Schnellstart: Senden einer Pushbenachrichtigung im Windows Developer Center. Ich gebe hier keine vollständige Auflistung, weil der Großteil davon nur das Authentifizieren bei WNS über OAuth (unter „https://login.live.com/accesstoken.srf“) mithilfe der SID und des geheimen Clientschlüssels aus dem Windows Store betrifft. Das Ergebnis dieser Authentifizierung ist ein Zugriffstoken, das dann wiederum im HTTP POST enthalten ist, das an den Kanal-URI gesendet wird:

C#:

 public string PostToWns(string secret, string sid, string uri, string xml, string type = "wns/badge")
{
    try
    {
        // You should cache this access token
        var accessToken = GetAccessToken(secret, sid);

        byte[] contentInBytes = Encoding.UTF8.GetBytes(xml);

        // uri is the channel URI
        HttpWebRequest request = HttpWebRequest.Create(uri) as HttpWebRequest;
        request.Method = "POST";
        request.Headers.Add("X-WNS-Type", type);
        request.Headers.Add("Authorization", String.Format("Bearer {0}", accessToken.AccessToken));

        using (Stream requestStream = request.GetRequestStream())
            requestStream.Write(contentInBytes, 0, contentInBytes.Length);

        using (HttpWebResponse webResponse = (HttpWebResponse)request.GetResponse())
            return webResponse.StatusCode.ToString();
    }
    catch (WebException webException)
    {
        // Implements a maximum retry policy (omitted)
    }
}

Beachten Sie in diesem Beispiel, dass der X-WNS-Type-Header in der HTTP-Anforderung auf wns/badge und der Content-Type-Header standardmäßig auf text/xml festgelegt wird. Bei Kacheln sollte der Typ wns/tile sein; bei Popups wird wns/toast verwendet. Verwenden Sie bei unformatierten Benachrichtigungen den Typ wns/raw und legen Sie Content-Type auf application/octet-stream fest. Weitere Informationen zu Headern finden Sie in der Dokumentation auf der Seite Anforderungs- und Antwortheader des Pushbenachrichtigungsdiensts.

Pushbenachrichtigungsfehler

Natürlich muss das Senden einer HTTP-Anforderung wie dieser nicht immer klappen, und WNS kann aus einer Vielzahl an Gründen mit etwas anderem als einem 200-Code (erfolgreich) antworten. Weitere Informationen hierzu finden Sie im Abschnitt „Antwortcode“ der Seite Anforderungs- und Antwortheader des Pushbenachrichtigungsdiensts; hier sind die häufigsten Fehler und Ursachen:

  • Der Kanal-URI ist nicht gültig (404 Nicht gefunden) oder abgelaufen (410 Fehlend). In diesen Fällen sollte der Dienst den Kanal-URI aus seiner Datenbank entfernen und keine weiteren Anforderungen an diesen stellen.
  • Die SID und der geheime Clientschlüssel sind möglicherweise nicht gültig (401 Nicht autorisiert) oder die Paket-ID der App in ihrem Manifest und die im Windows Store stimmen nicht überein (403 Verboten). Mithilfe des Menübefehls Store > App mit Store verknüpfen in Visual Studio (diesen Befehl finden Sie im Menü Projekt in Visual Studio 2012 Ultimate) lässt sich am besten sicherstellen, dass sie übereinstimmen.
  • Die Nutzlast der unformatierten Benachrichtigung beträgt über 5 KB (413 Anfrageeinheit zu groß).
  • Der Client ist vielleicht offline. In diesem Fall unternimmt WNS automatisch einen neuen Versuch, meldet dann aber schließlich einen Fehler. Bei XML-Benachrichtigungen werden standardmäßig Pushbenachrichtigungen zwischengespeichert und dann übermittelt, wenn der Client wieder online ist. Bei unformatierten Benachrichtigungen ist die Zwischenspeicherung standardmäßig deaktiviert. Dies können Sie ändern, indem Sie den X-WNS-Cache-BPolicy-Header in der Anforderung an den Kanal-URI auf cache festlegen.

Stellen Sie bei anderen Fehlern (400 Ungültige Anforderung) sicher, dass XML-Nutzlasten UTF-8-codierten Text enthalten und dass unformatierte Benachrichtigungen base64-codiert sind und der Content-Type-Header dabei auf application/octet-stream festgelegt ist. Es ist auch möglich, dass WNS die Übermittlung drosselt, weil Sie innerhalb eines bestimmten Zeitraums einfach zu viele Pushbenachrichtigungen senden wollen.

Außerdem kann eine unformatierte Pushbenachrichtigung auch abgelehnt werden, wenn die App nicht auf dem Sperrbildschirm vorhanden ist und das Gerät sich im verbundenen Standbymodus befindet. Da Windows unformatierte Benachrichtigungen für Apps mit Nicht-Sperrbildschirmen in diesem Zustand (und immer dann, wenn die App nicht im Vordergrund ausgeführt wird) blockiert, besitzt WNS Optimierungen, durch die Benachrichtigungen, die sicher nicht übermittelt werden, nicht gesendet werden.

Windows Azure Mobile Services

Da Sie nun die komplizierten Details (dabei wurde sogar die Speicherfrage noch außer Acht gelassen) der Arbeit mit Pushbenachrichtigungen kennen, fragen Sie sich bestimmt, ob sich das alles nicht irgendwie einfacher gestalten ließe. Stellen Sie sich doch einmal vor, was notwendig wäre, um potenziell Tausende oder Millionen von Kanal-URIs für ein hoffentlich große und wachsende Kundenbasis zu verwalten!

Glücklicherweise sind Sie nicht der erste, der sich solche Fragen stellt. Neben den Lösungen von Drittanbietern wie Urban Airship kann auch Windows Azure Mobile Services Ihr Leben ein ganzes Stück einfacher machen.

Windows Azure Mobile Services, für diesen Artikel hier kurz AMS genannt, bietet eine vorkonfigurierte Lösung (im Grunde eine Reihe von REST-Endpunkten) für die meisten der Dienstaspekte, über die wir bislang geredet haben. Ein „mobiler Dienst“ ist im Grunde ein Dienst, der eine Datenbank in Ihrem Auftrag verwaltet und Bibliotheksfunktionen zum einfachen Senden von Nutzlasten an WNS bietet. Eine Einführung zu AMS finden Sie unter Einbinden Ihrer App in die Cloud mit Windows Azure Mobile Services.

Rufen Sie bei Pushbenachrichtigungen im Speziellen zuerst die clientseitige Bibliothek im Windows Azure Mobile Services SDK für Windows 8 ab. Lesen Sie dann die Ersten Schritte bei Pushbenachrichtigungen in Mobile Services (es steht auch eine JavaScript-Version des Themas zur Verfügung!), in denen beschrieben wird, wie AMS Ihnen bei der Bewältigung der zuvor angesprochenen Verdrahtungsanforderungen helfen kann:

  • App-Registrierung beim Windows Store: Sobald Sie die SID und den geheimen Clientschlüssel für Ihre App aus dem Windows Store erhalten haben, müssen Sie diese Werte in der Konfiguration des mobilen Diensts speichern. Informationen hierzu finden Sie im Abschnitt zum Registrieren Ihrer App für den Windows Store des soeben erwähnten Erste Schritte-Themas.
  • Abrufen und Aktualisieren von Kanal-URIs: das Anfordern und Verwalten von Kanal-URIs in der App ist eine rein clientseitige Angelegenheit und erfolgt genau wie bereits beschrieben.
  • Senden von Kanal-URIs an den Dienst: dieser Schritt wird durch AMS viel einfacher. Zuerst erstellen Sie eine Datenbanktabelle im mobilen Dienst (über das Windows Azure-Portal) Danach kann die App problemlos Datensätze mit Kanal-URIs und anderen Schlüsselinformationen, die angefügt werden müssen, in diese Tabelle einfügen. Die AMS-Clientbibliothek kümmert sich im Hintergrund um die HTTP-Anforderung und aktualisiert sogar den clientseitigen Datensatz mit den auf dem Server vorgenommenen Änderungen. Darüber hinaus kann AMS die Authentifizierung automatisch über das Microsoft-Konto des Benutzers oder über drei andere OAuth-Anbieter (Facebook, Twitter oder Google, sofern Sie die App für einen davon registriert haben) verwenden. Informationen hierzu finden Sie unterGet started with authentication in Mobile Services.
  • Senden der Benachrichtigung: innerhalb des mobilen Diensts können Sie (in der Variante von JavaScript namens Node.js geschriebene) Skripts an Datenbankvorgänge anfügen sowie geplante Aufträge in JavaScript erstellen. In diesen Skripts erstellt ein einfacher Aufruf des push.wns-Objekts mit einem Kanal-URI und einer Nutzlast die erforderliche HTTP-Anforderung an den Kanal. Auch das Erfassen von Pushfehlern und das Aufzeichnen der Antwort mit console.log ist eine einfache Angelegenheit. Die entsprechenden Protokolle lassen sich schnell und einfach im Windows Azure-Portal einsehen.

Ausführliche Informationen dazu finden Sie in diesen zwei Beispiellernprogrammen: Tile, Toast, and Badge Push Notifications using Windows Azure Mobile Services und Raw Notifications using Windows Azure Mobile Services. Statt all diese Anweisungen nochmals zu wiederholen, lassen Sie uns nur einige der wichtigsten Punkte noch einmal durchgehen.

Wenn Sie einen mobilen Dienst einrichten, verfügt er über eine spezifische Dienst-URL. Diese verwenden Sie, wenn Sie eine Instanz des MobileServiceClient-Objekts im AMS SDK erstellen:

JavaScript:

 var mobileService = new Microsoft.WindowsAzure.MobileServices.MobileServiceClient(
    "https://{mobile-service-url}.azure-mobile.net/",
    "{mobile-service-key}");

C#:

 using Microsoft.WindowsAzure.MobileServices;

MobileServiceClient MobileService = new MobileServiceClient(
    "https://{mobile-service-url}.azure-mobile.net/",
    "{mobile-service-key}");

C++ (entnommen aus einem weiteren Beispiel):

 using namespace Microsoft::WindowsAzure::MobileServices;

auto MobileService = ref new MobileServiceClient(
    ref new Uri(L" https://{mobile-service-url}.azure-mobile.net/"), 
    ref new String(L"{mobile-service-key}"));

Diese Klasse kapselt alle HTTP-Kommunikationsvorgänge mit dem Dienst ein und nimmt Ihnen somit den ganzen handwerklichen Kleinkram ab, um die Sie sich am liebsten nicht kümmern würden.

Um sich bei einem bestimmten OAuth-Anbieter zu authentifizieren, verwenden Sie die login- oder LoginAsync-Methode, bei der als Ergebnis ein User-Objekt entsteht, das diese Informationen der App bereitstellt. (Nach der Authentifizierung enthält die CurrentUser-Eigenschaft des Clientobjekts auch die Benutzer-ID.) Wenn Sie den mobilen Dienst direkt auf diese Weise authentifizieren, hat der Dienst Zugriff auf die Benutzer-ID und es besteht keine Notwendigkeit für den Client, sie explizit zu senden:

JavaScript:

 mobileService.login("facebook").done(function (user) { /* ... */ });
mobileService.login("twitter").done(function (user) { /* ... */ });
mobileService.login("google").done(function (user) { /* ... */ });
mobileService.login("microsoftaccount").done(function (user) { /* ... */ });

C#:

 MobileServiceUser user = await MobileService.LoginAsync(MobileServiceAuthenticationProvider.Facebook);
MobileServiceUser user = await MobileService.LoginAsync(MobileServiceAuthenticationProvider.Twitter);
MobileServiceUser user = await MobileService.LoginAsync(MobileServiceAuthenticationProvider.Google);
MobileServiceUser user = await MobileService.LoginAsync(MobileServiceAuthenticationProvider.MicrosoftAccount);

C++:

 task<MobileServiceUser^> (MobileService->LoginAsync(MobileServiceAuthenticationProvider::Facebook))
    .then([this](MobileServiceUser^ user) { /* */ } );
task<MobileServiceUser^> (MobileService->LoginAsync(MobileServiceAuthenticationProvider::Twitter))
    .then([this](MobileServiceUser^ user) { /* */ } );
task<MobileServiceUser^> (MobileService->LoginAsync(MobileServiceAuthenticationProvider::Google))
    .then([this](MobileServiceUser^ user) { /* */ } );
task<MobileServiceUser^> (MobileService->LoginAsync(MobileServiceAuthenticationProvider::MicrosoftAccount))
    .then([this](MobileServiceUser^ user) { /* */ } );

Zum Senden eines Kanal-URI an den Dienst muss erneut einfach nur ein Datensatz in der Datenbank des Diensts gespeichert werden. Das Clientobjekt stellt dann die HTTP-Anforderungen. Fordern Sie dazu lediglich das Datenbankobjekt an und fügen den Datensatz wie in den Beispielen unten aus dem zuvor verlinkten Lernprogrammbeispiel für Pushbenachrichtigungen gezeigt ein. Gehen Sie in jedem Codeausschnitt davon aus, dass ch das PushNotificationChannel-Objekt aus den WinRT-APIs enthält. Sie können auch jede andere Eigenschaft im channel-Objekt, das erstellt wurde, einschließen, z. B. eine sekundäre Kachel-ID oder andere Daten, die den Zweck des Kanals identifizieren.

JavaScript:

 var channelTable = MobileServicesSample.mobileService.getTable('Channels');

var channel = {
    uri: ch.uri, 
    expirationTime: ch.expirationTime.
};

channelTable.insert(channel).done(function (item) {

    },
    function () {
        // Error on the insertion.
    });
}

C#:

 var channel = new Channel { Uri = ch.Uri, ExpirationTime = ch.ExpirationTime };
var channelTable = privateClient.GetTable<Channel>();

if (ApplicationData.Current.LocalSettings.Values["ChannelId"] == null)
{
    // Use try/catch block here to handle exceptions
    await channelTable.InsertAsync(channel);
}

C++:

 auto channel = ref new JsonObject();
channel->Insert(L"Uri", JsonValue::CreateStringValue(ch->Uri));
channel->Insert(L"ExpirationTime", JsonValue::CreateBooleanValue(ch->ExpirationTime));

auto table = MobileService->GetTable("Channel");
task<IJsonValue^> (table->InsertAsync(channel))
    .then([this, item](IJsonValue^ V) { /* ... */ });

Beachten Sie, dass nach dem Einfügen des Kanaldatensatzes sämtliche Änderungen oder Hinzufügungen, die der Dienst möglicherweise für diesen Datensatz vorgenommen hat, auch im Client enthalten sind.

Außerdem werden, wenn im GetTable/getTable-Aufruf der Name der Datenbank nicht korrekt angegeben ist, so lange keine Ausnahmen angezeigt, bis Sie versuchen, einen Datensatz einzufügen. Dies kann ein schwer nachzuverfolgender Bug sein. Wenn Sie also der Meinung sind, dass alles richtig funktionieren müsste, dies aber nicht der Fall ist, sollten Sie den Datenbanknamen überprüfen.

Nochmals, diese Einfügungen auf der Clientseite werden in HTTP-Anforderungen an den Dienst übersetzt, aber selbst auf der Dienstseite wird Ihnen dies nicht angezeigt. Sie erhalten und verarbeiten nicht Anforderungen, Sie fügen stattdessen benutzerdefinierte Skripts an die einzelnen Datenbankvorgänge (Einfügen, Lesen, Aktualisieren und Löschen) an.

Diese Skripts werden als JavaScript-Funktionen geschrieben, die dieselben intrinsischen Objekte und Methoden verwenden, die in Node.js verfügbar sind (all dies hat überhaupt nichts mit irgendeinem clientseitigen JavaScript in der App zu tun). Jede Funktion empfängt passende Parameter: insert und update empfangen den neuen Datensatz, delete empfängt die ID des Elements und read empfängt eine Abfrage. All die Funktionen empfangen außerdem ein user-Objekt, wenn die App den Benutzer mit dem mobilen Dienst authentifiziert hat, und ein request-Objekt, mit dem Sie den Vorgang ausführen und die letztendliche HTTP-Antwort erstellen können.

Das einfachste (und standardmäßige) insert-Skript führt nur die Anforderung aus und fügt den Datensatz, item, „as-is“ ein:

 function insert(item, user, request) {
    request.execute();
}

Wenn Sie einen Zeitstempel und die Benutzer-ID an den Datensatz anfügen möchten, ist das so einfach wie das Hinzufügen dieser Eigenschaften zum item-Parameter vor dem Ausführen der Anforderung:

 function insert(item, user, request) {
    item.user = user.userId;
    item.createdAt = new Date();
    request.execute();
}

Beachten Sie, dass die Änderungen, die vor dem Einfügen in die Datenbank an item in diesen Skripts vorgenommen wurden, automatisch zurück an den Client übermittelt werden. Im obigen Code würde das channel-Objekt im Client user- und createdAt-Eigenschaften enthalten, sobald das Einfügen abgeschlossen wäre. Eine überaus praktische Sache!

Die Dienstskripts können außerdem auch weitere Aktionen nach request.execute ausführen, insbesondere als Reaktion auf Erfolg oder Fehlschlagen, aber die Einzelheiten diesbezüglich können Sie dem Serverskriptbeispiel der Gewusst-wie-Dokumentation entnehmen.

Kehren wir nun zu Pushbenachrichtigungen zurück. Das Speichern der Kanal-URIs in einer Tabelle ist nur ein Teil der Gleichung, und der Dienst kann Benachrichtigungen als Reaktion auf dieses bestimmte Ereignis senden oder auch nicht. Wahrscheinlicher ist aber, dass der Dienst über andere Tabellen mit zusätzlichen Informationen verfügt, bei denen Vorgänge, die für diese Tabellen ausgeführt werden, Benachrichtigungen an irgendeine Untergruppe von Kanal-URIs auslösen. Im nächsten Abschnitt erläutern wir das anhand einiger Beispiele genauer. Wie dem auch sei, Sie senden eine Pushbenachrichtigung von einem Skript mithilfe des push.wns - Objekts. Dieses wiederum verfügt über zahlreiche Methoden zum Senden von spezifischen Typen von Updates (einschließlich unformatierte). Dabei funktionieren Kacheln, Popups und Signale direkt über Namensmethoden, die den verfügbaren Vorlagen entsprechen. Zum Beispiel:

 push.wns.sendTileSquarePeekImageAndText02(channel.uri, {
    image1src: baseImageUrl + "image1.png",
    text1: "Notification Received",
    text2: item.text
}, {
    success: function (pushResponse) {
        console.log("Sent Tile Square:", pushResponse);
    },
    error: function (err) {
        console.log("Error sending tile:", err);
    }

});

push.wns.sendToastImageAndText02(channel.uri, {
    image1src: baseImageUrl + "image2.png",
    text1: "Notification Received",
    text2: item.text
}, {
    success: function (pushResponse) {
        console.log("Sent Toast:", pushResponse);
    }
});

push.wns.sendBadge(channel.uri, {
    value: value,
    text1: "Notification Received"
}, {
    success: function (pushResponse) {
        console.log("Sent Badge:", pushResponse);
    }
});

Auch hier hinterlässt die console.log-Funktion einen Eintrag in den Protokollen, den Sie auf dem Azure Mobile Services-Portal einsehen können. Daher sollten Protokollaufrufe, wie in der Kachelbenachrichtigung oben dargestellt, normalerweise in Fehlerhandler einbezogen werden.

Sie haben vielleicht bemerkt, dass die send* -Methoden jeweils an eine spezifische Vorlage gebunden sind. Für Kacheln bedeutet das, dass die Nutzlasten für breite Kacheln und für quadratische Kacheln separat als zwei Benachrichtigungen gesendet werden müssen. Denken Sie daran, dass Sie fast immer beide Größen zusammen senden sollten, da der Benutzer steuert, wie die Kachel auf seiner Startseite angezeigt wird. Mit den vorlagenspezifischen send-Funktionen von push.wns werden zwei sequenzielle Aufrufe ausgeführt, die jeweils beide eine separate Pushbenachrichtigung erstellen.

Um mehrere Updates zu kombinieren – und das schließt das gleichzeitige Senden mehrerer Kachelupdates mit unterschiedlichen Tags oder das Senden mehrerer Signale ein – müssen Sie die Methoden push.wns.sendTile und push.wns.sendToast verwenden. Zum Beispiel:

 var channel = '{channel_url}';

push.wns.sendTile(channel,
    { type: 'TileSquareText04', text1: 'Hello' },
    { type: 'TileWideText09', text1: 'Hello', text2: 'How are you?' },
    { client_id: '{your Package Security Identifier}', client_secret: '{your Client Secret}' },

    function (error, result) {
        // ...
    });

Auf einer sogar noch niedrigeren Ebene können Sie bei push.wns.send in Bezug auf die Inhalte der Benachrichtigung sehr genau sein; es steht auch push.wns.sendRaw für unformatierte Benachrichtigungen zur Verfügung. Alle weiteren Informationen hierzu finden Sie ebenfalls in der Dokumentation zum push.wns-Objekt.

Reale Szenarien mit Windows Azure Mobile Services

Die Beispiel-App unter Tile, Toast, and Badge Push Notifications using Windows Azure Mobile Services zeigt, wie Sie Pushbenachrichtigungen als Reaktion auf das Einfügen einer neuen Nachricht in eine Datenbanktabelle senden. Dies bedeutet allerdings, dass die App am Ende Pushbenachrichtigungen an sich selbst sendet, was sie eigentlich nicht tun müsste (außer vielleicht um Benachrichtigungen an dieselbe App auf den anderen Geräten des Benutzers zu senden).

Der wahrscheinlichere Fall ist, dass der Dienst Pushbenachrichtigungen als Reaktion auf Ereignisse sendet, die außerhalb der App/Kachel auftreten, die letztendlich diese Benachrichtigungen empfängt. Betrachten wir ein paar Szenarien:

  • Verwenden von sozialen Netzwerken:

Apps können über das soziale Netzwerk des Benutzers Funktionen wie das Ausgeben von Herausforderungen an dessen Freunde implementieren. Wenn beispielsweise ein Benutzer einen neuen Highscore in einem Spiel erzielt hat, möchten Sie vielleicht über Kachelupdates oder Popups Herausforderungen an die Freunde des Benutzers ausgeben, die das Spiel ebenfalls installiert haben. Auch bei Fitness-Apps, bei denen Sie eine neue Bestleistung für eine bestimmte Aktivität posten können, ist dies vorstellbar.

Dazu kann die App einen neuen Datensatz in eine entsprechende Tabelle (Punktestände, Bestzeiten usw.) des mobilen Diensts einfügen. Innerhalb des Einfügeskripts kann der Dienst seine Datenbank auf in Frage kommende Freunde des aktuellen Benutzers abfragen und dann Benachrichtigungen an jene Kanal-URIs senden. In zusätzlichen Abfragekriterien wird der genaue Aspekt eines Spiels, die spezielle Art der Übung (für sekundäre Kacheln) usw. beschrieben.

  • Aktuelle Wetterdaten und -warnungen:

Bei Wetter-Apps können Sie in der Regel der primären Kachel der App einen bestimmten Standort zuweisen und für zusätzliche Standorte sekundäre Kacheln erstellen. Die relevanten Informationen bei den einzelnen Kacheln sind der Längen- und der Breitengrad des Standorts, die die App zusammen mit den einzelnen Kanal-URIs (durch Einfügen in eine Tabelle) an den Dienst sendet. Um ein Update an diesen Kanal auszulösen, verfügt der Dienst möglicherweise über einen anderen Prozess (wie der unten beschriebene geplante Auftrag), der einen zentralen Wetterdienst regelmäßig auf aktuelle Daten und Warnungen abfragt und dann die erhaltenen Antworten verarbeitet und die entsprechend erstellten Nachrichten in eine Tabelle für Warnungen im mobilen Dienst einfügt. Das Einfügeskript ruft dann die entsprechenden Kanal-URIs ab und sendet die Updates. Wenn ein Wetterdienst die Möglichkeit der Registrierung für Warnungen oder regelmäßige Updates bietet, würde eine andere Seite im Dienst diese Anforderungen (sehr wahrscheinlich HTTP PUTs) empfangen, sie verarbeiten und den mobilen Dienst aufrufen, um einen Datensatz einzufügen, und dadurch ein Update auslösen.

  • Nachrichten:

Das Verarbeiten von Sofortnachrichten erfolgt nahezu auf dieselbe Art und Weise wie das Empfangen von aktuellen Wetterdaten. Auch hier überwacht ein anderer Prozess den Empfang von neuen Nachrichten, z. B. ein Prozess, der auf regelmäßige Nachrichten überprüft, oder er registriert sich bei der Nachrichtenquelle für Benachrichtigungen beim Eingang von neuen Nachrichten. Bei beiden Optionen löst der Eingang einer neuen Nachricht Pushbenachrichtigungen an die entsprechenden Kanäle aus. In diesem Fall sind die Kanal-URIs der Kachel eines Benutzers für eine bestimmte Nachrichtenform zugeordnet. Wahrscheinlich verwenden Sie in diesem Fall unformatierte Benachrichtigungen, da er dem am Anfang des Beitrags beschriebenen E-Mail-Szenario ähnelt.

In all diesen Szenarien sollten Sie beachten, dass es eigentlich nicht notwendig ist, überhaupt irgendetwas in eine Datenbanktabelle einzufügen. Wenn Sie nicht request.execute im Einfügeskript aufrufen, bleibt die Datenbank zwar leer, aber Sie können weiterhin andere Aufgaben innerhalb dieses Skripts durchführen, z. B. Benachrichtigungen senden. In anderen Worten gesagt, macht es keinen Sinn, die Datenbank mit Datensätzen zu füllen, die Sie später gar nicht verwenden, insbesondere da das Speichern von Daten ja Geld kostet.

Beachten Sie außerdem auch, dass Azure Mobile Services Funktionen zur Planung von Aufträgen besitzt. Informationen hierzu finden Sie unter Schedule recurring jobs in Mobile Services. Bei solchen Aufträgen können z. B. routinemäßig Daten von anderen Diensten abgerufen und dann verarbeitet und anschließend Datensätze in die Datenbank des Diensts eingefügt werden. Auch hier werden dadurch Pushbenachrichtigungen ausgelöst. Ebenso können, wie bereits in Teil 2 dieser Reihe erwähnt, andere Webseiten und mobile Apps Änderungen an dieser Datenbank vornehmen und Pushbenachrichtigungen auslösen. Die Datenbankskripts im mobilen Dienst werden in all diesen Fällen ausgeführt.

Zusammenfassung

Zum Abschluss dieser Reihe haben wir ausführlich besprochen, was ein „lebendiges und dynamisches System“ alles für Benutzer, Entwickler, Apps und Dienste bedeutet. Sie haben die Möglichkeiten von Kachel-, Signal- und Popupupdates gesehen, gelernt, wie sich regelmäßige Benachrichtigungen einrichten lassen und wie Hintergrundaufgaben als Teil dieses Prozesses verwendet werden, und Sie kennen nun die Struktur von Diensten für die Verarbeitung von regelmäßigen Benachrichtigungen sowie Pushbenachrichtigungen. Und ganz eindeutig bietet Windows Azure Mobile Services einen viel ausführlicheren und besseren Überblick über den ganzen Prozess des Arbeitens mit Pushbenachrichtigungen. Sie sind damit im Vergleich zum Schreiben vollkommen neuer Dienste auf jeden Fall produktiver – und es erspart Ihnen wahrscheinlich einiges an Kopfzerbrechen.

Kraig Brockschmidt

Programmmanager, Windows Ecosystem Team

Autor, Programming Windows 8 Apps in HTML, CSS, and JavaScript