Lernprogramm: Senden von Pushbenachrichtigungen an Flutter-Apps mithilfe von Azure Notification Hubs über einen Back-End-Dienst
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:
- Einrichten von Pushbenachrichtigungsdiensten und Azure Notification Hubs.
- Erstellen einer ASP.NET Core Web API-Back-End-Anwendung.
- Erstellen einer plattformübergreifenden Flutteranwendung.
- Konfigurieren des systemeigenen Android-Projekts für Pushbenachrichtigungen.
- Konfigurieren des systemeigenen iOS-Projekts für Pushbenachrichtigungen.
- Testen Sie die Lösung.
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 IhremSchlüsselbund installiert , mit dem Sie eine App auf einem physischen Gerätausführenkö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.
- Apple Developer Portal.
- ASP.NET Core.
- Google Firebase Console.
- Microsoft Azure und Senden von Pushbenachrichtigungen an iOS-Apps mithilfe von Azure Notification Hubs.
- Flutter und Dart für die plattformübergreifende Entwicklung.
- Kotlin und Swift für Android und iOS native Entwicklung.
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
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.
Nachdem Sie Ihr Projekt erstellt haben, wählen Sie "Firebase hinzufügen" zu Ihrer Android-Appaus.
Führen Sie auf der Seite Hinzufügen von Firebase zu Ihrer Android-App Seite die folgenden Schritte aus.
Geben Sie für den Android-Paketnameneinen Namen für Ihr Paket ein. Beispiel:
com.<organization_identifier>.<package_name>
.Wählen Sie App-registrieren aus.
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.
Wählen Sie Nächstenaus.
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.
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.
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.
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.
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
Wählen Sie auf dem Bildschirm Registrieren eines neuen Bezeichners die App-IDs Optionsfeld aus. Wählen Sie dann Weiteraus.
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.Pushbenachrichtigungen: Überprüfen Sie die Option Pushbenachrichtigungen im Abschnitt Funktionen.
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.
bestätigen
Nachdem Sie Registrierenausgewählt haben, wird die neue App-ID als Zeilenelement auf der Seite Zertifikate, Bezeichner & Profile Seite angezeigt.
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:
Erstellen eines p12-Pushzertifikats, das direkt in den Notification Hub- hochgeladen werden kann (den ursprünglichen Ansatz)
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
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.
Wählen Sie Schlüsselbundzugriffaus, erweitern Sie Zertifikat-Assistenten, und wählen Sie dann Zertifikat von einer Zertifizierungsstelleanfordern.
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.
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.
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.
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.
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.
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.
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.
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.
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.
Das Zertifikat wird heruntergeladen und auf Ihrem Computer in Ihrem ordner "Downloads" gespeichert.
Anmerkung
Standardmäßig heißt das heruntergeladene Entwicklungszertifikat aps_development.cer.
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:
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.
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.
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
Notieren Sie sich die folgenden Details:
- App-ID-Präfix (Team-ID)
- Bundle-ID
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.
Klicken Sie auf die Schaltfläche + (oder auf die Schaltfläche Erstellen eines Schlüssels), um einen neuen Schlüssel zu erstellen.
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.
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.
Klicken Sie auf Tastenauf den von Ihnen erstellten Schlüssel (oder auf einen vorhandenen Schlüssel, wenn Sie stattdessen dies verwenden möchten).
Notieren Sie sich den wert Key ID.
Ö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
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.
Wählen Sie iOS App Development unter Development als Bereitstellungsprofiltyp aus, und wählen Sie dann Weiteraus.
Wählen Sie als Nächstes die App-ID aus, die Sie aus der Dropdownliste
App-ID erstellt haben, und wählen Sie Weiter aus.Wählen Sie im Fenster
Zertifikat auswählen das Entwicklungszertifikat aus, das Sie für die Codesignierung verwenden, und wählen Sie Weiter aus.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.
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.
Wählen Sie im Fenster Zertifikate auswählen das von Ihnen erstellte Entwicklungszertifikat aus. Wählen Sie dann Weiteraus.
Wählen Sie als Nächstes die geräte aus, die zum Testen verwendet werden sollen, und wählen Sie Weiteraus.
Wählen Sie schließlich einen Namen für das Profil in Bereitstellungsprofilnameaus, und wählen Sie Generierenaus.
Wenn das neue Bereitstellungsprofil erstellt wird, wählen Sie Herunterladenaus. Denken Sie an den Speicherort, an dem sie gespeichert ist.
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.
Melden Sie sich bei Azurean.
Klicken Sie auf Erstellen einer Ressource, suchen Und wählen Sie Notification Hub-aus, und klicken Sie dann auf Erstellen.
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 beibehaltenAnmerkung
Sofern Sie nicht die maximale Anzahl von Hubs auf der kostenlosen Ebene erreicht haben.
Nachdem der Notification Hub bereitgestellt bereitgestellt wurde, navigieren Sie zu dieser Ressource.
Navigieren Sie zum neuen Notification Hub-.
Wählen Sie Zugriffsrichtlinien aus der Liste aus (unter VERWALTEN).
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
Wählen Sie Zertifikataus.
Wählen Sie das Dateisymbol aus.
Wählen Sie die P12-Datei aus, die Sie zuvor exportiert haben, und wählen Sie dann Öffnenaus.
Geben Sie bei Bedarf das richtige Kennwort an.
Wählen Sie Sandkastenmodus aus.
Wählen Sie Speichernaus.
OPTION 2: Verwenden der tokenbasierten Authentifizierung
Wählen Sie Token-aus.
Geben Sie die folgenden Werte ein, die Sie zuvor erworben haben:
- Schlüssel-ID-
- Bundle-ID
- Team-ID
- Token-
Wählen Sie Sandkasten-aus.
Wählen Sie Speichernaus.
Konfigurieren Des Benachrichtigungshubs mit FCM-Informationen
- Wählen Sie Google (GCM/FCM) im Abschnitt Einstellungen im linken Menü aus.
- Geben Sie den Serverschlüssel ein, Sie aus der Google Firebase Consolenotiert haben.
- 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
Wählen Sie in Visual StudioDatei>neue Projektmappeaus.
Wählen Sie .NET Core>App>ASP.NET Core>API>Nextaus.
Wählen Sie im Dialogfeld Konfigurieren der neuen ASP.NET Core Web APITarget Framework.NET Core 3.1aus.
Geben Sie PushDemoApi- für den Projektnamen ein, und wählen Sie dann Erstellenaus.
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:
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.
Klicken Sie auf
Ja , wenn Sie aufgefordert werden, das neue Zertifikatzuinstallieren und als vertrauenswürdig einzustufen, und geben Sie dann das Kennwort für Ihren Schlüsselbund ein.
Erweitern Sie den Ordner Controller, und löschen Sie dann WeatherForecastController.cs.
WeatherForecast.cslöschen .
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 PoliciesAnmerkung
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.
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.
Steuerelement Klicken Sie im Klicken Sie im MenüPushDemoApi- Projekt aufHinzufügen auf,und klicken Sie dann auf Hinzufügen mithilfeAuthentifizierung alsOrdnername .Steuerelement Klicken Sie im Ordner , und wählen Sie dann im MenüAuthentifizierung auf" hinzufügen""Neue Datei" aus. 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; } } }
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.
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.
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); }
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.
Steuerelement + Klicken Sie im Ordner Abhängigkeiten auf, und wählen Sie dann NuGet-Pakete verwalten...aus.
Suchen Sie nach Microsoft.Azure.NotificationHubs, und stellen Sie sicher, dass sie aktiviert ist.
Klicken Sie auf Paketehinzufügen, und klicken Sie dann auf Akzeptieren, wenn Sie aufgefordert werden, die Lizenzbedingungen zu akzeptieren.
Steuerelement Klicken Sie im projekt klicken, wählen Sie im MenüPushDemoApi aufOrdner hinzufügen Neuen Ordner aus, und klicken Sie dann auf Hinzufügen mithilfeModelle alsOrdnername .Steuerelement + Klicken Sie im Ordner Modelle auf, und wählen Sie dann Neue Datei... aus dem Menü Hinzufügen aus.
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.
Fügen Sie dem Ordner "
DeviceInstallation.cs " eine weitereleere 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>(); } }
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; } } }
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; } } }
Fügen Sie dem PushDemoApi Projekt namens Serviceseinen neuen Ordner hinzu.
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); } }
Fügen Sie dem
NotificationHubsService.cs Ordner"" eine "Leere Klasse" hinzu, und fügen Sie dann den folgenden Code hinzu, um dieINotificationService- -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.
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
Steuerelement Klicken Sie im Ordner , und wählen Sie dann im MenüController aufHinzufügen neue Datei aus. 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.
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;
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.
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]
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; }
Ä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.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.
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.
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> 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.
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.
Melden Sie sich beim Azure-Portalan.
Klicken Sie auf Erstellen einer Ressource, suchen Und wählen Sie API-App-aus, und klicken Sie dann auf Erstellen.
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 PlanAnmerkung
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.Nachdem die -API-App bereitgestellt wurde, navigieren Sie zu dieser Ressource.
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
.Wählen Sie Konfigurations- aus der Liste aus (unter Einstellungen).
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.
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.
Ändern Sie Ihre Konfiguration von Debug- in Release-, sofern dies noch nicht geschehen ist.
Steuerelement + Klicken Sie auf das PushDemoApi- Projekt, und wählen Sie dann im Menü VeröffentlichenIn Azure veröffentlichen... aus.
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.
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
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/
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> 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:
{}
Klicken Sie auf senden.
Anmerkung
Sie sollten einen 422 UnprocessableEntity Status des Diensts erhalten.
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
Öffnen Sie eine neue Instanz von Visual Studio Code.
Öffnen Sie die Befehlspalette (Umschalttaste + Befehl + P).
Wählen Sie den Befehl Flutter: Neues Projekt aus, und drücken Sie dann EINGABETASTE.
Geben Sie push_demo für den Projektnamen ein, und wählen Sie dann einen Projektspeicherortaus.
Wenn Sie dazu aufgefordert werden, wählen Sie Get Packagesaus.
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>
undpushdemo
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
- Mobcat
- COM
- kotlin
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.
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>
Aktualisieren Sie das
android:label
Attribut in der AndroidManifest.xml Datei unter src>Haupt- auf PushDemo-. Fügen Sie dann das attributandroid:allowBackup
direkt unterandroid:label
hinzu, 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>
Ö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.
Steuerelement + Klicken Sie im Ordner ios auf, und wählen Sie dann In Xcode öffnenaus.
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.
Klicken Sie auf Info.plist aktualisieren Sie dann den Bundle-Namen Wert auf PushDemo-
Schließen Sie Xcode-, und kehren Sie zu Visual Studio Codezurück.
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
Ä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).
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>[], ) ) ); } }
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));
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
Steuerelement + Klicken Sie auf in der Lib Ordner, und wählen Sie Neuen Ordner aus dem Menü aus, indem Sie Modelle als Ordnernamen.
Control Klicken Sie auf im ordnerModelle , 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, }; }
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, }
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.
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.
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.
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
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, ), ], ), ), ); }
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';
Fügen Sie der klasse _MainPageState ein Feld hinzu, um einen Verweis auf die NotificationRegistrationService-zu speichern.
final notificationRegistrationService = NotificationRegistrationService(Config.backendServiceEndpoint, Config.apiKey);
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(); }, ), ], ); }, ); }
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';
Deklarieren Sie eine Variable zum Speichern eines Verweises auf eine Instanz von NotificationActionService und initialisieren Sie sie.
final notificationActionService = NotificationActionService();
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(); }, ), ], ); }, ); }
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
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).
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
Wechseln Sie zur Ansicht ProjectAndroid.
Ö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
Ö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.
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 { // ... }
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.
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
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.
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.
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.
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.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.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.
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>
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.
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 }
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.
Fügen Sie eine Variable hinzu, um einen Verweis auf die DeviceInstallationService-zu speichern.
private lateinit var deviceInstallationService: DeviceInstallationService
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) } } } }
Ü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.
Ü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) } }
Legen Sie die eigenschaften notificationActionService und notificationRegistrationService für PushNotificationFirebaseMessagingServicesfest.
flutterEngine?.let { deviceInstallationService = DeviceInstallationService(context, it) PushNotificationsFirebaseMessagingService.notificationActionService = NotificationActionService(it) PushNotificationsFirebaseMessagingService.notificationRegistrationService = NotificationRegistrationService(it) }
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() }) }
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
Klicken Sie in Visual Studio Code, Steuerelement + Klicken Sie im Ordner ios auf, und wählen Sie dann In Xcode öffnen.
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.
Klicken Sie auf + Funktion, und suchen Sie dann nach Pushbenachrichtigungen. doppelklicken Sie aufPushbenachrichtigungen, um diese Funktion hinzuzufügen.
Ö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.
Öffnen Sie Runner.entitlements und stellen Sie sicher, dass die einstellung APS Environment auf Entwicklungfestgelegt ist.
Behandeln von Pushbenachrichtigungen für iOS
Steuerelement + Klicken Sie auf im Ordner Runner (innerhalb des Runner-Projekts), und wählen Sie dann Neue Gruppe unter Verwendung Services als Namen aus.
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.
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.
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.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.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?
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) } } }
Ü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() }
Ü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) }
Ü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.
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)
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() } } } }
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
Öffnen Sie eine neue Registerkarte in Postman-.
Legen Sie die Anforderung auf POST-fest, und geben Sie die folgende Adresse ein:
https://<app_name>.azurewebsites.net/api/notifications/requests
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> 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" }
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" }
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.
Tippen Sie in der PushDemo--App auf die Schaltfläche Registrieren.
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.
Überprüfen Sie, ob Sie eine 200 OK Antwort in Postman- erhalten und die Warnung in der App mit Aktion angezeigt wird, dieempfangen wurde.
Schließen Sie die PushDemo--App, und klicken Sie dann erneut in Postman-auf die Schaltfläche " senden".
Ü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.
Tippen Sie auf die Benachrichtigung, um zu bestätigen, dass sie die App öffnet und die ActionA-Aktion angezeigt hat, die Warnung empfangen wurde.
Ä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 }
Wenn die App weiterhin geöffnet ist, klicken Sie in Postman-auf die Schaltfläche Senden.
Ü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.
Schließen Sie die PushDemo--App, und klicken Sie dann erneut in Postman-auf die Schaltfläche " senden".
Ü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.
Verwandte Links
- übersicht über Azure Notification Hubs
- Installieren von Flutter auf macOS-
- Installieren von Fluter unter Windows
- Notification Hubs SDK für Back-End-Vorgänge
- Notification Hubs SDK auf GitHub-
- Registrieren mit Anwendungs-Back-End-
- Registrierungsverwaltung
- Arbeiten mit Tags
- Arbeiten mit benutzerdefinierten Vorlagen
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.