April 2017

Band 32, Nummer 4

UWP-Apps: Entwickeln gehosteter Web-Apps für UWP

Von Sagar Bhanudas Bhanudas

Viele Entwickler und Unternehmen erstellen Webschnittstellen für ihre Produkte und Dienste, damit diese schnell gefunden werden können und der Zugriff darauf einfach ist. Eine weitere Plattform ist die Apps-Plattform. Native Apps stellen eine umfangreichere UX und Anzahl von Funktionen als Web-Apps zur Verfügung. Project Westminster bietet Entwicklern nun die Möglichkeit, moderne Websites in native Apps zu konvertieren.

Die Project Westminster-Brücke ermöglicht Webentwicklern, ihre dynamischen Webanwendungen auf die universelle Windows-Plattform (UWP) zu übertragen, indem vorhandener Code genutzt wird (siehe Beitrag „Project Westminster in a Nutshell“ des Windows Developer-Blogs unter bit.ly/2jyhVQo). Diese „Brücke“ basiert auf der folgenden Idee: vorhandener Websitecode soll wiederverwendet und eine Schicht für UWP-spezifischen Code hinzugefügt werden, um die Integrationspunkte der Web-App in eine zugrunde liegenden Windows-Plattform zu bilden. Der Blogbeitrag beschäftigt sich mit einigen Codierungspraktiken, um eine konsistente UX sicherzustellen.

Wie kann ein Webentwickler eine moderne Webanwendung so integrieren, dass sie z. B. mit Cortana zusammenarbeitet? Die Antwort lautet: durch den gemeinsamen Nenner JavaScript. Windows stellt die Funktionen des App-Frameworks (Windows-Runtime-APIs) über JavaScript und den Windows-Namespace bereit. Die sich ergebenden Apps werden als „gehostete Web-Apps“ bezeichnet.

In diesem Artikel erfahren Sie, was ich bei der Zusammenarbeit mit unabhängigen Softwareherstellern (ISVs) und Partnern beim Portieren ihrer Apps auf die UWP mithilfe des Project Westminster-Tools gelernt habe. Der Schwerpunkt liegt dabei auf den Details, wie Web-Apps am besten für die Bereitstellung optimaler UX angepasst werden, während die Ausführung als Plattform-App erfolgt.

Erste Schritte

Als Einstieg in das Project Westminster-Tool müssen Sie zuerst Ihre Website in die UWP konvertieren (weitere Informationen dazu finden Sie im Channel 9-Video „Creating Hosted Web Apps with Project Westminster“ unter bit.ly/2jp4srs).

Testen Sie die Website vorläufig mit dem Browser Microsoft Edge, um sicherzustellen, dass sie wie erwartet gerendert wird und die Präsentation konsistent aussieht. Auf diese Weise können Sie Renderingprobleme identifizieren und beheben, bevor mit der Codierungsintegration für Windows-Funktionalität begonnen wird.

Die meisten Websites weisen einige gemeinsame Features auf, die Benutzern ermöglichen, eine bestimmte Ausgabe auszuführen (etwa das Ausfüllen von Formularen) oder Informationen zu Referenzzwecken abzurufen (z. B. das Herunterladen eines Handbuchs). In solchen Szenarien ist es wichtig, dass diese Funktionen intakt bleiben und die neu generierte gehostete Benutzeroberfläche der Web-App konsistent mit der ursprünglichen Website ist. Einige dieser Szenarien müssen ggf. getestet und überprüft werden, damit mithilfe von Code ein Refactoring erfolgen kann, um die Erwartungen der Benutzer zu erfüllen. In den nächsten Abschnitten stelle ich einige Schlüsselszenarien vor, um verschiedene Klassen oder Objekte zu zeigen, die Entwicklern beim Arbeiten mit dem Project Westminster-Tool und zugehörigen Codeworkflows zur Verfügung stehen. Beim Portieren der App in die UWP ist es ratsam, die Integration einiger nativer Features der Plattform in Erwägung zu ziehen, um eine reichhaltigere UX und eine optimierte App-Benutzeroberfläche zu erhalten. Die folgenden Features werden von App-Entwicklern häufig implementiert:

  • Kontakte
  • Cortana-Integration
  • Live-Kacheln
  • Popupbenachrichtigungen
  • Kamera und Mikrofon
  • Fotogalerie
  • Erweiterte Grafiken und Window-Runtime-Medienstapel
  • Freigeben von Inhalten für andere Apps

In diesem Artikel liegt der Schwerpunkt auf der Integration von UWP-Features (z. B. Cortana und Live-Kacheln), die die Aktivierung von Apps über sprachbasierte Befehle und Informationsbereitstellung für den Benutzer unterstützen. Auf diese Weise wird die gesamte UX durch Unterstützung der Infrastruktur von UWP-Apps optimiert. Die Webseite mit den aktuellen Windows 10-Features für Entwickler (bit.ly/2iKufs6) bietet einen schnellen Überblick über weitere Integrationsmöglichkeiten. Die Webseite, die in eine App konvertiert wird, stellt Informationen zu den folgenden Aspekten zur Verfügung:

  1. Features der Webanwendungsfunktionalität
    1. Dateidownloads
    2. Sitzungsverwaltung oder einmaliges Anmelden (SSO)
    3. Sichere Rückkehr zur vorherigen Seite über die Schaltfläche „Zurück“
  2. UWP-Integrationsfeatures
    1. Live-Kacheln
    2. Cortana

Diese Features müssen bei der Portierung und dem Refactoring berücksichtigt werden, um eine vorhersagbare Benutzeroberfläche für die App bereitzustellen.

Szenario „Dateidownload“

Die meisten heutigen Webanwendungen ermöglichen Dateidownloads für eine Vielzahl von Inhalten. Wie Abbildung 1 zeigt, erfolgt der Dateidownload in der Standardbenutzeroberfläche im Browser z. B. durch Klicken auf eine Schaltfläche oder auf einen Link. Der Browser beginnt dann mit dem Download einer Datei und speichert diese außerdem (meistens) in „rootdir:\Benutzer\Benutzername\Downloads“.

Standardbenutzeroberfläche für den Download

Abbildung 1: Standardbenutzeroberfläche für den Download

Dies ist zum Teil der Fall, weil der Browser eine native Win32-Anwendung ist, die mit voller Vertrauenswürdigkeit ausgeführt wird und die Datei direkt in den Ordner „Downloads“ schreibt.

Sehen Sie sich nun das gleiche Szenario an, wenn die Website im Kontext einer App (genauer: „WWAHost.exe“) ausgeführt und auf die Downloadschaltfläche geklickt wird. Was geschieht nun? Wahrscheinlich geschieht überhaupt nichts, und es sieht so aus, als würde der Code einfach nicht funktionieren. Es kann so aussehen als würde die Schaltfläche nicht reagieren. Vielleicht wurde der Dateidownload auch gestartet, aber wo wird die Datei gespeichert?

„WWAHost.exe“ ist ein App-Container für Websites, der eine Teilmenge von Features im Vergleich zum Browser aufweist. Diese Teilmenge von Features umfasst die Renderingfunktion (hauptsächlich Präsentation über HTML) und die Standardskriptausführung.

Sie arbeiten nun tatsächlich mit einer App. In der Welt der Apps sollten Entwickler den Dateidownload explizit programmieren. Andernfalls ist die Remotedatei nur eine URL, und es ist unklar, welche Aktion die App bzw. der Container mit einer Remotedatei-URL ausführt (ich kann mithilfe spezialisierter Debugtools herausfinden, was im Verborgenen geschieht, möchte an dieser Stelle aber nicht weiter darauf eingehen).

Zum Verarbeiten dieser Art von Szenarien müssen Sie die entsprechenden UWP-APIs aufrufen. Diese APIs können mit dem Code koexistieren, durch den diese Funktionen beim Ausführen der Website mithilfe eines Browsers ermöglicht werden. Abbildung 2 zeigt den verwendeten Code.

Abbildung 2: JavaScript-Code für Dateidownload (größere Dateien)

(function() {
  if (typeof Windows !== 'undefined' &&
    typeof Windows.UI !== 'undefined' &&
    typeof Windows.ApplicationModel !== 'undefined') {
  function WinAppSaveFileBGDownloader() {
    // This condition is only true when running inside an app.
    // The else condition is effective when running inside browsers.
    // This function uses the Background Downloader class to download a file.
    // This is useful when downloading a file more than 50MB. 
    // Downloads continue even after the app is suspended/closed.
    if (typeof Windows !== 'undefined' &&
      typeof Windows.UI !== 'undefined' &&
      typeof Windows.ApplicationModel !== 'undefined') {
        var fileSavePicker = new Windows.Storage.Pickers.FileSavePicker();
        // Example: You can replace the words EXTENSION and ext with the word PNG. 
        fileSavePicker.fileTypeChoices.insert(
          "EXTENSION file", [".ext"]);
            // Insert appropriate file format through code.
        fileSavePicker.defaultFileExtension = ".ext";
          // Extension of the file being saved.
        fileSavePicker.suggestedFileName = "file.ext";
          // Name of the file to be downloaded.
        fileSavePicker.settingsIdentifier = "fileSavePicker1";
        var fileUri =
          new Windows.Foundation.Uri("<URL of the file being downloaded>");
        fileSavePicker.pickSaveFileAsync().then(function (fileToSave) {
          var downloader =
            new Windows.Networking.BackgroundTransfer.BackgroundDownloader();
          var download = downloader.createDownload(
            fileUri,
            fileToSave);
          download.startAsync().then(function (download) {
            // Any post processing.
            console.log("Done");
          });
        });
      }
      else {
        // Use the normal download functionality already implemented for browsers,
        // something like <a href="<URL>" />.
      }
    }
}
})();

Sie können den Code in Abbildung 2 für das Klicken auf die Schaltfläche oder für eine beliebige andere Aktion schreiben, bei der die Dateidownloadfunktion erwartet wird. Der Codeausschnitt

verwendet die BackgroundDownloader-Klasse (bit.ly/2jQeuBw), die zahlreiche Vorteile besitzt, z. B. das persistente Speichern von Downloads im Hintergrund, Unterbrechung nach der App-Ausführung und die Möglichkeit, große Dateien herunterzuladen.

Der Code in Abbildung 2 erstellt tatsächlich die gleiche Benutzeroberfläche wie ein Browser. Der Benutzer wird z. B. aufgefordert, einen Dateispeicherort auszuwählen (fileSavePicker-Variable), der Download wird eingeleitet (downloader-Variable), und die Datei wird in den ausgewählten Speicherort geschrieben.

Alternativ können Sie den Code in Abbildung 3 für kleinere Dateidownloads verwenden. Die Ausführung erfolgt genau so lange wie die App ausgeführt wird:

Abbildung 3: JavaScript-Code für Dateidownload (kleinere Dateien)

// Use the Windows.Web.Http.HttpClient to download smaller files and
// files are needed to download when the app is running in foreground.
(function() {
  if (typeof Windows !== 'undefined' &&
    typeof Windows.UI !== 'undefined' &&
    typeof Windows.ApplicationModel !== 'undefined') {
  function WinAppSaveFileWinHTTP() {
    var uri = new Windows.Foundation.Uri("<URL of the file being downloaded>");
    var fileSavePicker = new Windows.Storage.Pickers.FileSavePicker();
    fileSavePicker.fileTypeChoices.insert("EXT file",
      [".ext"]); //insert appropriate file format through code.
    fileSavePicker.defaultFileExtension = ".ext";
      // Extension of the file being saved.
    fileSavePicker.suggestedFileName = "file.ext";
      // Name of the file to be downloaded. Needs to be replaced programmatically.
    fileSavePicker.settingsIdentifier = "fileSavePicker1";
    fileSavePicker.pickSaveFileAsync().then(function (fileToSave) {
      console.log(fileToSave);
      var httpClient = new Windows.Web.Http.HttpClient();
      httpClient.getAsync(uri).then(function (remoteFile) {
        remoteFile.content.readAsInputStreamAsync().then(
           function (stream) {
          fileToSave.openAsync(
            Windows.Storage.FileAccessMode.readWrite).then(
            function (outputStream) {
            Windows.Storage.Streams.RandomAccessStream.copyAndCloseAsync(
              stream, outputStream).then(function (progress, progress2) {
          // Monitor file download progress.
            console.log(progress);
            var temp = progress2;
          });
        });
        });
      });
    });
  }
}
})();

Der Code in Abbildung 3 verwendet „Windows.Web.Http.HttpClient“ zum Verarbeiten des Dateidownloadvorgangs (bit.ly/2k5iX2E). Wenn Sie die Codeausschnitte in Abbildung 2 und Abbildung 3 vergleichen, fällt Ihnen auf, dass für den letztgenannten Codeausschnitt fortgeschrittenere Codierung erforderlich ist, damit eine größere Kontrolle über den Dateidownload erfolgen kann. Auf diese Weise können Sie auch die verschiedenen Möglichkeiten untersuchen, einen Datenstrom mithilfe einer UWP-App in einer Datei zu speichern.

In dem Beispiel, in dem die App die heruntergeladenen Dateien auch verarbeitet, sollte nach Möglichkeit die Eigenschaft „FutureAccessList“ zum Zwischenspeichern des Speicherorts der Datei und für den Zugriff darauf verwendet werden (bit.ly/2k5fXn6). Dies ist wichtig, weil der Benutzer die heruntergeladenen Dateien an einem beliebigen Speicherort im System speichern kann (z. B. in „D:\Dateien\“ oder in „C:\Benutzer\MeinBenutzer\MeineDateien\“). Der App-Container (als Sandkastenprozess) ist ggf. nicht in der Lage, ohne vom Benutzer ausgelöste Aktionen auf das Dateisystem zuzugreifen. Diese Klasse kann zum Vermeiden zusätzlicher Schritte des Benutzers beim erneuten Öffnen der gleichen Datei verwendet werden. Damit diese Klasse verwendet werden kann, muss die Datei mit „FileOpenPicker“ mindestens ein Mal geöffnet worden sein.

Dies sollte bei der Optimierung der Dateidownloadfunktion in gehosteten Web-Apps und beim Bereitstellen intuitiver UX hilfreich sein. (Tipp: Stellen Sie sicher, dass die URL-Domäne der Datei dem „ApplicationContentURI“ unter bit.ly/2jsN1WS hinzugefügt wird, um Laufzeitausnahmen zu vermeiden.)

Sitzungsverwaltung

Die meisten modernen Apps speichern heute Daten zwischen mehreren Sitzungen von Benutzern persistent. Stellen Sie sich als Beispiel vor, Sie müssten sich bei einer häufig verwendeten App bei jedem Start dieser App anmelden. Dies würde viel Zeit in Anspruch nehmen, wenn die App mehrmals täglich gestartet wird. Im Windows-Runtime-Framework sind Klassen für Web-Apps verfügbar, die in UWP-Apps konvertiert werden.

Stellen Sie sich ein Szenario vor, in dem bestimmte Parameter zwischen Sitzungen des gleichen Benutzers persistent gespeichert werden müssen. Angenommen, es handelt sich z. B. um eine Zeichenfolge, die den Benutzer identifiziert, und um diverse andere Informationen wie die letzte Sitzungszeit sowie andere zwischengespeicherte Elemente.

Die Klasse, die in diesem Szenario verwendet werden muss, ist „Windows.Storage.ApplicationData“. Diese Klasse verfügt über zahlreiche Eigenschaften und Methoden. Für dieses Szenario eignet sich die Eigenschaft „localSettings“.

Die Einstellungen werden in einem Schlüssel-Wert-Paar gespeichert. Der folgende Beispielcode zeigt die Implementierung:

function getSessionData()
{
var applicationData = Windows.Storage.ApplicationData.current;
var localSettings = applicationData.localSettings;
// Create a simple setting.
localSettings.values["userID"] = "user998-i889-27";
// Read data from a simple setting.
var value = localSettings.values["userID"];
}

Idealerweise kann der Code zum Schreiben von Daten in die Einstellungen an Prüfpunkten in der App geschrieben werden, an denen es erforderlich ist, bestimmte Informationen zu erfassen, die dann an eine Remote-Web-API oder einen -dienst gesendet werden. Der Code zum Lesen der Einstellung kann normalerweise im App_activated-Ereignishandler geschrieben werden, in dem die App gestartet wird und auf die Informationen zugegriffen werden kann, die aus der vorherigen App-Sitzung persistent gespeichert wurden. Beachten Sie, dass für den Namen jeder Einstellung eine Längenbeschränkung von 255 Zeichen und für jede Einstellung eine Größenbeschränkung von 8 KB gilt.

Szenario „Sprachintegration“ (Cortana)

Eines der Szenarien, die Ihre Website (die nun eine App ist) implementieren kann (nach der Portierung in die UWP) ist die Integration von Cortana, einer sprachbasierten interaktiven digitalen Assistentin auf Windows-Geräten.

Angenommen, die Website ist ein Reiseportal. Jetzt – nach der Portierung in eine Windows 10-App – ist einer der Anwendungsfälle, in den Cortana integriert werden kann, das Anzeigen von Details zur Reiseplanung einer Person. Der Benutzer kann dann Befehle wie „Show trip to London“ (zeige meine Reise nach London – natürlich ist auch jedes andere Ziel möglich) ausgeben. Dies muss von App-Entwicklern wie in Abbildung 4 gezeigt konfiguriert werden.

Abbildung 4: XML-Code für Befehle an Cortana

<?xml version="1.0" encoding="utf-8"?>
<VoiceCommands xmlns="http://schemas.microsoft.com/voicecommands/1.1">
  <CommandSet xml:lang="en-us" Name="AdventureWorksCommandSet_en-us">
    <CommandPrefix> Adventure Works, </CommandPrefix>
    <Example> Show trip to London </Example>
    <Command Name="showTripToDestination">
      <Example> Show trip to London </Example>
      <ListenFor RequireAppName=
        "BeforeOrAfterPhrase"> show trip to {destination} </ListenFor>
      <Feedback> Showing trip to {destination} </Feedback>
      <Navigate/>
    </Command>
    <PhraseList Label="destination">
      <Item> London </Item>
      <Item> Dallas </Item>
    </PhraseList>
  </CommandSet>
<!-- Other CommandSets for other languages -->
</VoiceCommands>

Cortana kann das Erledigen von Aufgaben mit zahlreichen Erstanbieter-Apps (z. B. mit dem Kalender) unterstützen und APIs als Schnittstelle für benutzerdefinierte Apps bereitstellen. Die folgenden grundlegenden Aktionen werden beim Zusammenspiel von Cortana mit Apps ausgeführt:

  1. Anhören von Befehlen, die in der Datei „voicecommands.xml“ registriert sind.
  2. Aktivieren der relevanten App und Zuordnen der gesprochenen bzw. in die Windows-Suchleiste eingegebenen Befehle.
  3. Übergeben der Sprach-/Textbefehle an die App als Variablen, damit die App die Benutzereingaben verarbeiten kann.

Hinweis: Der Dateiname ist frei wählbar und sollte sinnvoll sein. Die Datei kann jeden gewünschten Namen mit einer XML-Erweiterung tragen. Der Windows Developer-Artikel „Using Cortana to Interact with Your Customers (10 by 10)“ unter bit.ly/2iGymdE bietet einen guten Überblick über das Konfigurieren von Befehlen in der XML-Datei und deren Schema.

Der XML-Code in Abbildung 4 unterstützt Cortana beim Identifizieren, dass die Adventure Works-App gestartet werden muss, wenn Befehle wie im folgenden Beispiel ausgegeben werden:

'Adventure Works, Show trip to London'
'Adventure Works, Show trip to Dallas'

Sehen wir uns nun an, wie der Webcode die Aktivierung und Navigation zur relevanten Seite in der App (oder auf der Website) basierend auf der Eingabe verarbeiten würde. Sie erstellen eine separate JavaScript-Datei zum Codieren dieses Szenarios.

Auf den Code in Abbildung 5 sollte im Abschnitt „<body>“ auf der Aufruferseite bzw. verweisenden Seite verwiesen werden, unmittelbar bevor das DOMContentLoaded-Ereignis ausgelöst wird. Daher ist es empfehlenswert, „<script src>“ hinzuzufügen, unmittelbar bevor das <body>-Element auf der verweisenden Seite endet.

Abbildung 5: Handlercode für Sprachbefehle

<!-- In HTML page :
<meta name="msapplication-cortanavcd" content="http://<URL>/vcd.xml" />
-->
(function () {
  if (typeof Windows !== 'undefined' &&
    typeof Windows.UI !== 'undefined' &&
    typeof Windows.ApplicationModel !== 'undefined') {
    Windows.UI.WebUI.WebUIApplication.addEventListener("activated", activatedEvent);
  }
  function activatedEvent (args) {
    var activation = Windows.ApplicationModel.Activation;
    // Check to see if the app was activated by a voice command.
    if (args.kind === activation.ActivationKind.voiceCommand) {
      // Get the speech recognition.
      var speechRecognitionResult = args.result;
      var textSpoken = speechRecognitionResult.text;
      // Determine the command type {search} defined in vcd.
      switch (textSpoken) {
         case "London":
           window.location.href =
             'https://<mywebsite.webapp.net>/Pages/Cities.html?value=London';
        break;
      case "Dallas":
        window.location.href =
          'https://<mywebsite.webapp.net>/Pages/Cities.html?value=Dallas';
        break;
                              ...                                   
        <other cases>
                              ...               
      }
    }
  }
})();

 (Hinweis: Da die App durch Cortana mithilfe von „activationKind“ als „voiceCommand“ „aktiviert“ wird, muss der Ereignishandler für diese Aktivierung unbedingt registriert werden. Zum Registrieren von App-Lebenszyklusereignissen für Apps, die keine nativen WinJS- oder C#-Apps sind, wird der Namespace „Windows.UI.WebUI.WebUIApplication“ bereitgestellt, um bestimmte Ereignisse zu abonnieren und zu verarbeiten.)

Im Code in Abbildung 5 empfangen Cortana-APIs die Spracheingabe des Benutzers und füllen die Eigenschaft „SpeechRecognition“ der Aktivierungsklassen mit Daten auf. Dies sollte das Abrufen des konvertierten Texts im Code und die App beim Ausführen der relevanten Aktionen unterstützen. In diesem Ausschnitt verwenden Sie eine switch-case-Anweisung zum Auswerten der textSpoken-Variablen und Weiterleiten des Benutzers auf die Seite „Cities.html“. Dabei wird der Wert der Stadt als „querystring“ angefügt.

Dies ist ganz klar nur eines der Szenarien. Unter Berücksichtigung der Routingkonfiguration für jede Website (MVC, REST usw.) ändern sich die Fälle entsprechend. Die App ist nun bereit, mit Cortana zu sprechen.

Die (fehlende) Schaltfläche „Zurück“

Nachdem wir uns mit einigen der komplexesten Funktionen beschäftigt haben, sollten wir uns nun mit einem grundlegenden (aber wichtigen) Aspekt der App-Benutzeroberfläche befassen: mit der Navigation. Die Einfachheit des Browsens durch die App und eine intuitive Navigationshierarchie unterstützen Benutzer dabei, eine App auf vorhersagbare Weise zu bedienen.

Dieses Szenario ist ein besonderes, weil sich die Benutzeroberfläche beim Portieren der dynamischen Website in eine UWP-App wie erwartet verhält. Sie müssen für den App-Container jedoch weitere Zeiger zum Ausführen der Navigation in der App bereitstellen. Die Standard-UX verhält sich wie folgt:

  1. Der Benutzer startet die App.
  2. Der Benutzer durchsucht verschiedene Abschnitte der App, indem er auf Links oder Menüs auf den Seiten klickt.
  3. An einem bestimmten Punkt möchte der Benutzer zur vorherigen Seite zurückkehren. Er klickt also auf die Hardware- oder Softwareschaltfläche „Zurück“, die vom Windows-Betriebssystem bereitgestellt wird (in der App ist noch keine Schaltfläche „Zurück“ vorhanden).
  4. Die App wird beendet.

Punkt Nr. 4 ist ein unerwartetes Ergebnis und muss korrigiert werden. Die Lösung ist einfach. Sie besteht u. a. darin, das Fenster des App-Containers anzuweisen, über reguläre JavaScript-APIs zurückzukehren. Abbildung 6 zeigt den Code für dieses Szenario.

Abbildung 6: Code für die Schaltfläche „Zurück“

(function() {
  if (typeof Windows !== 'undefined' &&
    typeof Windows.UI !== 'undefined' &&
    typeof Windows.ApplicationModel !== 'undefined') {
   Windows.UI.Core.SystemNavigationManager.getForCurrentView().
     appViewBackButtonVisibility =
     Windows.UI.Core.AppViewBackButtonVisibility.visible;
        Windows.UI.Core.SystemNavigationManager.getForCurrentView().
        addEventListener("backrequested", onBackRequested);
function onBackRequested(eventArgs) {
      window.history.back();
      eventArgs.handled = true;
    }
  }
  })();

Die Anfangszeilen aktivieren die vom Framework bereitgestellte Schaltfläche „Zurück“, die oben in der App angezeigt wird, und registrieren dann einen Ereignishandler für das tap/click-Ereignis. Sie greifen in Ihrem Code nur auf das „Fenster“-DOM-Objekt zu und weisen es an, eine Seite zurückzugehen. An eine Sache müssen Sie denken: Wenn sich die App ganz unten im Navigationsstapel befindet, sind im Verlauf keine weiteren Seiten verfügbar, und die App wird beendet. Es ist erforderlich, zusätzlichen Code zu schreiben, wenn benutzerdefiniertes Verhalten in die App integriert werden muss.

Live-Kacheln

Live-Kacheln sind ein Feature von UWP-Apps, mit dem aktuelle Informationen zu Updates in der App oder beliebige Informationen angezeigt werden, die für den Benutzer interessant sein könnten, ohne dass die App gestartet werden muss. Ein schnelles Beispiel ist das Drücken/Tippen auf das Startmenü auf einem Windows-Gerät. Live-Kacheln eigenen sich gut für Apps wie Nachrichten, Finanzanwendungen und Sport.

Die folgenden Verwendungsfälle können als Beispiel dienen:

  • Für eine E-Commerce-App kann eine Kachel Empfehlungen oder den Status Ihrer Bestellung anzeigen.
  • In einer Branchenanwendung kann eine Kachel ein kleines Bild der Berichte Ihrer Organisation anzeigen.
  • In einer Spiele-App können Live-Kacheln Angebote, Erfolge, neue Herausforderungen usw. anzeigen.

Abbildung 7 zeigt zwei Beispiele für Kacheln aus Microsoft-Erstanbieter-Apps.

Beispiele für Live-Kacheln
Abbildung 7: Beispiele für Live-Kacheln

Eine der einfachsten Möglichkeiten, um Live-Kacheln in Ihre gehostete Web-App zu integrieren, besteht im Erstellen einer Web-API und Einrichten des App-Codes (wie in Abbildung 8 gezeigt) zum Abfragen dieser im Abstand von wenigen Minuten. Die Aufgabe der Web-API besteht im Zurücksenden von XML-Code, der zum Erstellen des Inhalts der Kachel für die Windows-App verwendet wird. (Hinweis: Es ist wichtig, dass der Endbenutzer die App an das Startmenü anheftet, um Live-Kacheln nutzen zu können.)

Abbildung 8: Code für einfache Live-Kacheln

function enableLiveTile()
  {
    if (typeof Windows !== 'undefined' &&
      typeof Windows.UI !== 'undefined' &&
      typeof Windows.ApplicationModel !== 'undefined') {
      {
        var notification = Windows.UI.Notifications;
        var tileUpdater =
          notification.TileUpdateManager.createTileUpdaterForApplication();
        var recurrence = notification.PeriodicUpdateRecurrence.halfHour;
        var url = new Windows.Foundation.Uri("<URL to receieve the XML for tile>");
        tileUpdater.startPeriodicUpdate(url, recurrence);
      }
      }       
  }

Die wichtigste Klasse ist hier „TileUpdateManager“ aus dem Namespace „Windows.UI.Notifications“. Diese Klasse erstellt nicht nur intern die Vorlage für das Senden an die Kachel, sondern fragt auch die angegebene URL nach dem XML-Inhalt der Kachel über die startPeriodicUpdate-Methode ab. Die Dauer der Abfrage kann mithilfe der Periodic­UpdateRecurrence-Enumeration für den regelmäßigen Abruf des XML-Inhalts für Kacheln festgelegt werden. Dieser Ansatz ist serverorientiert, wenn die Web-API den XML-Code und die Kachelvorlage an den Client sendet. Dies ist praktikabel, wenn der Entwickler die Kontrolle über die App und die Dienstschichten besitzt.

Stellen Sie sich nun ein Szenario vor, in dem die App Informationen von Drittanbieter-Web-APIs empfängt (z. B. Wetter- oder Marktforschungsdaten). In solchen Szenarien würden hauptsächlich die Web-APIs HTTP-Standardantworten (Text, Header usw.) senden. Sie können dann die Antwort der Web-API analysieren und den Inhalt einer XML-Kachel im clientseitigen Code der UWP-App in JavaScript generieren. Auf diese Weise besitzt der Entwickler größere Kontrolle über den Typ der Vorlagen zum Anzeigen der Daten. Sie können außerdem die Ablaufzeit für die Kachel über die TileNotification-Klasse angeben. Der zugehörige Code wird in Abbildung 9 gezeigt.

Abbildung 9: Eine weitere Option für das Erstellen von Live-Kacheln

function createLiveTile() /* can contain parameters */
{
  var notifications = Windows.UI.Notifications,
  tile = notifications.TileTemplateType.tileSquare310x310ImageAndText01,
  tileContent = notifications.TileUpdateManager.getTemplateContent(tile),
  tileText = tileContent.getElementsByTagName('text'),
  tileImage = tileContent.getElementsByTagName('image');
  // Get the text for live tile here [possibly] from a remote service through xhr.
  tileText[0].appendChild(tileContent.createTextNode('Demo Message')); // Text here.
  tileImage[0].setAttribute('src','<URL of image>');
  var tileNotification = new notifications.TileNotification(tileContent);
  var currentTime = new Date();
  tileNotification.expirationTime = new Date(currentTime.getTime() + 600 * 1000);
    notifications.TileUpdateManager.createTileUpdaterForApplication().
    update(tileNotification);
}

Beachten Sie, dass die TileTemplateType-Klasse eine Funktion zum Erstellen einer quadratischen Kachelvorlage mit einer Größe von 310 x 310 Pixeln mit einem Bild und Text bereitstellt. Außerdem wird die Ablaufzeit für die Kachel über Code auf 10 Minuten festgelegt. Nach dieser Zeit wird die Live-Kachel auf die Standardkachel der App zurückgesetzt, die im App-Paket bereitgestellt wird, wenn keine neue Benachrichtigung in der App in der Form von Pushbenachrichtigungen eingeht. Weitere Informationen zu verfügbaren Kachelvorlagen finden Sie unter bit.ly/2k5PDJj.

Zusammenfassung

Beim Planen der Migration aus einer Web-App in eine UWP-App müssen einige Aspekte berücksichtigt werden:

  1. Testen Sie die App hinsichtlich Layout und Rendering mithilfe moderner Browser (z. B. Microsoft Edge).
  2. Wenn Ihre Web-App ein ActiveX-Steuerelement oder -Plug-In verwendet, stellen Sie mithilfe eines alternativen Verfahrens sicher, dass die Funktionalität erhalten bleibt, wenn die Ausführung mit modernen Browsern oder als eine UWP-App erfolgt.
  3. Verwenden Sie das SiteScan-Tool unter bit.ly/1PJBcpi, um Empfehlungen umzusetzen, die sich auf Bibliotheken und die Funktionalität beziehen.
  4. Identifizieren Sie die URLs externer Ressourcen, auf die Ihre Website verweist. Diese müssen dem Abschnitt „ApplicationContentUriRules“ der Datei „Appx.manifest“ hinzugefügt werden.

Außerdem sind zahlreiche tiefgreifendere Integrationen verfügbar, die durch das JavaScript Windows-Objekt umgesetzt werden können und die App-Funktionalität durch eine optimierte Benutzeroberfläche bereichern. Kontakte, Kamera, Mikrofon, Popupbenachrichtigungen und viele weitere Features eröffnen Möglichkeiten, Ihre Website mit der individuellen App zu verbinden. Der Code in diesem Artikel wurde in eine Projektvorlage konvertiert und Entwicklern über GitHub unter bit.ly/2k5FlJh zur Verfügung gestellt.


Sagar Bhanudas Joshiarbeitet seit mehr als sechs Jahren mit Entwicklern und ISVs an der universellen Windows-Plattform und Microsoft Azure zusammen. Seine Aufgabe besteht z. B. in der Zusammenarbeit mit Startups, um diese bei der Architektur, dem Entwurf und der Bereitstellung von On-Board-Lösungen und -Anwendungen für Azure, Windows und die Office 365-Plattform zu unterstützen. Joshi lebt und arbeitet in Mumbai in Indien. Folgen Sie ihm auf Twitter: @sagarjms.

Unser Dank gilt den folgenden technischen Experten von Microsoft für die Durchsicht dieses Artikels: Sandeep Alur und Ashish Sahu