Freigeben über


Lernprogramm: Senden von Pushbenachrichtigungen an Flutter-Apps mithilfe von Azure Notification Hubs über einen Back-End-Dienst

Downloadbeispiel Laden Sie das Beispiel

In diesem Lernprogramm verwenden Sie Azure Notification Hubs, um Benachrichtigungen an eine Flutter- Anwendung zu übertragen, die auf Android- und iOS-ausgerichtet ist.

Eine ASP.NET Core Web API Back-End wird verwendet, um Geräteregistrierung für den Client mithilfe des neuesten und besten Installations- Ansatzes zu behandeln. Der Dienst sendet pushbenachrichtigungen auch plattformübergreifend.

Diese Vorgänge werden mithilfe des Notification Hubs SDK für Back-End-Vorgängebehandelt. Weitere Details zum allgemeinen Ansatz finden Sie in der Registrierung aus Ihrem App-Back-End Dokumentation.

Dieses Lernprogramm führt Sie durch die folgenden Schritte:

Voraussetzungen

Um ihnen zu folgen, benötigen Sie Folgendes:

  • Ein Azure-Abonnement, in dem Sie Ressourcen erstellen und verwalten können.
  • Das Flutter Toolkit (zusammen mit seinen Voraussetzungen).
  • Visual Studio Code mit installierten Flutter- und Dart-Plug-In s.
  • CocoaPods zum Verwalten von Bibliotheksabhängigkeiten installiert.
  • Die Möglichkeit, die App entweder auf Android (physische oder Emulatorgeräte) oder iOS- (nur physische Geräte) auszuführen.

Für Android müssen Sie folgendes haben:

  • Ein entwickler entsperrtes physisches Gerät oder ein Emulator (ausgeführt api 26 und höher mit installierten Google Play Services).

Für iOS müssen Sie folgendes haben:

  • Ein aktives Apple Developer Account.
  • Ein physisches iOS-Gerät, das für Ihr Entwicklerkonto registriert (unter iOS 13.0 und höher).
  • Ein .p12-Entwicklungszertifikat in Ihrem Schlüsselbund installiert, mit dem Sie eine App auf einem physischen Gerätausführen können.

Anmerkung

Der iOS-Simulator unterstützt keine Remotebenachrichtigungen und es ist daher ein physisches Gerät erforderlich, wenn Sie dieses Beispiel unter iOS erkunden. Sie müssen die App jedoch nicht sowohl auf Android als auch auf iOS- ausführen, um dieses Lernprogramm abzuschließen.

Sie können die Schritte in diesem Beispiel für erste Prinzipien ohne vorherige Erfahrung ausführen. Sie profitieren jedoch von der Vertrautheit mit den folgenden Aspekten.

Die angegebenen Schritte sind spezifisch für macOS-. Es ist möglich, Windows zu verfolgen, indem Sie die iOS- Aspekte überspringen.

Einrichten von Pushbenachrichtigungsdiensten und Azure Notification Hub

In diesem Abschnitt richten Sie Firebase Cloud Messaging (FCM) und Apple Push Notification Services (APNS)ein. Anschließend erstellen und konfigurieren Sie einen Benachrichtigungshub für die Arbeit mit diesen Diensten.

Erstellen eines Firebase-Projekts und Aktivieren von Firebase Cloud Messaging für Android

  1. Melden Sie sich bei der Firebase-Konsolean. Erstellen Sie ein neues Firebase-Projekt, das PushDemo- als Projektnameneingibt.

    Anmerkung

    Ein eindeutiger Name wird für Sie generiert. Standardmäßig besteht dies aus einer Kleinbuchstabenvariante des angegebenen Namens sowie einer generierten Zahl, die durch einen Gedankenstrich getrennt ist. Sie können dies ändern, wenn sie bereitgestellt werden soll, dass sie weiterhin global eindeutig ist.

  2. Nachdem Sie Ihr Projekt erstellt haben, wählen Sie "Firebase hinzufügen" zu Ihrer Android-Appaus.

    Hinzufügen von Firebase zu Ihrer Android-App

  3. Führen Sie auf der Seite Hinzufügen von Firebase zu Ihrer Android-App Seite die folgenden Schritte aus.

    1. Geben Sie für den Android-Paketnameneinen Namen für Ihr Paket ein. Beispiel: com.<organization_identifier>.<package_name>.

      Geben Sie den Paketnamen

    2. Wählen Sie App-registrieren aus.

    3. Wählen Sie Herunterladen google-services.jsonaus. Speichern Sie die Datei dann in einem lokalen Ordner, um sie später zu verwenden, und wählen Sie Nextaus.

      Herunterladen google-services.json

    4. Wählen Sie Nächstenaus.

    5. Wählen Sie Weiter zur Konsolen-

      Anmerkung

      Wenn die Schaltfläche Konsole fortsetzen nicht aktiviert ist, klicken Sie aufgrund der Überprüfung der Installation überprüfen, und wählen Sie Diesen Schritt überspringenaus.

  4. Wählen Sie in der Firebase-Konsole die Kopp für Ihr Projekt aus. Wählen Sie dann Projekteinstellungenaus.

    Anmerkung

    Wenn Sie die google-services.json Datei nicht heruntergeladen haben, können Sie sie auf dieser Seite herunterladen.

  5. Wechseln Sie oben zur Registerkarte Cloud Messaging. Kopieren Und speichern Sie den Serverschlüssel für die spätere Verwendung. Sie verwenden diesen Wert, um Ihren Benachrichtigungshub zu konfigurieren.

    Serverschlüssel kopieren

Registrieren Ihrer iOS-App für Pushbenachrichtigungen

Um Pushbenachrichtigungen an eine iOS-App zu senden, registrieren Sie Ihre Anwendung bei Apple, und registrieren Sie sich auch für Pushbenachrichtigungen.

  1. Wenn Sie Ihre App noch nicht registriert haben, navigieren Sie zum iOS-Bereitstellungsportal im Apple Developer Center. Melden Sie sich mit Ihrer Apple-ID beim Portal an, navigieren Sie zu Zertifikaten, Bezeichnern & Profilen, und wählen Sie dann Bezeichneraus. Klicken Sie auf +, um eine neue App zu registrieren.

    seite iOS-Bereitstellungsportal-App-IDs

  2. Wählen Sie auf dem Bildschirm Registrieren eines neuen Bezeichners die App-IDs Optionsfeld aus. Wählen Sie dann Weiteraus.

    iOS-Bereitstellungsportal registrieren neue ID-Seite

  3. Aktualisieren Sie die folgenden drei Werte für Ihre neue App, und wählen Sie dann Weiteraus:

    • Beschreibung: Geben Sie einen beschreibenden Namen für Ihre App ein.

    • Bundle-ID: Geben Sie eine Bundle-ID des Formulars com ein.<organization_identifier>.<product_name> wie im App-Verteilungshandbucherwähnt. Im folgenden Screenshot wird der mobcat Wert als Organisationsbezeichner verwendet, und der PushDemo- Wert wird als Produktname verwendet.

      App-ID-Seite des iOS-Bereitstellungsportals registrieren

    • Pushbenachrichtigungen: Überprüfen Sie die Option Pushbenachrichtigungen im Abschnitt Funktionen.

      Formular zum Registrieren einer neuen App-ID

      Diese Aktion generiert Ihre App-ID und fordert sie an, die Informationen zu bestätigen. Wählen Sie Weiteraus, und wählen Sie dann Registrieren aus, um die neue App-ID zu bestätigen.

      Neue App-ID bestätigen

      Nachdem Sie Registrierenausgewählt haben, wird die neue App-ID als Zeilenelement auf der Seite Zertifikate, Bezeichner & Profile Seite angezeigt.

  4. Suchen Sie auf der Seite Zertifikate bezeichner & Profile Seite unter Bezeichnernach dem von Ihnen erstellten Element der App-ID. Wählen Sie dann die Zeile aus, um den Bildschirm App-ID-Konfiguration bearbeiten Bildschirm anzuzeigen.

Erstellen eines Zertifikats für Benachrichtigungshubs

Ein Zertifikat ist erforderlich, damit der Benachrichtigungshub mit Apple Push Notification Services (APNS)- funktioniert und auf eine von zwei Arten bereitgestellt werden kann:

  1. Erstellen eines p12-Pushzertifikats, das direkt in den Notification Hub- hochgeladen werden kann (den ursprünglichen Ansatz)

  2. Erstellen eines p8-Zertifikats, das für die tokenbasierte Authentifizierung verwendet werden kann (den neueren und empfohlenen Ansatz)

Der neuere Ansatz bietet eine Reihe von Vorteilen, wie in Tokenbasierten Authentifizierung (HTTP/2) für APNS-dokumentiert. Es sind weniger Schritte erforderlich, aber auch für bestimmte Szenarien vorgeschrieben. Für beide Ansätze wurden jedoch Schritte bereitgestellt, da beide für die Zwecke dieses Lernprogramms funktionieren.

OPTION 1: Erstellen eines p12-Pushzertifikats, das direkt in den Notification Hub hochgeladen werden kann
  1. Führen Sie auf Ihrem Mac das Schlüsselbund-Access-Tool aus. Sie kann über den Ordner Dienstprogramme oder den Ordner Andere auf dem Launchpad geöffnet werden.

  2. Wählen Sie Schlüsselbundzugriffaus, erweitern Sie Zertifikat-Assistenten, und wählen Sie dann Zertifikat von einer Zertifizierungsstelleanfordern.

    Verwenden des Schlüsselbundzugriffs zum Anfordern eines neuen Zertifikats

    Anmerkung

    Standardmäßig wählt Access das erste Element in der Liste aus. Dies kann ein Problem sein, wenn Sie sich in der Kategorie Zertifikate befinden und Zertifizierungsstelle für Apple Worldwide Developer Relations nicht das erste Element in der Liste ist. Stellen Sie sicher, dass Sie über ein Nichtschlüsselelement oder die Apple Worldwide Developer Relations Zertifizierungsstelle Schlüssel ausgewählt ist, bevor Sie die CSR (Zertifikatsignierungsanforderung) generieren.

  3. Wählen Sie ihre Benutzer-E-Mail-Adresseaus, geben Sie Ihren Allgemeinen Namen Wert ein, stellen Sie sicher, dass Sie auf Datenträger gespeichertangeben, und wählen Sie dann Weiteraus. Lassen Sie E-Mail-Adresse der Zertifizierungsstelle leer, da sie nicht erforderlich ist.

    Erwartete Zertifikatinformationen

  4. Geben Sie einen Namen für die datei Zertifikatsignaturanforderung (CSR) in Speichern unterein, wählen Sie den Speicherort in Woaus, und wählen Sie dann Speichernaus.

    Wählen Sie einen Dateinamen für das Zertifikat

    Diese Aktion speichert die CSR-Datei am ausgewählten Speicherort. Der Standardspeicherort ist Desktop-. Denken Sie an den Speicherort, der für die Datei ausgewählt wurde.

  5. Zurück auf der Seite Zertifikate & Profile Seite im iOS-Bereitstellungsportalscrollen Sie nach unten zur aktivierten option Pushbenachrichtigungen, und wählen Sie dann Konfigurieren zum Erstellen des Zertifikats aus.

    Seite

  6. Das Fenster Apple Push Notification Service TLS/SSL-Zertifikate angezeigt. Wählen Sie die Schaltfläche Zertifikat erstellen unter dem Abschnitt Entwicklungs-TLS/SSL-Zertifikat aus.

    Schaltfläche

    Der Bildschirm Erstellen eines neuen Zertifikats wird angezeigt.

    Anmerkung

    In diesem Lernprogramm wird ein Entwicklungszertifikat verwendet. Derselbe Prozess wird beim Registrieren eines Produktionszertifikats verwendet. Stellen Sie einfach sicher, dass Sie beim Senden von Benachrichtigungen denselben Zertifikattyp verwenden.

  7. Wählen Sie Dateiauswählen, navigieren Sie zu dem Speicherort, an dem Sie die CSR-Dateigespeichert haben, und doppelklicken Sie dann auf den Zertifikatnamen, um sie zu laden. Wählen Sie dann Weiteraus.

  8. Nachdem das Portal das Zertifikat erstellt hat, wählen Sie die Schaltfläche Herunterladen aus. Speichern Sie das Zertifikat, und merken Sie sich den Speicherort, an dem es gespeichert ist.

    Generierte Zertifikatdownloadseite

    Das Zertifikat wird heruntergeladen und auf Ihrem Computer in Ihrem ordner "Downloads" gespeichert.

    Suchen der Zertifikatdatei im Ordner

    Anmerkung

    Standardmäßig heißt das heruntergeladene Entwicklungszertifikat aps_development.cer.

  9. Doppelklicken Sie auf das heruntergeladene Pushzertifikat aps_development.cer. Mit dieser Aktion wird das neue Zertifikat im Schlüsselbund installiert, wie in der folgenden Abbildung dargestellt:

    Liste der Schlüsselbundzugriffszertifikate mit neuen Zertifikaten

    Anmerkung

    Obwohl der Name in Ihrem Zertifikat möglicherweise anders ist, wird dem Namen Apple Development iOS Push Services vorangestellt und der entsprechende Bündelbezeichner zugeordnet.

  10. Klicken Sie im Schlüsselbundzugriff auf Steuerelement + Klicken Sie auf auf das neue Pushzertifikat, das Sie in der Kategorie Zertifikate erstellt haben. Wählen Sie Exportaus, benennen Sie die Datei, wählen Sie das p12--Format aus, und wählen Sie dann Speichernaus.

    Exportieren des Zertifikats als p12-Format

    Sie können das Zertifikat mit einem Kennwort schützen, aber ein Kennwort ist optional. Klicken Sie auf OK, wenn Sie die Kennworterstellung umgehen möchten. Notieren Sie sich den Dateinamen und speicherort des exportierten p12-Zertifikats. Sie werden verwendet, um die Authentifizierung mit APNs zu aktivieren.

    Anmerkung

    Ihr p12-Dateiname und -Speicherort unterscheiden sich möglicherweise von dem, was in diesem Lernprogramm dargestellt wird.

OPTION 2: Erstellen eines p8-Zertifikats, das für die tokenbasierte Authentifizierung verwendet werden kann
  1. Notieren Sie sich die folgenden Details:

    • App-ID-Präfix (Team-ID)
    • Bundle-ID
  2. Zurück in Zertifikaten, Bezeichner & Profile, klicken Sie auf Schlüssel.

    Anmerkung

    Wenn Sie bereits einen Schlüssel für APNS-konfiguriert haben, können Sie das p8-Zertifikat erneut verwenden, das Sie direkt nach der Erstellung heruntergeladen haben. Wenn ja, können Sie die Schritte 3 bis 5ignorieren.

  3. Klicken Sie auf die Schaltfläche + (oder auf die Schaltfläche Erstellen eines Schlüssels), um einen neuen Schlüssel zu erstellen.

  4. Geben Sie einen geeigneten Key Name Wert an, überprüfen Sie dann die Option Apple Push Notifications Service (APNS), und klicken Sie dann auf Weiter, gefolgt von Registrieren auf dem nächsten Bildschirm.

  5. Klicken Sie auf Download, und verschieben Sie dann die p8--Datei (vorangestellt mit AuthKey_) in ein sicheres lokales Verzeichnis, und klicken Sie dann auf Fertig.

    Anmerkung

    Achten Sie darauf, ihre p8-Datei an einem sicheren Ort zu speichern (und eine Sicherung zu speichern). Nach dem Herunterladen des Schlüssels kann er nicht erneut heruntergeladen werden, wenn die Serverkopie entfernt wird.

  6. Klicken Sie auf Tastenauf den von Ihnen erstellten Schlüssel (oder auf einen vorhandenen Schlüssel, wenn Sie stattdessen dies verwenden möchten).

  7. Notieren Sie sich den wert Key ID.

  8. Öffnen Sie Ihr p8-Zertifikat in einer geeigneten Anwendung Ihrer Wahl, z. B. Visual Studio Code. Notieren Sie sich den Schlüsselwert (zwischen -----BEGIN PRIVATE KEY----- und -----END PRIVATE KEY-----).

    -----BEGIN PRIVATE KEY-----
    <key_value>
    -----END PRIVATEN SCHLÜSSEL-----

    Anmerkung

    Dies ist der Tokenwert, der später verwendet wird, um Notification Hub-zu konfigurieren.

Am Ende dieser Schritte sollten Sie die folgenden Informationen zur späteren Verwendung in Konfigurieren Ihres Benachrichtigungshubs mit APNS-Informationenhaben:

  • Team-ID (siehe Schritt 1)
  • Bundle-ID (siehe Schritt 1)
  • Schlüssel-ID- (siehe Schritt 7)
  • Tokenwert (p8-Schlüsselwert, der in Schritt 8 abgerufen wurde)

Erstellen eines Bereitstellungsprofils für die App

  1. Kehren Sie zum iOS-Bereitstellungsportal, wählen Sie Zertifikate, Bezeichner & Profileaus, wählen Sie im linken Menü Profile aus, und wählen Sie dann + aus, um ein neues Profil zu erstellen. Der Bildschirm Registrieren eines neuen Bereitstellungsprofils angezeigt.

  2. Wählen Sie iOS App Development unter Development als Bereitstellungsprofiltyp aus, und wählen Sie dann Weiteraus.

    Bereitstellungsprofilliste

  3. Wählen Sie als Nächstes die App-ID aus, die Sie aus der Dropdownliste App-ID erstellt haben, und wählen Sie Weiteraus.

    Wählen Sie die App-ID

  4. Wählen Sie im Fenster Zertifikat auswählen das Entwicklungszertifikat aus, das Sie für die Codesignierung verwenden, und wählen Sie Weiteraus.

    Anmerkung

    Dieses Zertifikat ist nicht das Pushzertifikat, das Sie im vorherigen Schritterstellt haben. Dies ist Ihr Entwicklungszertifikat. Wenn eine nicht vorhanden ist, müssen Sie sie erstellen, da es sich um eine Voraussetzung für dieses Lernprogramm handelt. Entwicklerzertifikate können im Apple Developer Portalüber Xcode- oder in Visual Studio-erstellt werden.

  5. Kehren Sie zur Seite Zertifikate, Bezeichner & Profile Seite zurück, wählen Sie im linken Menü Profile aus, und wählen Sie dann + aus, um ein neues Profil zu erstellen. Der Bildschirm Registrieren eines neuen Bereitstellungsprofils angezeigt.

  6. Wählen Sie im Fenster Zertifikate auswählen das von Ihnen erstellte Entwicklungszertifikat aus. Wählen Sie dann Weiteraus.

  7. Wählen Sie als Nächstes die geräte aus, die zum Testen verwendet werden sollen, und wählen Sie Weiteraus.

  8. Wählen Sie schließlich einen Namen für das Profil in Bereitstellungsprofilnameaus, und wählen Sie Generierenaus.

    Auswählen eines Bereitstellungsprofilnamens

  9. Wenn das neue Bereitstellungsprofil erstellt wird, wählen Sie Herunterladenaus. Denken Sie an den Speicherort, an dem sie gespeichert ist.

  10. Navigieren Sie zum Speicherort des Bereitstellungsprofils, und doppelklicken Sie dann darauf, um es auf Ihrem Entwicklungscomputer zu installieren.

Erstellen eines Benachrichtigungshubs

In diesem Abschnitt erstellen Sie einen Benachrichtigungshub und konfigurieren die Authentifizierung mit APNS-. Sie können ein p12-Pushzertifikat oder eine tokenbasierte Authentifizierung verwenden. Wenn Sie einen Benachrichtigungshub verwenden möchten, den Sie bereits erstellt haben, können Sie mit Schritt 5 fortfahren.

  1. Melden Sie sich bei Azurean.

  2. Klicken Sie auf Erstellen einer Ressource, suchen Und wählen Sie Notification Hub-aus, und klicken Sie dann auf Erstellen.

  3. Aktualisieren Sie die folgenden Felder, und klicken Sie dann auf Erstellen:

    GRUNDLEGENDE DETAILS

    Abonnement: Wählen Sie das Ziel Abonnement- aus der Dropdownliste aus.
    Ressourcengruppe: Erstellen einer neuen Ressourcengruppe (oder Auswählen einer vorhandenen)

    NAMESPACEDETAILS

    Notification Hub-Namespace: Geben Sie einen global eindeutigen Namen für den Notification Hub Namespace ein.

    Anmerkung

    Stellen Sie sicher, dass für dieses Feld die Option "Neue erstellen" ausgewählt ist.

    NOTIFICATION HUB DETAILS

    Benachrichtigungshub: Geben Sie einen Namen für den Benachrichtigungshub-
    Speicherort: Wählen Sie einen geeigneten Speicherort aus der Dropdownliste aus.
    Preisstufe: Standardoption Kostenlos beibehalten

    Anmerkung

    Sofern Sie nicht die maximale Anzahl von Hubs auf der kostenlosen Ebene erreicht haben.

  4. Nachdem der Notification Hub bereitgestellt bereitgestellt wurde, navigieren Sie zu dieser Ressource.

  5. Navigieren Sie zum neuen Notification Hub-.

  6. Wählen Sie Zugriffsrichtlinien aus der Liste aus (unter VERWALTEN).

  7. Notieren Sie sich den Richtliniennamen Werte zusammen mit den entsprechenden Verbindungszeichenfolgen- Werten.

Konfigurieren des Benachrichtigungshubs mit APNS-Informationen

Wählen Sie unter Notification ServicesApple dann die entsprechenden Schritte basierend auf dem Ansatz aus, den Sie zuvor im Abschnitt Erstellen eines Zertifikats für Benachrichtigungshubs ausgewählt haben.

Anmerkung

Verwenden Sie die Production- nur für Anwendungsmodus, wenn Sie Pushbenachrichtigungen an Benutzer senden möchten, die Ihre App aus dem Store erworben haben.

OPTION 1: Verwenden eines P12-Pushzertifikats

  1. Wählen Sie Zertifikataus.

  2. Wählen Sie das Dateisymbol aus.

  3. Wählen Sie die P12-Datei aus, die Sie zuvor exportiert haben, und wählen Sie dann Öffnenaus.

  4. Geben Sie bei Bedarf das richtige Kennwort an.

  5. Wählen Sie Sandkastenmodus aus.

  6. Wählen Sie Speichernaus.

OPTION 2: Verwenden der tokenbasierten Authentifizierung

  1. Wählen Sie Token-aus.

  2. Geben Sie die folgenden Werte ein, die Sie zuvor erworben haben:

    • Schlüssel-ID-
    • Bundle-ID
    • Team-ID
    • Token-
  3. Wählen Sie Sandkasten-aus.

  4. Wählen Sie Speichernaus.

Konfigurieren Des Benachrichtigungshubs mit FCM-Informationen

  1. Wählen Sie Google (GCM/FCM) im Abschnitt Einstellungen im linken Menü aus.
  2. Geben Sie den Serverschlüssel ein, Sie aus der Google Firebase Consolenotiert haben.
  3. Wählen Sie Speichern auf der Symbolleiste aus.

Erstellen einer ASP.NET Core Web API-Back-End-Anwendung

In diesem Abschnitt erstellen Sie die ASP.NET Core Web API Back-End, um Geräteregistrierung und das Senden von Benachrichtigungen an die mobile Flutter-App zu verarbeiten.

Erstellen eines Webprojekts

  1. Wählen Sie in Visual StudioDatei>neue Projektmappeaus.

  2. Wählen Sie .NET Core>App>ASP.NET Core>API>Nextaus.

  3. Wählen Sie im Dialogfeld Konfigurieren der neuen ASP.NET Core Web APITarget Framework.NET Core 3.1aus.

  4. Geben Sie PushDemoApi- für den Projektnamen ein, und wählen Sie dann Erstellenaus.

  5. Starten Sie das Debuggen (Command + Enter), um die vorlagenbasierte App zu testen.

    Anmerkung

    Die vorlagenbasierte App ist so konfiguriert, dass die WeatherForecastController- als launchUrl-verwendet wird. Dies wird in Eigenschaften>launchSettings.jsonfestgelegt.

    Wenn Sie mit einem Ungültiges Entwicklungszertifikat aufgefordert werden, wurde Meldung gefunden:

    1. Klicken Sie auf Ja, um der Ausführung des Tools "dotnet dev-certs https" zuzustimmen, um dies zu beheben. Das Tool "dotnet dev-certs https" fordert Sie dann auf, ein Kennwort für das Zertifikat und das Kennwort für Ihren Schlüsselbund einzugeben.

    2. Klicken Sie auf Ja, wenn Sie aufgefordert werden, das neue Zertifikatzu installieren und als vertrauenswürdig einzustufen, und geben Sie dann das Kennwort für Ihren Schlüsselbund ein.

  6. Erweitern Sie den Ordner Controller, und löschen Sie dann WeatherForecastController.cs.

  7. WeatherForecast.cslöschen .

  8. Richten Sie lokale Konfigurationswerte mithilfe des Secret Manager-Toolsein. Durch das Decoupieren der geheimen Schlüssel aus der Lösung wird sichergestellt, dass sie nicht in der Quellcodeverwaltung enden. Öffnen Sie Terminal wechseln Sie dann zum Verzeichnis der Projektdatei, und führen Sie die folgenden Befehle aus:

    dotnet user-secrets init
    dotnet user-secrets set "NotificationHub:Name" <value>
    dotnet user-secrets set "NotificationHub:ConnectionString" <value>
    

    Ersetzen Sie die Platzhalterwerte durch Ihren eigenen Benachrichtigungshubnamen und Verbindungszeichenfolgenwerte. Sie haben im einen Benachrichtigungshub Abschnitt erstellt. Andernfalls können Sie sie in Azurenachschlagen.

    NotificationHub:Name:
    Siehe Name in der Zusammenfassung Essentials oben in Übersicht.

    NotificationHub:ConnectionString:
    Siehe DefaultFullSharedAccessSignature in Access Policies

    Anmerkung

    Für Produktionsszenarien können Sie Optionen wie Azure KeyVault- anzeigen, um die Verbindungszeichenfolge sicher zu speichern. Der Einfachheit halber werden die geheimen Schlüssel den Azure App Service Anwendungseinstellungen hinzugefügt.

Authentifizieren von Clients mit einem API-Schlüssel (optional)

API-Schlüssel sind nicht so sicher wie Token, reichen aber für die Zwecke dieses Lernprogramms aus. Ein API-Schlüssel kann einfach über die ASP.NET Middleware-konfiguriert werden.

  1. Fügen Sie den API-Schlüssel zu den lokalen Konfigurationswerten hinzu.

    dotnet user-secrets set "Authentication:ApiKey" <value>
    

    Anmerkung

    Sie sollten den Platzhalterwert durch Ihren eigenen ersetzen und eine Notiz davon machen.

  2. SteuerelementKlicken Sie im PushDemoApi- Projekt auf Klicken Sie im Menü Hinzufügen auf, und klicken Sie dann auf Hinzufügen mithilfe Authentifizierung als Ordnername.

  3. SteuerelementKlicken Sie im Ordner Authentifizierung auf, und wählen Sie dann im Menü " hinzufügen" "Neue Datei" aus.

  4. Wählen Sie Allgemeine>Leere Klasseaus, geben Sie ApiKeyAuthOptions.cs für den Namenein, und klicken Sie dann auf Neue Hinzufügen der folgenden Implementierung.

    using Microsoft.AspNetCore.Authentication;
    
    namespace PushDemoApi.Authentication
    {
        public class ApiKeyAuthOptions : AuthenticationSchemeOptions
        {
            public const string DefaultScheme = "ApiKey";
            public string Scheme => DefaultScheme;
            public string ApiKey { get; set; }
        }
    }
    
  5. Fügen Sie dem Ordner "ApiKeyAuthHandler.cs" eine weitere "Leere Klasse" hinzu, und fügen Sie dann die folgende Implementierung hinzu.

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Security.Claims;
    using System.Text.Encodings.Web;
    using System.Threading.Tasks;
    using Microsoft.AspNetCore.Authentication;
    using Microsoft.Extensions.Logging;
    using Microsoft.Extensions.Options;
    
    namespace PushDemoApi.Authentication
    {
        public class ApiKeyAuthHandler : AuthenticationHandler<ApiKeyAuthOptions>
        {
            const string ApiKeyIdentifier = "apikey";
    
            public ApiKeyAuthHandler(
                IOptionsMonitor<ApiKeyAuthOptions> options,
                ILoggerFactory logger,
                UrlEncoder encoder,
                ISystemClock clock)
                : base(options, logger, encoder, clock) {}
    
            protected override Task<AuthenticateResult> HandleAuthenticateAsync()
            {
                string key = string.Empty;
    
                if (Request.Headers[ApiKeyIdentifier].Any())
                {
                    key = Request.Headers[ApiKeyIdentifier].FirstOrDefault();
                }
                else if (Request.Query.ContainsKey(ApiKeyIdentifier))
                {
                    if (Request.Query.TryGetValue(ApiKeyIdentifier, out var queryKey))
                        key = queryKey;
                }
    
                if (string.IsNullOrWhiteSpace(key))
                    return Task.FromResult(AuthenticateResult.Fail("No api key provided"));
    
                if (!string.Equals(key, Options.ApiKey, StringComparison.Ordinal))
                    return Task.FromResult(AuthenticateResult.Fail("Invalid api key."));
    
                var identities = new List<ClaimsIdentity> {
                    new ClaimsIdentity("ApiKeyIdentity")
                };
    
                var ticket = new AuthenticationTicket(
                    new ClaimsPrincipal(identities), Options.Scheme);
    
                return Task.FromResult(AuthenticateResult.Success(ticket));
            }
        }
    }
    

    Anmerkung

    Ein Authentifizierungshandler ist ein Typ, der das Verhalten eines Schemas implementiert, in diesem Fall ein benutzerdefiniertes API-Schlüsselschema.

  6. Fügen Sie dem Ordner "ApiKeyAuthenticationBuilderExtensions.cs" eine weitere "Leere Klasse" hinzu, und fügen Sie dann die folgende Implementierung hinzu.

    using System;
    using Microsoft.AspNetCore.Authentication;
    
    namespace PushDemoApi.Authentication
    {
        public static class AuthenticationBuilderExtensions
        {
            public static AuthenticationBuilder AddApiKeyAuth(
                this AuthenticationBuilder builder,
                Action<ApiKeyAuthOptions> configureOptions)
            {
                return builder
                    .AddScheme<ApiKeyAuthOptions, ApiKeyAuthHandler>(
                        ApiKeyAuthOptions.DefaultScheme,
                        configureOptions);
            }
        }
    }
    

    Anmerkung

    Diese Erweiterungsmethode vereinfacht den Middleware-Konfigurationscode in Startup.cs die Lesbarkeit und im Allgemeinen einfacher zu verfolgen.

  7. Aktualisieren Sie in Startup.csdie ConfigureServices-Methode, um die API-Schlüsselauthentifizierung unter dem Aufruf der -Dienste zu konfigurieren. AddControllers Methode.

    using PushDemoApi.Authentication;
    using PushDemoApi.Models;
    using PushDemoApi.Services;
    
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddControllers();
    
        services.AddAuthentication(options =>
        {
            options.DefaultAuthenticateScheme = ApiKeyAuthOptions.DefaultScheme;
            options.DefaultChallengeScheme = ApiKeyAuthOptions.DefaultScheme;
        }).AddApiKeyAuth(Configuration.GetSection("Authentication").Bind);
    }
    
  8. Aktualisieren Sie in Startup.csdie Configure-Methode, um die UseAuthentication- und UseAuthorization- Erweiterungsmethoden für die IApplicationBuilder-der App aufzurufen. Stellen Sie sicher, dass diese Methoden nach UseRouting und vor App aufgerufen werden. UseEndpoints.

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
    
        app.UseHttpsRedirection();
    
        app.UseRouting();
    
        app.UseAuthentication();
    
        app.UseAuthorization();
    
        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllers();
        });
    }
    

    Anmerkung

    Durch Aufrufen UseAuthentication wird die Middleware registriert, die die zuvor registrierten Authentifizierungsschemas verwendet (von ConfigureServices). Dies muss vor jeder Middleware aufgerufen werden, die von authentifizierten Benutzern abhängt.

Hinzufügen von Abhängigkeiten und Konfigurieren von Diensten

ASP.NET Core unterstützt das Abhängigkeitsinjektion (DI) Softwaredesignmuster, das eine Technik zum Erreichen Inversion of Control (IoC) zwischen Klassen und deren Abhängigkeiten ist.

Die Verwendung des Benachrichtigungshubs und des Notification Hubs SDK für Back-End-Vorgänge in einem Dienst gekapselt wird. Der Service wird registriert und durch eine geeignete Abstraktion zur Verfügung gestellt.

  1. Steuerelement + Klicken Sie im Ordner Abhängigkeiten auf, und wählen Sie dann NuGet-Pakete verwalten...aus.

  2. Suchen Sie nach Microsoft.Azure.NotificationHubs, und stellen Sie sicher, dass sie aktiviert ist.

  3. Klicken Sie auf Paketehinzufügen, und klicken Sie dann auf Akzeptieren, wenn Sie aufgefordert werden, die Lizenzbedingungen zu akzeptieren.

  4. SteuerelementKlicken Sie im projekt PushDemoApi auf klicken, wählen Sie im Menü Ordner hinzufügen Neuen Ordner aus, und klicken Sie dann auf Hinzufügen mithilfe Modelle als Ordnername.

  5. Steuerelement + Klicken Sie im Ordner Modelle auf, und wählen Sie dann Neue Datei... aus dem Menü Hinzufügen aus.

  6. Wählen Sie Allgemeine>Leere Klasseaus, geben Sie PushTemplates.cs für den Namenein, und klicken Sie dann auf Neue die folgende Implementierung hinzuzufügen.

    namespace PushDemoApi.Models
    {
        public class PushTemplates
        {
            public class Generic
            {
                public const string Android = "{ \"notification\": { \"title\" : \"PushDemo\", \"body\" : \"$(alertMessage)\"}, \"data\" : { \"action\" : \"$(alertAction)\" } }";
                public const string iOS = "{ \"aps\" : {\"alert\" : \"$(alertMessage)\"}, \"action\" : \"$(alertAction)\" }";
            }
    
            public class Silent
            {
                public const string Android = "{ \"data\" : {\"message\" : \"$(alertMessage)\", \"action\" : \"$(alertAction)\"} }";
                public const string iOS = "{ \"aps\" : {\"content-available\" : 1, \"apns-priority\": 5, \"sound\" : \"\", \"badge\" : 0}, \"message\" : \"$(alertMessage)\", \"action\" : \"$(alertAction)\" }";
            }
        }
    }
    

    Anmerkung

    Diese Klasse enthält die tokenisierten Benachrichtigungsnutzlasten für die generischen und automatischen Benachrichtigungen, die in diesem Szenario erforderlich sind. Die Nutzlasten werden außerhalb des Installation definiert, um Experimenten zu ermöglichen, ohne vorhandene Installationen über den Dienst aktualisieren zu müssen. Die Behandlung von Änderungen an Installationen auf diese Weise liegt außerhalb des Umfangs für dieses Lernprogramm. Berücksichtigen Sie für die Produktion benutzerdefinierte Vorlagen.

  7. Fügen Sie dem Ordner "DeviceInstallation.cs" eine weitere leere Klasse hinzu, und fügen Sie dann die folgende Implementierung hinzu.

    using System.Collections.Generic;
    using System.ComponentModel.DataAnnotations;
    
    namespace PushDemoApi.Models
    {
        public class DeviceInstallation
        {
            [Required]
            public string InstallationId { get; set; }
    
            [Required]
            public string Platform { get; set; }
    
            [Required]
            public string PushChannel { get; set; }
    
            public IList<string> Tags { get; set; } = Array.Empty<string>();
        }
    }
    
  8. Fügen Sie dem Ordner Models ordner "NotificationRequest.cs" weitere "Empty Class" hinzu, und fügen Sie dann die folgende Implementierung hinzu.

    using System;
    
    namespace PushDemoApi.Models
    {
        public class NotificationRequest
        {
            public string Text { get; set; }
            public string Action { get; set; }
            public string[] Tags { get; set; } = Array.Empty<string>();
            public bool Silent { get; set; }
        }
    }
    
  9. Fügen Sie dem Ordner Models Ordner mit dem Namen NotificationHubOptions.csweitere leere Klasse hinzu, und fügen Sie dann die folgende Implementierung hinzu.

    using System.ComponentModel.DataAnnotations;
    
    namespace PushDemoApi.Models
    {
        public class NotificationHubOptions
        {
            [Required]
            public string Name { get; set; }
    
            [Required]
            public string ConnectionString { get; set; }
        }
    }
    
  10. Fügen Sie dem PushDemoApi Projekt namens Serviceseinen neuen Ordner hinzu.

  11. Fügen Sie eine leere Schnittstelle zum Ordner Services namens INotificationService.cshinzu, und fügen Sie dann die folgende Implementierung hinzu.

    using System.Threading;
    using System.Threading.Tasks;
    using PushDemoApi.Models;
    
    namespace PushDemoApi.Services
    {
        public interface INotificationService
        {
            Task<bool> CreateOrUpdateInstallationAsync(DeviceInstallation deviceInstallation, CancellationToken token);
            Task<bool> DeleteInstallationByIdAsync(string installationId, CancellationToken token);
            Task<bool> RequestNotificationAsync(NotificationRequest notificationRequest, CancellationToken token);
        }
    }
    
  12. Fügen Sie dem NotificationHubsService.csOrdner "" eine "Leere Klasse" hinzu, und fügen Sie dann den folgenden Code hinzu, um die INotificationService--Schnittstelle zu implementieren:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading;
    using System.Threading.Tasks;
    using Microsoft.Azure.NotificationHubs;
    using Microsoft.Extensions.Logging;
    using Microsoft.Extensions.Options;
    using PushDemoApi.Models;
    
    namespace PushDemoApi.Services
    {
        public class NotificationHubService : INotificationService
        {
            readonly NotificationHubClient _hub;
            readonly Dictionary<string, NotificationPlatform> _installationPlatform;
            readonly ILogger<NotificationHubService> _logger;
    
            public NotificationHubService(IOptions<NotificationHubOptions> options, ILogger<NotificationHubService> logger)
            {
                _logger = logger;
                _hub = NotificationHubClient.CreateClientFromConnectionString(
                    options.Value.ConnectionString,
                    options.Value.Name);
    
                _installationPlatform = new Dictionary<string, NotificationPlatform>
                {
                    { nameof(NotificationPlatform.Apns).ToLower(), NotificationPlatform.Apns },
                    { nameof(NotificationPlatform.Fcm).ToLower(), NotificationPlatform.Fcm }
                };
            }
    
            public async Task<bool> CreateOrUpdateInstallationAsync(DeviceInstallation deviceInstallation, CancellationToken token)
            {
                if (string.IsNullOrWhiteSpace(deviceInstallation?.InstallationId) ||
                    string.IsNullOrWhiteSpace(deviceInstallation?.Platform) ||
                    string.IsNullOrWhiteSpace(deviceInstallation?.PushChannel))
                    return false;
    
                var installation = new Installation()
                {
                    InstallationId = deviceInstallation.InstallationId,
                    PushChannel = deviceInstallation.PushChannel,
                    Tags = deviceInstallation.Tags
                };
    
                if (_installationPlatform.TryGetValue(deviceInstallation.Platform, out var platform))
                    installation.Platform = platform;
                else
                    return false;
    
                try
                {
                    await _hub.CreateOrUpdateInstallationAsync(installation, token);
                }
                catch
                {
                    return false;
                }
    
                return true;
            }
    
            public async Task<bool> DeleteInstallationByIdAsync(string installationId, CancellationToken token)
            {
                if (string.IsNullOrWhiteSpace(installationId))
                    return false;
    
                try
                {
                    await _hub.DeleteInstallationAsync(installationId, token);
                }
                catch
                {
                    return false;
                }
    
                return true;
            }
    
            public async Task<bool> RequestNotificationAsync(NotificationRequest notificationRequest, CancellationToken token)
            {
                if ((notificationRequest.Silent &&
                    string.IsNullOrWhiteSpace(notificationRequest?.Action)) ||
                    (!notificationRequest.Silent &&
                    (string.IsNullOrWhiteSpace(notificationRequest?.Text)) ||
                    string.IsNullOrWhiteSpace(notificationRequest?.Action)))
                    return false;
    
                var androidPushTemplate = notificationRequest.Silent ?
                    PushTemplates.Silent.Android :
                    PushTemplates.Generic.Android;
    
                var iOSPushTemplate = notificationRequest.Silent ?
                    PushTemplates.Silent.iOS :
                    PushTemplates.Generic.iOS;
    
                var androidPayload = PrepareNotificationPayload(
                    androidPushTemplate,
                    notificationRequest.Text,
                    notificationRequest.Action);
    
                var iOSPayload = PrepareNotificationPayload(
                    iOSPushTemplate,
                    notificationRequest.Text,
                    notificationRequest.Action);
    
                try
                {
                    if (notificationRequest.Tags.Length == 0)
                    {
                        // This will broadcast to all users registered in the notification hub
                        await SendPlatformNotificationsAsync(androidPayload, iOSPayload, token);
                    }
                    else if (notificationRequest.Tags.Length <= 20)
                    {
                        await SendPlatformNotificationsAsync(androidPayload, iOSPayload, notificationRequest.Tags, token);
                    }
                    else
                    {
                        var notificationTasks = notificationRequest.Tags
                            .Select((value, index) => (value, index))
                            .GroupBy(g => g.index / 20, i => i.value)
                            .Select(tags => SendPlatformNotificationsAsync(androidPayload, iOSPayload, tags, token));
    
                        await Task.WhenAll(notificationTasks);
                    }
    
                    return true;
                }
                catch (Exception e)
                {
                    _logger.LogError(e, "Unexpected error sending notification");
                    return false;
                }
            }
    
            string PrepareNotificationPayload(string template, string text, string action) => template
                .Replace("$(alertMessage)", text, StringComparison.InvariantCulture)
                .Replace("$(alertAction)", action, StringComparison.InvariantCulture);
    
            Task SendPlatformNotificationsAsync(string androidPayload, string iOSPayload, CancellationToken token)
            {
                var sendTasks = new Task[]
                {
                    _hub.SendFcmNativeNotificationAsync(androidPayload, token),
                    _hub.SendAppleNativeNotificationAsync(iOSPayload, token)
                };
    
                return Task.WhenAll(sendTasks);
            }
    
            Task SendPlatformNotificationsAsync(string androidPayload, string iOSPayload, IEnumerable<string> tags, CancellationToken token)
            {
                var sendTasks = new Task[]
                {
                    _hub.SendFcmNativeNotificationAsync(androidPayload, tags, token),
                    _hub.SendAppleNativeNotificationAsync(iOSPayload, tags, token)
                };
    
                return Task.WhenAll(sendTasks);
            }
        }
    }
    

    Anmerkung

    Der Tagausdruck, der für SendTemplateNotificationAsync- bereitgestellt wird, ist auf 20 Tags beschränkt. Er ist für die meisten Operatoren auf 6 beschränkt, der Ausdruck enthält jedoch nur ORs (||) in diesem Fall. Wenn in der Anforderung mehr als 20 Tags vorhanden sind, müssen sie in mehrere Anforderungen aufgeteilt werden. Weitere Details finden Sie in der Dokumentation Routing- und Tagausdrücke.

  13. Aktualisieren Sie in Startup.csdie ConfigureServices-Methode, um die NotificationHubsService- als Singletonimplementierung von INotificationServicehinzuzufügen.

    
    using PushDemoApi.Models;
    using PushDemoApi.Services;
    
    public void ConfigureServices(IServiceCollection services)
    {
        ...
    
        services.AddSingleton<INotificationService, NotificationHubService>();
    
        services.AddOptions<NotificationHubOptions>()
            .Configure(Configuration.GetSection("NotificationHub").Bind)
            .ValidateDataAnnotations();
    }
    

Erstellen der Benachrichtigungs-API

  1. SteuerelementKlicken Sie im Ordner Controller auf, und wählen Sie dann im Menü Hinzufügen neue Datei aus.

  2. Wählen Sie ASP.NET Core>Web API Controller-Klasseaus, geben Sie NotificationsController- für den Namenein, und klicken Sie dann auf Neue.

    Anmerkung

    Wenn Sie mit Visual Studio 2019folgen, wählen Sie den API Controller mit Lese-/Schreibaktionen Vorlage aus.

  3. Fügen Sie die folgenden Namespaces am Anfang der Datei hinzu.

    using System.ComponentModel.DataAnnotations;
    using System.Net;
    using System.Threading;
    using System.Threading.Tasks;
    using Microsoft.AspNetCore.Authorization;
    using Microsoft.AspNetCore.Mvc;
    using PushDemoApi.Models;
    using PushDemoApi.Services;
    
  4. Aktualisieren Sie den vorlagenbasierten Controller so, dass er von ControllerBase abgeleitet wird und mit dem ApiController-Attribut versehen ist.

    [ApiController]
    [Route("api/[controller]")]
    public class NotificationsController : ControllerBase
    {
        // Templated methods here
    }
    

    Anmerkung

    Die Controller Basisklasse bietet Unterstützung für Ansichten, dies ist jedoch in diesem Fall nicht erforderlich, sodass ControllerBase- stattdessen verwendet werden kann. Wenn Sie mit Visual Studio 2019folgen, können Sie diesen Schritt überspringen.

  5. Wenn Sie sich entschieden haben, die Authentifizieren von Clients mit einem API-Schlüssel Abschnitt abzuschließen, sollten Sie auch den NotificationsController- mit dem Attribut Authorize versehen.

    [Authorize]
    
  6. Aktualisieren Sie den Konstruktor so, dass die registrierte Instanz von INotificationService als Argument akzeptiert wird, und weisen Sie ihn einem readonly-Element zu.

    readonly INotificationService _notificationService;
    
    public NotificationsController(INotificationService notificationService)
    {
        _notificationService = notificationService;
    }
    
  7. Ändern Sie in launchSettings.json (im Ordner Eigenschaften Ordner) die launchUrl- von weatherforecast in API/Benachrichtigungen so, dass sie mit der url übereinstimmen, die im RegistrationsControllerRoute Attribut angegeben ist.

  8. Starten Sie das Debuggen (Command + Enter), um zu überprüfen, ob die App mit dem neuen NotificationsController- arbeitet und einen 401 Nicht autorisiert Status zurückgibt.

    Anmerkung

    Visual Studio startet die App möglicherweise nicht automatisch im Browser. Sie verwenden Postman-, um die API ab diesem Zeitpunkt zu testen.

  9. Legen Sie auf einer neuen Registerkarte Postman die Anforderung auf GET-fest. Geben Sie die folgende Adresse ein, indem Sie den Platzhalter <applicationUrl> durch die https-applicationUrl- ersetzen, die in Eigenschaften>launchSettings.jsongefunden wurde.

    <applicationUrl>/api/notifications
    

    Anmerkung

    Die applicationUrl- sollte für das Standardprofil "https://localhost:5001" sein. Wenn Sie IIS- verwenden (Standardeinstellung in Visual Studio 2019- unter Windows), sollten Sie stattdessen die applicationUrl- verwenden, die im iisSettings- Element angegeben ist. Sie erhalten eine 404-Antwort, wenn die Adresse falsch ist.

  10. Wenn Sie sich entschieden haben, die Authentifizieren von Clients mit einem API-Schlüssel Abschnitt abzuschließen, müssen Sie die Anforderungsheader so konfigurieren, dass ihr apikey Wert enthalten ist.

    Schlüssel Wert
    apikey <your_api_key>
  11. Klicken Sie auf die Schaltfläche senden.

    Anmerkung

    Sie sollten einen 200 OK Status mit einigen JSON- Inhalt erhalten.

    Wenn Sie eine SSL-Zertifikatüberprüfung Warnung erhalten, können Sie die Anforderungs-SSL-Zertifikatüberprüfung Postman einstellung in den Einstellungenwechseln.

  12. Ersetzen Sie die vorlagenbasierten Klassenmethoden in NotificationsController.cs durch den folgenden Code.

    [HttpPut]
    [Route("installations")]
    [ProducesResponseType((int)HttpStatusCode.OK)]
    [ProducesResponseType((int)HttpStatusCode.BadRequest)]
    [ProducesResponseType((int)HttpStatusCode.UnprocessableEntity)]
    public async Task<IActionResult> UpdateInstallation(
        [Required]DeviceInstallation deviceInstallation)
    {
        var success = await _notificationService
            .CreateOrUpdateInstallationAsync(deviceInstallation, HttpContext.RequestAborted);
    
        if (!success)
            return new UnprocessableEntityResult();
    
        return new OkResult();
    }
    
    [HttpDelete()]
    [Route("installations/{installationId}")]
    [ProducesResponseType((int)HttpStatusCode.OK)]
    [ProducesResponseType((int)HttpStatusCode.BadRequest)]
    [ProducesResponseType((int)HttpStatusCode.UnprocessableEntity)]
    public async Task<ActionResult> DeleteInstallation(
        [Required][FromRoute]string installationId)
    {
        var success = await _notificationService
            .DeleteInstallationByIdAsync(installationId, CancellationToken.None);
    
        if (!success)
            return new UnprocessableEntityResult();
    
        return new OkResult();
    }
    
    [HttpPost]
    [Route("requests")]
    [ProducesResponseType((int)HttpStatusCode.OK)]
    [ProducesResponseType((int)HttpStatusCode.BadRequest)]
    [ProducesResponseType((int)HttpStatusCode.UnprocessableEntity)]
    public async Task<IActionResult> RequestPush(
        [Required]NotificationRequest notificationRequest)
    {
        if ((notificationRequest.Silent &&
            string.IsNullOrWhiteSpace(notificationRequest?.Action)) ||
            (!notificationRequest.Silent &&
            string.IsNullOrWhiteSpace(notificationRequest?.Text)))
            return new BadRequestResult();
    
        var success = await _notificationService
            .RequestNotificationAsync(notificationRequest, HttpContext.RequestAborted);
    
        if (!success)
            return new UnprocessableEntityResult();
    
        return new OkResult();
    }
    

Erstellen der API-App

Sie erstellen nun eine -API-App- in Azure App Service zum Hosten des Back-End-Diensts.

  1. Melden Sie sich beim Azure-Portalan.

  2. Klicken Sie auf Erstellen einer Ressource, suchen Und wählen Sie API-App-aus, und klicken Sie dann auf Erstellen.

  3. Aktualisieren Sie die folgenden Felder, und klicken Sie dann auf Erstellen.

    App-Name:
    Geben Sie einen global eindeutigen Namen für die -API-App- ein.

    -Abonnement:
    Wählen Sie dasselbe Ziel Abonnement Sie den Benachrichtigungshub erstellt haben.

    Ressourcengruppe:
    Wählen Sie dieselbe Ressourcengruppe aus, Sie den Benachrichtigungshub erstellt haben.

    App Service Plan/Standort:
    Erstellen eines neuen App Service Plan

    Anmerkung

    Wechseln Sie von der Standardoption zu einem Plan, der SSL--Unterstützung enthält. Andernfalls müssen Sie beim Arbeiten mit der mobilen App die entsprechenden Schritte ausführen, um zu verhindern, dass http- Anforderungen blockiert werden.

    Application Insights:
    Behalten Sie die vorgeschlagene Option bei (eine neue Ressource wird mit diesem Namen erstellt), oder wählen Sie eine vorhandene Ressource aus.

  4. Nachdem die -API-App bereitgestellt wurde, navigieren Sie zu dieser Ressource.

  5. Notieren Sie sich die eigenschaft URL in der Zusammenfassung Essentials oben im Overview. Diese URL ist Ihr Back-End-Endpunkt, der später in diesem Lernprogramm verwendet wird.

    Anmerkung

    Die URL verwendet den API-App-Namen, den Sie zuvor angegeben haben, mit dem Format https://<app_name>.azurewebsites.net.

  6. Wählen Sie Konfigurations- aus der Liste aus (unter Einstellungen).

  7. Klicken Sie für jede der folgenden Einstellungen auf Neue Anwendungseinstellung, um den Namen und einen Werteinzugeben, und klicken Sie dann auf OK.

    Name Wert
    Authentication:ApiKey <api_key_value>
    NotificationHub:Name <hub_name_value>
    NotificationHub:ConnectionString <hub_connection_string_value>

    Anmerkung

    Dies sind die gleichen Einstellungen, die Sie zuvor in den Benutzereinstellungen definiert haben. Sie sollten diese kopieren können. Die einstellung Authentication:ApiKey ist nur erforderlich, wenn Sie die Authentifizieren von Clients mit einem API-Schlüssel Abschnitt abgeschlossen haben. Für Produktionsszenarien können Sie Optionen wie Azure KeyVault-anzeigen. Diese wurden in diesem Fall als Anwendungseinstellungen hinzugefügt.

  8. Nachdem alle Anwendungseinstellungen hinzugefügt wurden, klicken Sie auf Speichern, und Weiter.

Veröffentlichen des Back-End-Diensts

Als Nächstes stellen Sie die App in der API-App bereit, um sie von allen Geräten aus zugänglich zu machen.

Anmerkung

Die folgenden Schritte sind spezifisch für Visual Studio für Mac. Wenn Sie mit Visual Studio 2019 unter Windows folgen, unterscheidet sich der Veröffentlichungsfluss. Siehe Veröffentlichen in Azure App Service unter Windows.

  1. Ändern Sie Ihre Konfiguration von Debug- in Release-, sofern dies noch nicht geschehen ist.

  2. Steuerelement + Klicken Sie auf das PushDemoApi- Projekt, und wählen Sie dann im Menü VeröffentlichenIn Azure veröffentlichen... aus.

  3. Folgen Sie dem Authentifizierungsfluss, wenn Sie dazu aufgefordert werden. Verwenden Sie das Konto, das Sie im vorherigen zum Erstellen des Abschnitts "API-App" verwendet haben.

  4. Wählen Sie die Azure App Service-API-App aus, die Sie zuvor in der Liste als Veröffentlichungsziel erstellt haben, und klicken Sie dann auf Veröffentlichen.

Nachdem Sie den Assistenten abgeschlossen haben, veröffentlicht er die App in Azure und öffnet dann die App. Notieren Sie sich die -URL, falls dies noch nicht geschehen ist. Diese URL ist Ihr Back-End-Endpunkt, das weiter unten in diesem Lernprogramm verwendet wird.

Überprüfen der veröffentlichten API

  1. Legen Sie in Postman eine neue Registerkarte öffnen, legen Sie die Anforderung auf PUT- fest, und geben Sie die folgende Adresse ein. Ersetzen Sie den Platzhalter durch die Basisadresse, die Sie im vorherigen Veröffentlichen des Back-End-Diensts Abschnitt vorgenommen haben.

    https://<app_name>.azurewebsites.net/api/notifications/installations
    

    Anmerkung

    Die Basisadresse sollte im Format https://<app_name>.azurewebsites.net/

  2. Wenn Sie sich entschieden haben, die Authentifizieren von Clients mit einem API-Schlüssel Abschnitt abzuschließen, müssen Sie die Anforderungsheader so konfigurieren, dass ihr apikey Wert enthalten ist.

    Schlüssel Wert
    apikey <your_api_key>
  3. Wählen Sie die Option unformatierten für den Bodyaus, und wählen Sie dann JSON- aus der Liste der Formatoptionen aus, und fügen Sie dann einen Platzhalter JSON- Inhalt ein:

    {}
    
  4. Klicken Sie auf senden.

    Anmerkung

    Sie sollten einen 422 UnprocessableEntity Status des Diensts erhalten.

  5. Führen Sie die Schritte 1 bis 4 erneut aus, aber dieses Mal geben Sie den Anforderungsendpunkt an, um zu überprüfen, dass Sie eine 400 Ungültige Anforderung Antwort erhalten.

    https://<app_name>.azurewebsites.net/api/notifications/requests
    

Anmerkung

Es ist noch nicht möglich, die API mit gültigen Anforderungsdaten zu testen, da dies plattformspezifische Informationen aus der mobilen Client-App erfordert.

Erstellen einer plattformübergreifenden Flutteranwendung

In diesem Abschnitt erstellen Sie eine Flutter mobile Anwendung, die Pushbenachrichtigungen plattformübergreifend implementiert.

Damit können Sie sich über den von Ihnen erstellten Back-End-Dienst von einem Benachrichtigungshub registrieren und abmelden.

Eine Warnung wird angezeigt, wenn eine Aktion angegeben wird und sich die App im Vordergrund befindet. Andernfalls werden Benachrichtigungen im Benachrichtigungscenter angezeigt.

Anmerkung

Normalerweise führen Sie die Registrierungsaktionen (und Die Registrierung) während des entsprechenden Zeitpunkts im Anwendungslebenszyklus (oder als Teil der Ersten Ausführungserfahrung möglicherweise) ohne explizite Benutzerregistrierungs-/Registrierungseingaben durch. Dieses Beispiel erfordert jedoch explizite Benutzereingaben, damit diese Funktionalität einfacher untersucht und getestet werden kann.

Erstellen der Flutterlösung

  1. Öffnen Sie eine neue Instanz von Visual Studio Code.

  2. Öffnen Sie die Befehlspalette (Umschalttaste + Befehl + P).

  3. Wählen Sie den Befehl Flutter: Neues Projekt aus, und drücken Sie dann EINGABETASTE.

  4. Geben Sie push_demo für den Projektnamen ein, und wählen Sie dann einen Projektspeicherortaus.

  5. Wenn Sie dazu aufgefordert werden, wählen Sie Get Packagesaus.

  6. Steuerelement- + Klicken Sie auf im ordner kotlin (unter App>src>Haupt-), und wählen Sie dann Einblendung in Finderaus. Benennen Sie dann die untergeordneten Ordner (unter dem ordner kotlin) in com, <your_organization>und pushdemo um.

    Anmerkung

    Wenn Sie die Vorlage Visual Studio Code verwenden, werden diese Ordner standardmäßig auf com-, Beispiel, <project_name>. Vorausgesetzt, Mobcat für die Organisationverwendet wird, sollte die Ordnerstruktur indikativ erscheinen als:

    • kotlin
      • COM
        • Mobcat
          • pushdemo
  7. Aktualisieren Sie zurück in Visual Studio Codeden wert applicationId in Android>App>build.gradle auf com.<your_organization>.pushdemo.

    Anmerkung

    Sie sollten Ihren eigenen Organisationsnamen für den Platzhalter <your_organization> verwenden. Wenn Sie z. B. mobcat verwenden, da die Organisation einen Paketnamen Wert von com.mobcat.pushdemo.

  8. Aktualisieren Sie das Paket--Attribut in den AndroidManifest.xml Dateien unter src>Debug-, src>Haupt-und src>Profil. Stellen Sie sicher, dass die Werte mit der applicationId übereinstimmen, Sie im vorherigen Schritt verwendet haben.

    <manifest
        xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.<your_organization>.pushdemo>">
        ...
    </manifest>
    
  9. Aktualisieren Sie das android:label Attribut in der AndroidManifest.xml Datei unter src>Haupt- auf PushDemo-. Fügen Sie dann das attribut android:allowBackup direkt unter android:labelhinzu, indem Sie dessen Wert auf falsefestlegen.

    <application
        android:name="io.flutter.app.FlutterApplication"
        android:label="PushDemo"
        android:allowBackup="false"
        android:icon="@mipmap/ic_launcher">
        ...
    </application>
    
  10. Öffnen Sie die Datei "build.gradle" auf App-Ebene Datei (Android>App>build.gradle), und aktualisieren Sie dann die compileSdkVersion (aus dem Abschnitt android), um API 29zu verwenden. Aktualisieren Sie dann die werte minSdkVersion und targetSdkVersion (aus dem Abschnitt defaultConfig), auf 26 bzw. 29.

    Anmerkung

    Nur die Geräte, auf denen API-Ebene 26 und höher ausgeführt werden, werden für die Zwecke dieses Lernprogramms unterstützt. Sie können sie jedoch erweitern, um Geräte mit älteren Versionen zu unterstützen.

  11. Steuerelement + Klicken Sie im Ordner ios auf, und wählen Sie dann In Xcode öffnenaus.

  12. Klicken Sie in Xcode-auf Runner (die xcodeproj oben, nicht auf den Ordner). Wählen Sie dann das ziel Runner und dann die Registerkarte Allgemein aus. Aktualisieren Sie bei ausgewählter Alle Buildkonfiguration die Bundle-ID auf com.<your_organization>.PushDemo.

    Anmerkung

    Sie sollten Ihren eigenen Organisationsnamen für den Platzhalter <your_organization> verwenden. Wenn Sie z. B. mobcat verwenden, da die Organisation einen Bundle Identifier Wert von com.mobcat.PushDemo.

  13. Klicken Sie auf Info.plist aktualisieren Sie dann den Bundle-Namen Wert auf PushDemo-

  14. Schließen Sie Xcode-, und kehren Sie zu Visual Studio Codezurück.

  15. Zurück in Visual Studio Codeöffnen Sie pubspec.yaml, fügen Sie die http- und flutter_secure_storageDart-Pakete als Abhängigkeiten hinzu. Speichern Sie dann die Datei, und klicken Sie auf Pakete abrufen, wenn Sie dazu aufgefordert werden.

    dependencies:
      flutter:
        sdk: flutter
    
      http: ^0.12.1
      flutter_secure_storage: ^3.3.3
    
  16. Ändern Sie in Terminaldas Verzeichnis in den Ordner ios (für Ihr Flutterprojekt). Führen Sie dann den Pod install Befehl aus, um neue Pods zu installieren (erforderlich für das flutter_secure_storage-Paket).

  17. control + Click on the lib folder, then choose New File from the menu using main_page.dart as the filename. Fügen Sie dann den folgenden Code hinzu.

    import 'package:flutter/material.dart';
    
    class MainPage extends StatefulWidget {
      @override
      _MainPageState createState() => _MainPageState();
    }
    
    class _MainPageState extends State<MainPage> {
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          body: SafeArea(
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.stretch,
              children: <Widget>[],
            )
          )
        );
      }
    }
    
  18. Ersetzen Sie in main.dartden vorlagenbasierten Code durch Folgendes.

    import 'package:flutter/material.dart';
    import 'package:push_demo/main_page.dart';
    
    final navigatorKey = GlobalKey<NavigatorState>();
    
    void main() => runApp(MaterialApp(home: MainPage(), navigatorKey: navigatorKey));
    
  19. Erstellen Sie in Terminal-die App auf jeder Zielplattform, und führen Sie sie aus, um die App mit Vorlagen zu testen, die auf Ihren Geräten ausgeführt wird. Stellen Sie sicher, dass unterstützte Geräte verbunden sind.

    flutter run
    

Implementieren der plattformübergreifenden Komponenten

  1. Steuerelement + Klicken Sie auf in der Lib Ordner, und wählen Sie Neuen Ordner aus dem Menü aus, indem Sie Modelle als Ordnernamen.

  2. ControlKlicken Sie auf im ordner Modelle, und wählen Sie dann im Menü neue Datei aus, indem Sie device_installation.dart als Dateinamen verwenden. Fügen Sie dann den folgenden Code hinzu.

    class DeviceInstallation {
        final String deviceId;
        final String platform;
        final String token;
        final List<String> tags;
    
        DeviceInstallation(this.deviceId, this.platform, this.token, this.tags);
    
        DeviceInstallation.fromJson(Map<String, dynamic> json)
          : deviceId = json['installationId'],
            platform = json['platform'],
            token = json['pushChannel'],
            tags = json['tags'];
    
        Map<String, dynamic> toJson() =>
        {
          'installationId': deviceId,
          'platform': platform,
          'pushChannel': token,
          'tags': tags,
        };
    }
    
  3. Fügen Sie der Modelle eine neue Datei hinzu, Ordner mit dem Namen push_demo_action.dart definieren, welche Enumeration von Aktionen in diesem Beispiel unterstützt wird.

    enum PushDemoAction {
      actionA,
      actionB,
    }
    
  4. Fügen Sie dem Projekt einen neuen Ordner namens Services hinzu, fügen Sie dann mit der folgenden Implementierung eine neue Datei zu diesem Ordner namens device_installation_service.dart hinzu.

    import 'package:flutter/services.dart';
    
    class DeviceInstallationService {
      static const deviceInstallation = const MethodChannel('com.<your_organization>.pushdemo/deviceinstallation');
      static const String getDeviceIdChannelMethod = "getDeviceId";
      static const String getDeviceTokenChannelMethod = "getDeviceToken";
      static const String getDevicePlatformChannelMethod = "getDevicePlatform";
    
      Future<String> getDeviceId() {
        return deviceInstallation.invokeMethod(getDeviceIdChannelMethod);
      }
    
      Future<String> getDeviceToken() {
        return deviceInstallation.invokeMethod(getDeviceTokenChannelMethod);
      }
    
      Future<String> getDevicePlatform() {
        return deviceInstallation.invokeMethod(getDevicePlatformChannelMethod);
      }
    }
    

    Anmerkung

    Sie sollten Ihren eigenen Organisationsnamen für den Platzhalter <your_organization> verwenden. Beispielsweise führt die Verwendung Mobcat als Organisation zu einem MethodChannel Namen von com.mobcat.pushdemo/deviceinstallation.

    Diese Klasse kapselt die Arbeit mit der zugrunde liegenden systemeigenen Plattform, um die erforderlichen Geräteinstallationsdetails zu erhalten. Eine MethodChannel- erleichtert die bidirektionale asynchrone Kommunikation mit den zugrunde liegenden nativen Plattformen. Das plattformspezifische Gegenstück für diesen Kanal wird in den nachfolgenden Schritten erstellt.

  5. Fügen Sie diesem Ordner eine weitere Datei namens notification_action_service.dart mit der folgenden Implementierung hinzu.

    import 'package:flutter/services.dart';
    import 'dart:async';
    import 'package:push_demo/models/push_demo_action.dart';
    
    class NotificationActionService {
      static const notificationAction =
          const MethodChannel('com.<your_organization>.pushdemo/notificationaction');
      static const String triggerActionChannelMethod = "triggerAction";
      static const String getLaunchActionChannelMethod = "getLaunchAction";
    
      final actionMappings = {
        'action_a' : PushDemoAction.actionA,
        'action_b' : PushDemoAction.actionB
      };
    
      final actionTriggeredController = StreamController.broadcast();
    
      NotificationActionService() {
        notificationAction
            .setMethodCallHandler(handleNotificationActionCall);
      }
    
      Stream get actionTriggered => actionTriggeredController.stream;
    
      Future<void> triggerAction({action: String}) async {
    
        if (!actionMappings.containsKey(action)) {
          return;
        }
    
        actionTriggeredController.add(actionMappings[action]);
      }
    
      Future<void> checkLaunchAction() async {
        final launchAction = await notificationAction.invokeMethod(getLaunchActionChannelMethod) as String;
    
        if (launchAction != null) {
          triggerAction(action: launchAction);
        }
      }
    
      Future<void> handleNotificationActionCall(MethodCall call) async {
        switch (call.method) {
          case triggerActionChannelMethod:
            return triggerAction(action: call.arguments as String);
          default:
            throw MissingPluginException();
            break;
        }
      }
    }
    

    Anmerkung

    Dies wird als einfacher Mechanismus verwendet, um die Behandlung von Benachrichtigungsaktionen zu zentralisieren, sodass sie mithilfe einer stark typisierten Enumeration plattformübergreifend behandelt werden können. Der Dienst ermöglicht es der zugrunde liegenden nativen Plattform, eine Aktion auszulösen, wenn eine in der Benachrichtigungsnutzlast angegeben wird. Außerdem kann der allgemeine Code retrospektiv überprüfen, ob eine Aktion während des Anwendungsstarts angegeben wurde, sobald Flutter sie verarbeiten kann. Wenn die App beispielsweise gestartet wird, indem Sie über das Benachrichtigungscenter auf eine Benachrichtigung tippen.

  6. Fügen Sie der -Dienste eine neue Datei Ordner namens notification_registration_service.dart mit der folgenden Implementierung hinzu.

    import 'dart:convert';
    import 'package:flutter/services.dart';
    import 'package:http/http.dart' as http;
    import 'package:push_demo/services/device_installation_service.dart';
    import 'package:push_demo/models/device_installation.dart';
    import 'package:flutter_secure_storage/flutter_secure_storage.dart';
    
    class NotificationRegistrationService {
      static const notificationRegistration =
          const MethodChannel('com.<your_organization>.pushdemo/notificationregistration');
    
      static const String refreshRegistrationChannelMethod = "refreshRegistration";
      static const String installationsEndpoint = "api/notifications/installations";
      static const String cachedDeviceTokenKey = "cached_device_token";
      static const String cachedTagsKey = "cached_tags";
    
      final deviceInstallationService = DeviceInstallationService();
      final secureStorage = FlutterSecureStorage();
    
      String baseApiUrl;
      String apikey;
    
      NotificationRegistrationService(this.baseApiUrl, this.apikey) {
        notificationRegistration
            .setMethodCallHandler(handleNotificationRegistrationCall);
      }
    
      String get installationsUrl => "$baseApiUrl$installationsEndpoint";
    
      Future<void> deregisterDevice() async {
        final cachedToken = await secureStorage.read(key: cachedDeviceTokenKey);
        final serializedTags = await secureStorage.read(key: cachedTagsKey);
    
        if (cachedToken == null || serializedTags == null) {
          return;
        }
    
        var deviceId = await deviceInstallationService.getDeviceId();
    
        if (deviceId.isEmpty) {
          throw "Unable to resolve an ID for the device.";
        }
    
        var response = await http
            .delete("$installationsUrl/$deviceId", headers: {"apikey": apikey});
    
        if (response.statusCode != 200) {
          throw "Deregister request failed: ${response.reasonPhrase}";
        }
    
        await secureStorage.delete(key: cachedDeviceTokenKey);
        await secureStorage.delete(key: cachedTagsKey);
      }
    
      Future<void> registerDevice(List<String> tags) async {
        try {
          final deviceId = await deviceInstallationService.getDeviceId();
          final platform = await deviceInstallationService.getDevicePlatform();
          final token = await deviceInstallationService.getDeviceToken();
    
          final deviceInstallation =
              DeviceInstallation(deviceId, platform, token, tags);
    
          final response = await http.put(installationsUrl,
              body: jsonEncode(deviceInstallation),
              headers: {"apikey": apikey, "Content-Type": "application/json"});
    
          if (response.statusCode != 200) {
            throw "Register request failed: ${response.reasonPhrase}";
          }
    
          final serializedTags = jsonEncode(tags);
    
          await secureStorage.write(key: cachedDeviceTokenKey, value: token);
          await secureStorage.write(key: cachedTagsKey, value: serializedTags);
        } on PlatformException catch (e) {
          throw e.message;
        } catch (e) {
          throw "Unable to register device: $e";
        }
      }
    
      Future<void> refreshRegistration() async {
        final currentToken = await deviceInstallationService.getDeviceToken();
        final cachedToken = await secureStorage.read(key: cachedDeviceTokenKey);
        final serializedTags = await secureStorage.read(key: cachedTagsKey);
    
        if (currentToken == null ||
            cachedToken == null ||
            serializedTags == null ||
            currentToken == cachedToken) {
          return;
        }
    
        final tags = jsonDecode(serializedTags);
    
        return registerDevice(tags);
      }
    
      Future<void> handleNotificationRegistrationCall(MethodCall call) async {
        switch (call.method) {
          case refreshRegistrationChannelMethod:
            return refreshRegistration();
          default:
            throw MissingPluginException();
            break;
        }
      }
    }
    

    Anmerkung

    Diese Klasse kapselt die Verwendung der DeviceInstallationService- und die Anforderungen an den Back-End-Dienst, um die erforderlichen Registrierungs-, Registrierungs- und Aktualisierungsaktionen auszuführen. Das argument apiKey ist nur erforderlich, wenn Sie die Authentifizieren von Clients mit einem API-Schlüssel Abschnitt abgeschlossen haben.

  7. Fügen Sie der lib Ordner eine neue Datei mit dem Namen config.dart mit der folgenden Implementierung hinzu.

    class Config {
      static String apiKey = "API_KEY";
      static String backendServiceEndpoint = "BACKEND_SERVICE_ENDPOINT";
    }
    

    Anmerkung

    Dies wird als einfache Methode zum Definieren von App-Geheimschlüsseln verwendet. Ersetzen Sie die Platzhalterwerte durch Eigene. Sie sollten diese beim Erstellen des Back-End-Diensts notieren. Die -API-App-URL sollte https://<api_app_name>.azurewebsites.net/werden. Der apiKey Member ist nur erforderlich, wenn Sie die Authentifizieren von Clients mit einem API-Schlüssel Abschnitt abgeschlossen haben.

    Fügen Sie dies ihrer Gitignore-Datei hinzu, um zu vermeiden, dass diese geheimen Schlüssel zur Quellcodeverwaltung verpflichtet werden.

Implementieren der plattformübergreifenden Benutzeroberfläche

  1. Ersetzen Sie in main_page.dartdie Build Funktion durch Folgendes.

    @override
    Widget build(BuildContext context) {
    return Scaffold(
        body: Padding(
          padding: const EdgeInsets.symmetric(horizontal: 20.0, vertical: 40.0),
          child: Column(
            mainAxisAlignment: MainAxisAlignment.end,
            crossAxisAlignment: CrossAxisAlignment.stretch,
            children: <Widget>[
              FlatButton(
                child: Text("Register"),
                onPressed: registerButtonClicked,
              ),
              FlatButton(
                child: Text("Deregister"),
                onPressed: deregisterButtonClicked,
              ),
            ],
          ),
        ),
      );
    }
    
  2. Fügen Sie die erforderlichen Importe oben in der Datei main_page.dart hinzu.

    import 'package:push_demo/services/notification_registration_service.dart';
    import 'config.dart';
    
  3. Fügen Sie der klasse _MainPageState ein Feld hinzu, um einen Verweis auf die NotificationRegistrationService-zu speichern.

    final notificationRegistrationService = NotificationRegistrationService(Config.backendServiceEndpoint, Config.apiKey);
    
  4. Implementieren Sie in der klasse _MainPageState die Ereignishandler für die Register und Deregistern Schaltflächen onPressed--Ereignisse. Rufen Sie die entsprechenden Register/Deregister Methoden auf, und zeigen Sie dann eine Warnung an, um das Ergebnis anzuzeigen.

    void registerButtonClicked() async {
        try {
          await notificationRegistrationService.registerDevice(List<String>());
          await showAlert(message: "Device registered");
        }
        catch (e) {
          await showAlert(message: e);
        }
      }
    
      void deregisterButtonClicked() async {
        try {
          await notificationRegistrationService.deregisterDevice();
          await showAlert(message: "Device deregistered");
        }
        catch (e) {
          await showAlert(message: e);
        }
      }
    
      Future<void> showAlert({ message: String }) async {
        return showDialog<void>(
          context: context,
          barrierDismissible: false,
          builder: (BuildContext context) {
            return AlertDialog(
              title: Text('PushDemo'),
              content: SingleChildScrollView(
                child: ListBody(
                  children: <Widget>[
                    Text(message),
                  ],
                ),
              ),
              actions: <Widget>[
                FlatButton(
                  child: Text('OK'),
                  onPressed: () {
                    Navigator.of(context).pop();
                  },
                ),
              ],
            );
          },
        );
      }
    
  5. Stellen Sie jetzt in main.dartsicher, dass die folgenden Importe am Anfang der Datei vorhanden sind.

    import 'package:flutter/material.dart';
    import 'package:push_demo/models/push_demo_action.dart';
    import 'package:push_demo/services/notification_action_service.dart';
    import 'package:push_demo/main_page.dart';
    
  6. Deklarieren Sie eine Variable zum Speichern eines Verweises auf eine Instanz von NotificationActionService und initialisieren Sie sie.

    final notificationActionService = NotificationActionService();
    
  7. Fügen Sie Funktionen hinzu, um die Anzeige einer Warnung zu behandeln, wenn eine Aktion ausgelöst wird.

    void notificationActionTriggered(PushDemoAction action) {
      showActionAlert(message: "${action.toString().split(".")[1]} action received");
    }
    
    Future<void> showActionAlert({ message: String }) async {
      return showDialog<void>(
        context: navigatorKey.currentState.overlay.context,
        barrierDismissible: false,
        builder: (BuildContext context) {
          return AlertDialog(
            title: Text('PushDemo'),
            content: SingleChildScrollView(
              child: ListBody(
                children: <Widget>[
                  Text(message),
                ],
              ),
            ),
            actions: <Widget>[
              FlatButton(
                child: Text('OK'),
                onPressed: () {
                  Navigator.of(context).pop();
                },
              ),
            ],
          );
        },
      );
    }
    
  8. Aktualisieren Sie die Hauptfunktion, um die NotificationActionService-actionTriggered Stream zu beobachten und nach Aktionen zu suchen, die während des App-Starts erfasst werden.

    void main() async {
      runApp(MaterialApp(home: MainPage(), navigatorKey: navigatorKey,));
      notificationActionService.actionTriggered.listen((event) { notificationActionTriggered(event as PushDemoAction); });
      await notificationActionService.checkLaunchAction();
    }
    

    Anmerkung

    Dies ist einfach, den Empfang und die Verteilung von Pushbenachrichtigungsaktionen zu veranschaulichen. In der Regel werden diese im Hintergrund behandelt, z. B. das Navigieren zu einer bestimmten Ansicht oder das Aktualisieren einiger Daten, anstatt in diesem Fall eine Warnung anzuzeigen.

Konfigurieren des systemeigenen Android-Projekts für Pushbenachrichtigungen

Hinzufügen der JSON-Datei von Google Services

  1. Steuerelement + Klicken Sie auf im Ordner android, und wählen Sie dann In Android Studioöffnen. Wechseln Sie dann zur Ansicht Project (sofern dies noch nicht geschehen ist).

  2. Suchen Sie die google-services.json Datei, die Sie zuvor heruntergeladen haben, wenn Sie das PushDemo Projekt in der Firebase Consoleeinrichten. Ziehen Sie es dann in das App Modulstammverzeichnis (Android>Android>App).

Konfigurieren von Buildeinstellungen und Berechtigungen

  1. Wechseln Sie zur Ansicht ProjectAndroid.

  2. Öffnen Sie AndroidManifest.xml, fügen Sie dann die INTERNET- und READ_PHONE_STATE Berechtigungen nach dem Anwendung Element vor dem schließenden -Tag hinzu.

    <manifest>
        <application>...</application>
        <uses-permission android:name="android.permission.INTERNET" />
        <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    </manifest>
    

Hinzufügen der Firebase-SDKs

  1. Öffnen Sie in Android Studiodie datei build.gradle (Gradle Scripts>build.gradle (Project: android)). und stellen Sie sicher, dass Sie über den Klassenpfad "com.google.gms:google-services" in den buildscript>Abhängigkeiten Knoten verfügen.

    buildscript {
    
      repositories {
        // Check that you have the following line (if not, add it):
        google()  // Google's Maven repository
      }
    
      dependencies {
        // ...
    
        // Add the following line:
        classpath 'com.google.gms:google-services:4.3.3'  // Google Services plugin
      }
    }
    
    allprojects {
      // ...
    
      repositories {
        // Check that you have the following line (if not, add it):
        google()  // Google's Maven repository
        // ...
      }
    }
    

    Anmerkung

    Stellen Sie sicher, dass Sie auf die neueste Version gemäß den Anweisungen in der Firebase Console verweisen, wenn Sie das Android Projecterstellt haben.

  2. Wenden Sie in der Datei build.gradle Datei (Gradle Scripts>build.gradle (Modul: App)) das Google Services Gradle-Plug-Inan. Wenden Sie das Plug-In direkt über dem Android- Knoten an.

    // ...
    
    // Add the following line:
    apply plugin: 'com.google.gms.google-services'  // Google Services plugin
    
    android {
      // ...
    }
    
  3. Fügen Sie in derselben Datei in den Abhängigkeiten Knoten die Abhängigkeit für die Cloud Messaging Android-Bibliothek hinzu.

    dependencies {
        // ...
        implementation 'com.google.firebase:firebase-messaging:20.2.0'
    }
    

    Anmerkung

    Stellen Sie sicher, dass Sie gemäß der Cloud Messaging Android-Clientdokumentationauf die neueste Version verweisen.

  4. Speichern Sie die Änderungen, und klicken Sie dann auf die Schaltfläche Jetzt synchronisieren (aus der Symbolleistenaufforderung) oder Synchronisieren des Projekts mit Gradle-Dateien.

Behandeln von Pushbenachrichtigungen für Android

  1. Klicken Sie in Android Studio, Control + Klicken Sie auf auf der com.<your_organization>.pushdemo Paketordner (App>src>Haupt->kotlin), wählen Sie Paket aus dem Menü Neue aus. Geben Sie Dienste als Namen ein, und drücken Sie dann EINGABETASTE.

  2. Steuerelement + Klicken Sie im Ordner Dienste auf klicken, wählen Sie Kotlin File/Class aus dem Menü Neue aus. Geben Sie DeviceInstallationService- als Namen ein, und drücken Sie dann Eingabetaste.

  3. Implementieren Sie die DeviceInstallationService- mithilfe des folgenden Codes.

    package com.<your_organization>.pushdemo.services
    
    import android.annotation.SuppressLint
    import android.content.Context
    import android.provider.Settings.Secure
    import com.google.android.gms.common.ConnectionResult
    import com.google.android.gms.common.GoogleApiAvailability
    import io.flutter.embedding.engine.FlutterEngine
    import io.flutter.plugin.common.MethodCall
    import io.flutter.plugin.common.MethodChannel
    
    @SuppressLint("HardwareIds")
    class DeviceInstallationService {
    
        companion object {
            const val DEVICE_INSTALLATION_CHANNEL = "com.<your_organization>.pushdemo/deviceinstallation"
            const val GET_DEVICE_ID = "getDeviceId"
            const val GET_DEVICE_TOKEN = "getDeviceToken"
            const val GET_DEVICE_PLATFORM = "getDevicePlatform"
        }
    
        private var context: Context
        private var deviceInstallationChannel : MethodChannel
    
        val playServicesAvailable
            get() = GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(context) == ConnectionResult.SUCCESS
    
        constructor(context: Context, flutterEngine: FlutterEngine) {
            this.context = context
            deviceInstallationChannel = MethodChannel(flutterEngine.dartExecutor.binaryMessenger, DEVICE_INSTALLATION_CHANNEL)
            deviceInstallationChannel.setMethodCallHandler { call, result -> handleDeviceInstallationCall(call, result) }
        }
    
        fun getDeviceId() : String
            = Secure.getString(context.applicationContext.contentResolver, Secure.ANDROID_ID)
    
        fun getDeviceToken() : String {
            if(!playServicesAvailable) {
                throw Exception(getPlayServicesError())
            }
    
            // TODO: Revisit once we have created the PushNotificationsFirebaseMessagingService
            val token = "Placeholder_Get_Value_From_FirebaseMessagingService_Implementation"
    
            if (token.isNullOrBlank()) {
                throw Exception("Unable to resolve token for FCM.")
            }
    
            return token
        }
    
        fun getDevicePlatform() : String = "fcm"
    
        private fun handleDeviceInstallationCall(call: MethodCall, result: MethodChannel.Result) {
            when (call.method) {
                GET_DEVICE_ID -> {
                    result.success(getDeviceId())
                }
                GET_DEVICE_TOKEN -> {
                    getDeviceToken(result)
                }
                GET_DEVICE_PLATFORM -> {
                    result.success(getDevicePlatform())
                }
                else -> {
                    result.notImplemented()
                }
            }
        }
    
        private fun getDeviceToken(result: MethodChannel.Result) {
            try {
                val token = getDeviceToken()
                result.success(token)
            }
            catch (e: Exception) {
                result.error("ERROR", e.message, e)
            }
        }
    
        private fun getPlayServicesError(): String {
            val resultCode = GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(context)
    
            if (resultCode != ConnectionResult.SUCCESS) {
                return if (GoogleApiAvailability.getInstance().isUserResolvableError(resultCode)){
                    GoogleApiAvailability.getInstance().getErrorString(resultCode)
                } else {
                    "This device is not supported"
                }
            }
    
            return "An error occurred preventing the use of push notifications"
        }
    }
    

    Anmerkung

    Diese Klasse implementiert das plattformspezifische Gegenstück für den com.<your_organization>.pushdemo/deviceinstallation-Kanal. Dies wurde im Flutterteil der App innerhalb DeviceInstallationService.dartdefiniert. In diesem Fall werden die Aufrufe vom allgemeinen Code an den systemeigenen Host ausgeführt. Achten Sie darauf, <your_organization> durch Ihre eigene Organisation zu ersetzen, wo immer dies verwendet wird.

    Diese Klasse stellt eine eindeutige ID (mit Secure.AndroidId) als Teil der Benachrichtigungshub-Registrierungsnutzlast bereit.

  4. Fügen Sie dem ordner "NotificationRegistrationService"-einen weiteren Kotlin File/Class hinzu, und fügen Sie dann den folgenden Code hinzu.

    package com.<your_organization>.pushdemo.services
    
    import io.flutter.embedding.engine.FlutterEngine
    import io.flutter.plugin.common.MethodChannel
    
    class NotificationRegistrationService {
    
        companion object {
            const val NOTIFICATION_REGISTRATION_CHANNEL = "com.<your_organization>.pushdemo/notificationregistration"
            const val REFRESH_REGISTRATION = "refreshRegistration"
        }
    
        private var notificationRegistrationChannel : MethodChannel
    
        constructor(flutterEngine: FlutterEngine) {
            notificationRegistrationChannel = MethodChannel(flutterEngine.dartExecutor.binaryMessenger, NotificationRegistrationService.NOTIFICATION_REGISTRATION_CHANNEL)
        }
    
        fun refreshRegistration() {
            notificationRegistrationChannel.invokeMethod(REFRESH_REGISTRATION, null)
        }
    }
    

    Anmerkung

    Diese Klasse implementiert das plattformspezifische Gegenstück für den com.<your_organization>.pushdemo/notificationregistration-Kanal. Dies wurde im Flutterbereich der App innerhalb NotificationRegistrationService.dartdefiniert. In diesem Fall werden die Aufrufe vom systemeigenen Host an den gemeinsamen Code ausgeführt. Achten Sie auch hier darauf, <your_organization> durch Ihre eigene Organisation zu ersetzen, wo immer dies verwendet wird.

  5. Fügen Sie der Dienste Ordner mit dem Namen NotificationActionServiceeinen weiteren Kotlin File/Class- hinzu, und fügen Sie dann den folgenden Code hinzu.

    package com.<your_organization>.pushdemo.services
    
    import io.flutter.embedding.engine.FlutterEngine
    import io.flutter.plugin.common.MethodCall
    import io.flutter.plugin.common.MethodChannel
    
    class NotificationActionService {
        companion object {
            const val NOTIFICATION_ACTION_CHANNEL = "com.<your_organization>.pushdemo/notificationaction"
            const val TRIGGER_ACTION = "triggerAction"
            const val GET_LAUNCH_ACTION = "getLaunchAction"
        }
    
        private var notificationActionChannel : MethodChannel
        var launchAction : String? = null
    
        constructor(flutterEngine: FlutterEngine) {
            notificationActionChannel = MethodChannel(flutterEngine.dartExecutor.binaryMessenger, NotificationActionService.NOTIFICATION_ACTION_CHANNEL)
            notificationActionChannel.setMethodCallHandler { call, result -> handleNotificationActionCall(call, result) }
        }
    
        fun triggerAction(action: String) {
            notificationActionChannel.invokeMethod(NotificationActionService.TRIGGER_ACTION, action)
        }
    
        private fun handleNotificationActionCall(call: MethodCall, result: MethodChannel.Result) {
            when (call.method) {
                NotificationActionService.GET_LAUNCH_ACTION -> {
                    result.success(launchAction)
                }
                else -> {
                    result.notImplemented()
                }
            }
        }
    }
    

    Anmerkung

    Diese Klasse implementiert das plattformspezifische Gegenstück für den com.<your_organization>.pushdemo/notificationaction-Kanal. Das wurde im Flutterbereich der App innerhalb NotificationActionService.dartdefiniert. Anrufe können in diesem Fall in beide Richtungen erfolgen. Achten Sie darauf, <your_organization> durch Ihre eigene Organisation zu ersetzen, wo immer dies verwendet wird.

  6. Fügen Sie der com eine neue Kotlin File/Class hinzu.<your_organization>.pushdemo Paket namens PushNotificationsFirebaseMessagingServiceund implementieren Sie dann den folgenden Code.

    package com.<your_organization>.pushdemo
    
    import android.os.Handler
    import android.os.Looper
    import com.google.firebase.messaging.FirebaseMessagingService
    import com.google.firebase.messaging.RemoteMessage
    import com.<your_organization>.pushdemo.services.NotificationActionService
    import com.<your_organization>.pushdemo.services.NotificationRegistrationService
    
    class PushNotificationsFirebaseMessagingService : FirebaseMessagingService() {
    
        companion object {
            var token : String? = null
            var notificationRegistrationService : NotificationRegistrationService? = null
            var notificationActionService : NotificationActionService? = null
        }
    
        override fun onNewToken(token: String) {
            PushNotificationsFirebaseMessagingService.token = token
            notificationRegistrationService?.refreshRegistration()
        }
    
        override fun onMessageReceived(message: RemoteMessage) {
            message.data.let {
                Handler(Looper.getMainLooper()).post {
                    notificationActionService?.triggerAction(it.getOrDefault("action", null))
                }
            }
        }
    }
    

    Anmerkung

    Diese Klasse ist für die Behandlung von Benachrichtigungen verantwortlich, wenn die App im Vordergrund ausgeführt wird. Sie ruft die triggerAction- bedingt für den NotificationActionService- auf, wenn eine Aktion in der Benachrichtigungsnutzlast enthalten ist, die in onMessageReceivedempfangen wird. Dadurch wird auch refreshRegistration für die NotificationRegistrationService- aufgerufen, wenn das Firebase--Token neu generiert wird, indem die onNewToken--Funktion außer Kraft gesetzt wird.

    Achten Sie erneut darauf, <your_organization> durch Ihre eigene Organisation zu ersetzen, wo sie verwendet wird.

  7. Fügen Sie in AndroidManifest.xml (App>src>Haupt-) den PushNotificationsFirebaseMessagingService- am Ende des -Anwendungs elements mit dem com.google.firebase.MESSAGING_EVENT Intent-Filter hinzu.

    <manifest>
        <application>
            <!-- EXISTING MANIFEST CONTENT -->
             <service
                android:name="com.<your_organization>.pushdemo.PushNotificationsFirebaseMessagingService"
                android:exported="false">
                <intent-filter>
                    <action android:name="com.google.firebase.MESSAGING_EVENT" />
                </intent-filter>
            </service>
        </application>
    </manifest>
    
  8. Stellen Sie in DeviceInstallationService-sicher, dass die folgenden Importe am Anfang der Datei vorhanden sind.

    package com.<your_organization>.pushdemo
    import com.<your_organization>.pushdemo.services.PushNotificationsFirebaseMessagingService
    

    Anmerkung

    Ersetzen Sie <your_organization> durch Ihren eigenen Organisationswert.

  9. Aktualisieren Sie den Platzhaltertext Placeholder_Get_Value_From_FirebaseMessagingService_Implementation, um den Tokenwert aus dem PushNotificationFirebaseMessagingService-abzurufen.

    fun getDeviceToken() : String {
        if(!playServicesAvailable) {
            throw Exception(getPlayServicesError())
        }
    
        // Get token from the PushNotificationsFirebaseMessagingService.token field.
        val token = PushNotificationsFirebaseMessagingService.token
    
        if (token.isNullOrBlank()) {
            throw Exception("Unable to resolve token for FCM.")
        }
    
        return token
    }
    
  10. Stellen Sie in MainActivitysicher, dass die folgenden Importe am Anfang der Datei vorhanden sind.

    package com.<your_organization>.pushdemo
    
    import android.content.Intent
    import android.os.Bundle
    import com.google.android.gms.tasks.OnCompleteListener
    import com.google.firebase.iid.FirebaseInstanceId
    import com.<your_organization>.pushdemo.services.DeviceInstallationService
    import com.<your_organization>.pushdemo.services.NotificationActionService
    import com.<your_organization>.pushdemo.services.NotificationRegistrationService
    import io.flutter.embedding.android.FlutterActivity
    

    Anmerkung

    Ersetzen Sie <your_organization> durch Ihren eigenen Organisationswert.

  11. Fügen Sie eine Variable hinzu, um einen Verweis auf die DeviceInstallationService-zu speichern.

    private lateinit var deviceInstallationService: DeviceInstallationService
    
  12. Fügen Sie eine Funktion namens processNotificationActions hinzu, um zu überprüfen, ob ein Intent- einen zusätzlichen Wert namens Aktionhat. Lösen Sie diese Aktion bedingt aus, oder speichern Sie sie später, wenn die Aktion während des App-Starts verarbeitet wird.

     private fun processNotificationActions(intent: Intent, launchAction: Boolean = false) {
        if (intent.hasExtra("action")) {
            var action = intent.getStringExtra("action");
    
            if (action.isNotEmpty()) {
                if (launchAction) {
                    PushNotificationsFirebaseMessagingService.notificationActionService?.launchAction = action
                }
                else {
                    PushNotificationsFirebaseMessagingService.notificationActionService?.triggerAction(action)
                }
            }
        }
    }
    
  13. Überschreiben Sie die onNewIntent--Funktion, um processNotificationActionsaufzurufen.

    override fun onNewIntent(intent: Intent) {
        super.onNewIntent(intent)
        processNotificationActions(intent)
    }
    

    Anmerkung

    Da die LaunchMode- für MainActivity- auf SingleTop-festgelegt ist, wird eine Intent- über die onNew an die vorhandene Activity Instanz gesendet.Intent--Funktion anstelle der onCreate-Funktion und sie müssen daher eine eingehende Intent- sowohl in onCreate als auch in onNewIntent--Funktionen behandeln.

  14. Überschreiben Sie die onCreate-Funktion, legen Sie die deviceInstallationService- auf eine neue Instanz von DeviceInstallationService-fest.

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
    
        flutterEngine?.let {
            deviceInstallationService = DeviceInstallationService(context, it)
        }
    }
    
  15. Legen Sie die eigenschaften notificationActionService und notificationRegistrationService für PushNotificationFirebaseMessagingServicesfest.

    flutterEngine?.let {
      deviceInstallationService = DeviceInstallationService(context, it)
      PushNotificationsFirebaseMessagingService.notificationActionService = NotificationActionService(it)
      PushNotificationsFirebaseMessagingService.notificationRegistrationService = NotificationRegistrationService(it)
    }
    
  16. Rufen Sie in derselben Funktion FirebaseInstanceId.getInstance().instanceId. Implementieren Sie die OnCompleteListener-, um den resultierenden Token- Wert für PushNotificationFirebaseMessagingService- festzulegen, bevor Sie refreshRegistrationaufrufen.

    if(deviceInstallationService?.playServicesAvailable) {
        FirebaseInstanceId.getInstance().instanceId
            .addOnCompleteListener(OnCompleteListener { task ->
                if (!task.isSuccessful)
                    return@OnCompleteListener
    
                PushNotificationsFirebaseMessagingService.token = task.result?.token
                PushNotificationsFirebaseMessagingService.notificationRegistrationService?.refreshRegistration()
            })
    }
    
  17. Rufen Sie in onCreateprocessNotificationActions am Ende der Funktion auf. Verwenden Sie true für das argument launchAction, um anzugeben, dass diese Aktion während des App-Starts verarbeitet wird.

    processNotificationActions(this.intent, true)
    

Anmerkung

Sie müssen die App jedes Mal erneut registrieren, wenn Sie sie ausführen, und sie von einer Debugsitzung beenden, um weiterhin Pushbenachrichtigungen zu erhalten.

Konfigurieren des systemeigenen iOS-Projekts für Pushbenachrichtigungen

Konfigurieren des Läuferziels und der Info.plist

  1. Klicken Sie in Visual Studio Code, Steuerelement + Klicken Sie im Ordner ios auf, und wählen Sie dann In Xcode öffnen.

  2. Klicken Sie in Xcode-auf Runner (die xcodeproj oben, nicht den Ordner), und wählen Sie dann das Runner Ziel aus, und Signieren & Funktionen. Wählen Sie mit dem ausgewählten "Alle Buildkonfiguration" Ihr Entwicklerkonto für das Team-aus. Stellen Sie sicher, dass die Option "Signatur automatisch verwalten" aktiviert ist und Ihr Signaturzertifikat und Das Bereitstellungsprofil automatisch ausgewählt sind.

    Anmerkung

    Wenn der neue Bereitstellungsprofilwert nicht angezeigt wird, versuchen Sie, die Profile für die Signaturidentität zu aktualisieren, indem Sie Xcode->Einstellungen>Konto- wählen Sie dann die Schaltfläche Manuellen Profile herunterladen, um die Profile herunterzuladen.

  3. Klicken Sie auf + Funktion, und suchen Sie dann nach Pushbenachrichtigungen. doppelklicken Sie aufPushbenachrichtigungen, um diese Funktion hinzuzufügen.

  4. Öffnen Sie Info.plist, und legen Sie Mindestsystemversion auf 13.0fest.

    Anmerkung

    Nur die Geräte, auf denen iOS 13.0 und höher ausgeführt werden, werden für die Zwecke dieses Lernprogramms unterstützt. Sie können sie jedoch erweitern, um Geräte mit älteren Versionen zu unterstützen.

  5. Öffnen Sie Runner.entitlements und stellen Sie sicher, dass die einstellung APS Environment auf Entwicklungfestgelegt ist.

Behandeln von Pushbenachrichtigungen für iOS

  1. Steuerelement + Klicken Sie auf im Ordner Runner (innerhalb des Runner-Projekts), und wählen Sie dann Neue Gruppe unter Verwendung Services als Namen aus.

  2. Steuerelement + Klicken Sie im Ordner Services auf, und wählen Sie dann Neue Datei...aus. Wählen Sie dann Swift File aus, und klicken Sie auf Next. Geben Sie DeviceInstallationService- für den Namen an, und klicken Sie dann auf Erstellen.

  3. Implementieren Sie DeviceInstallationService.swift mithilfe des folgenden Codes.

    import Foundation
    
    class DeviceInstallationService {
    
        enum DeviceRegistrationError: Error {
            case notificationSupport(message: String)
        }
    
        var token : Data? = nil
    
        let DEVICE_INSTALLATION_CHANNEL = "com.<your_organization>.pushdemo/deviceinstallation"
        let GET_DEVICE_ID = "getDeviceId"
        let GET_DEVICE_TOKEN = "getDeviceToken"
        let GET_DEVICE_PLATFORM = "getDevicePlatform"
    
        private let deviceInstallationChannel : FlutterMethodChannel
    
        var notificationsSupported : Bool {
            get {
                if #available(iOS 13.0, *) {
                    return true
                }
                else {
                    return false
                }
            }
        }
    
        init(withBinaryMessenger binaryMessenger : FlutterBinaryMessenger) {
            deviceInstallationChannel = FlutterMethodChannel(name: DEVICE_INSTALLATION_CHANNEL, binaryMessenger: binaryMessenger)
            deviceInstallationChannel.setMethodCallHandler(handleDeviceInstallationCall)
        }
    
        func getDeviceId() -> String {
            return UIDevice.current.identifierForVendor!.description
        }
    
        func getDeviceToken() throws -> String {
            if(!notificationsSupported) {
                let notificationSupportError = getNotificationsSupportError()
                throw DeviceRegistrationError.notificationSupport(message: notificationSupportError)
            }
    
            if (token == nil) {
                throw DeviceRegistrationError.notificationSupport(message: "Unable to resolve token for APNS.")
            }
    
            return token!.reduce("", {$0 + String(format: "%02X", $1)})
        }
    
        func getDevicePlatform() -> String {
            return "apns"
        }
    
        private func handleDeviceInstallationCall(call: FlutterMethodCall, result: @escaping FlutterResult) {
            switch call.method {
            case GET_DEVICE_ID:
                result(getDeviceId())
            case GET_DEVICE_TOKEN:
                getDeviceToken(result: result)
            case GET_DEVICE_PLATFORM:
                result(getDevicePlatform())
            default:
                result(FlutterMethodNotImplemented)
            }
        }
    
        private func getDeviceToken(result: @escaping FlutterResult) {
            do {
                let token = try getDeviceToken()
                result(token)
            }
            catch let error {
                result(FlutterError(code: "UNAVAILABLE", message: error.localizedDescription, details: nil))
            }
        }
    
        private func getNotificationsSupportError() -> String {
    
            if (!notificationsSupported) {
                return "This app only supports notifications on iOS 13.0 and above. You are running \(UIDevice.current.systemVersion)"
            }
    
            return "An error occurred preventing the use of push notifications."
        }
    }
    

    Anmerkung

    Diese Klasse implementiert das plattformspezifische Gegenstück für den com.<your_organization>.pushdemo/deviceinstallation-Kanal. Dies wurde im Flutterteil der App innerhalb DeviceInstallationService.dartdefiniert. In diesem Fall werden die Aufrufe vom allgemeinen Code an den systemeigenen Host ausgeführt. Achten Sie darauf, <your_organization> durch Ihre eigene Organisation zu ersetzen, wo immer dies verwendet wird.

    Diese Klasse stellt eine eindeutige ID (mithilfe der UIDevice.identifierForVendor Wert) als Teil der Benachrichtigungshub-Registrierungsnutzlast bereit.

  4. Fügen Sie einen weiteren Swift File zum Ordner Services namens NotificationRegistrationServicehinzu, und fügen Sie dann den folgenden Code hinzu.

    import Foundation
    
    class NotificationRegistrationService {
    
        let NOTIFICATION_REGISTRATION_CHANNEL = "com.<your_organization>.pushdemo/notificationregistration"
        let REFRESH_REGISTRATION = "refreshRegistration"
    
        private let notificationRegistrationChannel : FlutterMethodChannel
    
        init(withBinaryMessenger binaryMessenger : FlutterBinaryMessenger) {
           notificationRegistrationChannel = FlutterMethodChannel(name: NOTIFICATION_REGISTRATION_CHANNEL, binaryMessenger: binaryMessenger)
        }
    
        func refreshRegistration() {
            notificationRegistrationChannel.invokeMethod(REFRESH_REGISTRATION, arguments: nil)
        }
    }
    

    Anmerkung

    Diese Klasse implementiert das plattformspezifische Gegenstück für den com.<your_organization>.pushdemo/notificationregistration-Kanal. Dies wurde im Flutterbereich der App innerhalb NotificationRegistrationService.dartdefiniert. In diesem Fall werden die Aufrufe vom systemeigenen Host an den gemeinsamen Code ausgeführt. Achten Sie auch hier darauf, <your_organization> durch Ihre eigene Organisation zu ersetzen, wo immer dies verwendet wird.

  5. Fügen Sie dem Ordner Services "NotificationActionService" eine weitere Swift File hinzu, und fügen Sie dann den folgenden Code hinzu.

    import Foundation
    
    class NotificationActionService {
    
        let NOTIFICATION_ACTION_CHANNEL = "com.<your_organization>.pushdemo/notificationaction"
        let TRIGGER_ACTION = "triggerAction"
        let GET_LAUNCH_ACTION = "getLaunchAction"
    
        private let notificationActionChannel: FlutterMethodChannel
    
        var launchAction: String? = nil
    
        init(withBinaryMessenger binaryMessenger: FlutterBinaryMessenger) {
            notificationActionChannel = FlutterMethodChannel(name: NOTIFICATION_ACTION_CHANNEL, binaryMessenger: binaryMessenger)
            notificationActionChannel.setMethodCallHandler(handleNotificationActionCall)
        }
    
        func triggerAction(action: String) {
           notificationActionChannel.invokeMethod(TRIGGER_ACTION, arguments: action)
        }
    
        private func handleNotificationActionCall(call: FlutterMethodCall, result: @escaping FlutterResult) {
            switch call.method {
            case GET_LAUNCH_ACTION:
                result(launchAction)
            default:
                result(FlutterMethodNotImplemented)
            }
        }
    }
    

    Anmerkung

    Diese Klasse implementiert das plattformspezifische Gegenstück für den com.<your_organization>.pushdemo/notificationaction-Kanal. Das wurde im Flutterbereich der App innerhalb NotificationActionService.dartdefiniert. Anrufe können in diesem Fall in beide Richtungen erfolgen. Achten Sie darauf, <your_organization> durch Ihre eigene Organisation zu ersetzen, wo immer dies verwendet wird.

  6. Fügen Sie in AppDelegate.swiftVariablen hinzu, um einen Verweis auf die zuvor erstellten Dienste zu speichern.

    var deviceInstallationService : DeviceInstallationService?
    var notificationRegistrationService : NotificationRegistrationService?
    var notificationActionService : NotificationActionService?
    
  7. Fügen Sie eine Funktion namens processNotificationActions zum Verarbeiten der Benachrichtigungsdaten hinzu. Lösen Sie diese Aktion bedingt aus, oder speichern Sie sie später, wenn die Aktion während des App-Starts verarbeitet wird.

    func processNotificationActions(userInfo: [AnyHashable : Any], launchAction: Bool = false) {
        if let action = userInfo["action"] as? String {
            if (launchAction) {
                notificationActionService?.launchAction = action
            }
            else {
                notificationActionService?.triggerAction(action: action)
            }
        }
    }
    
  8. Überschreiben Sie die didRegisterForRemoteNotificationsWithDeviceToken Funktionseinstellung des Token- Werts für das DeviceInstallationService-. Rufen Sie dann refreshRegistration im NotificationRegistrationService-auf.

    override func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
      deviceInstallationService?.token = deviceToken
      notificationRegistrationService?.refreshRegistration()
    }
    
  9. Überschreiben Sie die didReceiveRemoteNotification Funktion, die das argument userInfo an die processNotificationActions Funktion übergibt.

    override func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any]) {
        processNotificationActions(userInfo: userInfo)
    }
    
  10. Überschreiben Sie die didFailToRegisterForRemoteNotificationsWithError-Funktion, um den Fehler zu protokollieren.

    override func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
        print(error);
    }
    

    Anmerkung

    Dies ist sehr viel ein Platzhalter. Sie möchten die richtige Protokollierung und Fehlerbehandlung für Produktionsszenarien implementieren.

  11. Instanziieren Sie in didFinishLaunchingWithOptionsdie variablen deviceInstallationService, notificationRegistrationServiceund notificationActionService variablen.

    let controller : FlutterViewController = window?.rootViewController as! FlutterViewController
    
    deviceInstallationService = DeviceInstallationService(withBinaryMessenger: controller.binaryMessenger)
    notificationRegistrationService = NotificationRegistrationService(withBinaryMessenger: controller.binaryMessenger)
    notificationActionService = NotificationActionService(withBinaryMessenger: controller.binaryMessenger)
    
  12. Fordern Sie in derselben Funktion die Autorisierung bedingt an und registrieren Sie sich für Remotebenachrichtigungen.

    if #available(iOS 13.0, *) {
      UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound, .badge]) {
          (granted, error) in
    
          if (granted)
          {
              DispatchQueue.main.async {
                  let pushSettings = UIUserNotificationSettings(types: [.alert, .sound, .badge], categories: nil)
                  application.registerUserNotificationSettings(pushSettings)
                  application.registerForRemoteNotifications()
              }
          }
      }
    }
    
  13. Wenn das launchOptions- den remoteNotification--Schlüssel enthält, rufen Sie processNotificationActions am Ende der -Funktion "finishLaunchingWithOptions" auf. Übergeben Sie das resultierende userInfo--Objekt, und verwenden Sie true für das argument launchAction. Ein true Wert zeigt an, dass die Aktion während des App-Starts verarbeitet wird.

    if let userInfo = launchOptions?[.remoteNotification] as? [AnyHashable : Any] {
        processNotificationActions(userInfo: userInfo, launchAction: true)
    }
    

Testen der Lösung

Sie können jetzt das Senden von Benachrichtigungen über den Back-End-Dienst testen.

Senden einer Testbenachrichtigung

  1. Öffnen Sie eine neue Registerkarte in Postman-.

  2. Legen Sie die Anforderung auf POST-fest, und geben Sie die folgende Adresse ein:

    https://<app_name>.azurewebsites.net/api/notifications/requests
    
  3. Wenn Sie sich entschieden haben, die Authentifizieren von Clients mit einem API-Schlüssel Abschnitt abzuschließen, müssen Sie die Anforderungsheader so konfigurieren, dass ihr apikey Wert enthalten ist.

    Schlüssel Wert
    apikey <your_api_key>
  4. Wählen Sie die Option unformatierten für den Bodyaus, und wählen Sie dann JSON- aus der Liste der Formatoptionen aus, und fügen Sie dann einen Platzhalter JSON- Inhalt ein:

    {
        "text": "Message from Postman!",
        "action": "action_a"
    }
    
  5. Wählen Sie die Schaltfläche Code aus, die sich oben rechts im Fenster unter der Schaltfläche Speichern befindet. Die Anforderung sollte dem folgenden Beispiel ähnlich aussehen, wenn sie für HTML- angezeigt wird (je nachdem, ob Sie einen apikey Header eingeschlossen haben):

    POST /api/notifications/requests HTTP/1.1
    Host: https://<app_name>.azurewebsites.net
    apikey: <your_api_key>
    Content-Type: application/json
    
    {
        "text": "Message from backend service",
        "action": "action_a"
    }
    
  6. Führen Sie die PushDemo--Anwendung auf einer oder beiden Zielplattformen aus (Android und iOS-).

    Anmerkung

    Wenn Sie auf Android testen, stellen Sie sicher, dass Sie nicht in Debug-ausgeführt werden, oder wenn die App durch Ausführen der Anwendung bereitgestellt wurde, erzwingen Sie das Schließen der App, und starten Sie sie erneut vom Startfeld.

  7. Tippen Sie in der PushDemo--App auf die Schaltfläche Registrieren.

  8. Schließen Sie zurück in Postmandas Fenster Codeausschnitte generieren (sofern dies noch nicht geschehen ist), und klicken Sie dann auf die Schaltfläche Senden.

  9. Überprüfen Sie, ob Sie eine 200 OK Antwort in Postman- erhalten und die Warnung in der App mit Aktion angezeigt wird, dieempfangen wurde.

  10. Schließen Sie die PushDemo--App, und klicken Sie dann erneut in Postman-auf die Schaltfläche " senden".

  11. Überprüfen Sie, ob Sie eine 200 OK Antwort in Postman erneut erhalten. Überprüfen Sie, ob eine Benachrichtigung im Infobereich für die PushDemo--App mit der richtigen Nachricht angezeigt wird.

  12. Tippen Sie auf die Benachrichtigung, um zu bestätigen, dass sie die App öffnet und die ActionA-Aktion angezeigt hat, die Warnung empfangen wurde.

  13. Ändern Sie zurück in Postmanden vorherigen Anforderungstext, um eine automatische Benachrichtigung zu senden, die action_b anstelle von action_a für die Aktion Wert angibt.

    {
        "action": "action_b",
        "silent": true
    }
    
  14. Wenn die App weiterhin geöffnet ist, klicken Sie in Postman-auf die Schaltfläche Senden.

  15. Überprüfen Sie, ob Sie eine 200 OK Antwort in Postman- erhalten und dass die Warnung in der App angezeigt wird, in der ActionB-Aktion empfangen anstelle aktionA empfangen.

  16. Schließen Sie die PushDemo--App, und klicken Sie dann erneut in Postman-auf die Schaltfläche " senden".

  17. Überprüfen Sie, ob Sie eine 200 OK Antwort in Postman- erhalten und dass die automatische Benachrichtigung nicht im Infobereich angezeigt wird.

Fehlerbehebung

Keine Antwort vom Back-End-Dienst

Stellen Sie beim lokalen Testen sicher, dass der Back-End-Dienst ausgeführt wird und den richtigen Port verwendet.

Wenn Tests mit der Azure API Appdurchgeführt werden, überprüfen Sie, ob der Dienst ausgeführt wird und ohne Fehler gestartet wurde.

Vergewissern Sie sich, dass Sie die Basisadresse beim Testen über den Client korrekt in Postman- oder in der Konfiguration der mobilen App angegeben haben. Die Basisadresse sollte bei lokalen Tests indikativ https://<api_name>.azurewebsites.net/ oder https://localhost:5001/ werden.

Empfangen von Benachrichtigungen unter Android nach dem Starten oder Beenden einer Debugsitzung

Stellen Sie sicher, dass Sie sich nach dem Starten oder Beenden einer Debugsitzung erneut registrieren. Der Debugger bewirkt, dass ein neues Firebase- Token generiert wird. Die Installation des Benachrichtigungshubs muss ebenfalls aktualisiert werden.

Empfangen eines 401-Statuscodes vom Back-End-Dienst

Überprüfen Sie, ob Sie den apikey Anforderungsheader festlegen, und dieser Wert entspricht dem, den Sie für den Back-End-Dienst konfiguriert haben.

Wenn sie diesen Fehler beim lokalen Testen erhalten, stellen Sie sicher, dass der Schlüsselwert, den Sie in der Clientkonfiguration definiert haben, dem Authentication:ApiKey vom -API-verwendeten Benutzereinstellungswert entspricht.

Wenn Sie mit einer API-App-testen, stellen Sie sicher, dass der Schlüsselwert in der Clientkonfigurationsdatei mit der Authentication:ApiKey Anwendungseinstellung übereinstimmt, die Sie in der API-App-verwenden.

Anmerkung

Wenn Sie diese Einstellung erstellt oder geändert haben, nachdem Sie den Back-End-Dienst bereitgestellt haben, müssen Sie den Dienst neu starten, damit er wirksam wird.

Wenn Sie sich entschieden haben, die Authentifizieren von Clients mit einem API-Schlüssel Abschnitt nicht abzuschließen, stellen Sie sicher, dass Sie das attribut Authorize nicht auf die NotificationsController Klasse angewendet haben.

Empfangen eines 404-Statuscodes vom Back-End-Dienst

Überprüfen Sie, ob die Endpunkt- und HTTP-Anforderungsmethode korrekt ist. Die Endpunkte sollten z. B. indikativ sein:

  • [PUT]-https://<api_name>.azurewebsites.net/api/notifications/installations
  • [DELETE]-https://<api_name>.azurewebsites.net/api/notifications/installations/<installation_id>
  • [POST]-https://<api_name>.azurewebsites.net/api/notifications/requests

Oder beim lokalen Testen:

  • [PUT]-https://localhost:5001/api/notifications/installations
  • [DELETE]-https://localhost:5001/api/notifications/installations/<installation_id>
  • [POST]-https://localhost:5001/api/notifications/requests

Stellen Sie beim Angeben der Basisadresse in der Client-App sicher, dass sie mit einem /endet. Die Basisadresse sollte bei lokalen Tests indikativ https://<api_name>.azurewebsites.net/ oder https://localhost:5001/ werden.

Die Registrierung ist nicht möglich, und es wird eine Fehlermeldung des Benachrichtigungshubs angezeigt.

Stellen Sie sicher, dass das Testgerät über netzwerkkonnektivität verfügt. Bestimmen Sie dann den Http-Antwortstatuscode, indem Sie einen Haltepunkt festlegen, um den wert der StatusCode Eigenschaft im HttpResponse-zu prüfen.

Überprüfen Sie die vorherigen Problembehandlungsvorschläge, sofern zutreffend, basierend auf dem Statuscode.

Legen Sie einen Haltepunkt für die Zeilen fest, die diese spezifischen Statuscodes für die jeweilige API zurückgeben. Versuchen Sie dann, den Back-End-Dienst beim lokalen Debuggen aufzurufen.

Überprüfen Sie, ob der Back-End-Dienst wie erwartet über Postman- mit der entsprechenden Nutzlast funktioniert. Verwenden Sie die tatsächliche Nutzlast, die vom Clientcode für die betreffende Plattform erstellt wurde.

Überprüfen Sie die plattformspezifischen Konfigurationsabschnitte, um sicherzustellen, dass keine Schritte verpasst wurden. Überprüfen Sie, ob geeignete Werte für installation id und token Variablen für die entsprechende Plattform aufgelöst werden.

Es wird keine ID für die Gerätefehlermeldung angezeigt.

Überprüfen Sie die plattformspezifischen Konfigurationsabschnitte, um sicherzustellen, dass keine Schritte verpasst wurden.

Nächste Schritte

Sie sollten jetzt über einen Back-End-Dienst eine einfache Flutter-App mit einem Benachrichtigungshub verbunden haben und Benachrichtigungen senden und empfangen können.

Wahrscheinlich müssen Sie das in diesem Lernprogramm verwendete Beispiel an Ihr eigenes Szenario anpassen. Die Implementierung robusterer Fehlerbehandlung, Wiederholungslogik und Protokollierung wird ebenfalls empfohlen.

Visual Studio App Center- können schnell in mobile Apps integriert werden, die Analyse- und Diagnose- zur Unterstützung der Problembehandlung bereitstellen.