Tutorial: Senden von Pushbenachrichtigungen an Flutter-Apps mithilfe von Azure Notification Hubs über einen Back-End-Dienst
In diesem Tutorial verwenden Sie Azure Notification Hubs zum Pushen von Benachrichtigungen an eine Flutter-Anwendung für Android und iOS.
Ein ASP.NET Core Web-API-Back-End wird verwendet, um die Geräteregistrierung für den Client mithilfe des neuesten und besten Installationsansatzes zu verarbeiten. Der Dienst sendet auch plattformübergreifend Pushbenachrichtigungen.
Diese Vorgänge werden mit dem Notification Hubs SDK für Back-End-Vorgänge verarbeitet. Weitere Details zum Gesamtansatz finden Sie in der Dokumentation Registrieren über Das App-Back-End .
In diesem Tutorial werden die folgenden Schritte erklärt:
- Richten Sie Push Notification Services und Azure Notification Hubs ein.
- Erstellen Sie eine ASP.NET Core Web-API-Back-End-Anwendung.
- Erstellen Sie eine plattformübergreifende Flutter-Anwendung.
- Konfigurieren Sie das native Android-Projekt für Pushbenachrichtigungen.
- Konfigurieren Sie das native iOS-Projekt für Pushbenachrichtigungen.
- Testen der Lösung
Voraussetzungen
Für die Weiterverfolgung 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-Ins .
- CocoaPods zum Verwalten von Bibliotheksabhängigkeiten installiert.
- Die Möglichkeit, die App entweder unter Android (physische Geräte oder Emulatorgeräte) oder iOS (nur physische Geräte) auszuführen.
Für Android benötigen Sie Folgendes:
- Ein entwicklerentsperrtes physisches Gerät oder ein Emulator (mit API 26 und höher mit installierten Google Play Services)
Für iOS benötigen Sie Folgendes:
- Ein aktives Apple Developer-Konto.
- Ein physisches iOS-Gerät, das bei Ihrem Entwicklerkonto registriert ist (unter iOS 13.0 und höher)
- Ein P12-Entwicklungszertifikat, das in Ihrem Keychain installiert ist, mit dem Sie eine App auf einem physischen Gerät ausführen können.
Hinweis
Der iOS-Simulator unterstützt keine Remotebenachrichtigungen, sodass ein physisches Gerät erforderlich ist, wenn Sie dieses Beispiel unter iOS untersuchen. Sie müssen die App jedoch nicht sowohl unter Android als auch unter iOS ausführen, um dieses Tutorial abzuschließen.
Sie können die Schritte in diesem ersten Beispiel für Prinzipien ohne vorherige Erfahrung ausführen. Sie profitieren jedoch davon, dass Sie mit den folgenden Aspekten vertraut sind.
- Apple Developer Portal.
- ASP.NET Core.
- Google Firebase-Konsole.
- Microsoft Azure und Senden von Pushbenachrichtigungen an iOS-Apps mithilfe von Azure Notification Hubs.
- Flutter und Dart für plattformübergreifende Entwicklung.
- Kotlin und Swift für die native Entwicklung von Android und iOS.
Die angegebenen Schritte sind spezifisch für macOS. Es ist möglich, auf Windows zu folgen, indem Sie die iOS-Aspekte überspringen.
Einrichten von Push Notification Services 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 Notification Hub für die Verwendung dieser Dienste.
Erstellen eines Firebase-Projekts und Aktivieren von Firebase Cloud Messaging für Android
Melden Sie sich bei der Firebase-Konsole an. Erstellen Sie ein neues Firebase-Projekt, indem Sie PushDemo als Projektnamen eingeben.
Hinweis
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 Bindestrich getrennt ist. Sie können dies ändern, wenn Sie dies möchten, sofern sie weiterhin global eindeutig ist.
Nachdem Sie Ihr Projekt erstellt haben, wählen Sie Firebase zu Ihrer Android-App hinzufügen aus.
Führen Sie auf der Seite Firebase zu Ihrer Android-App hinzufügen die folgenden Schritte aus.
Geben Sie unter Android-Paketname einen Namen für Ihr Paket ein. Beispiel:
com.<organization_identifier>.<package_name>
.Wählen Sie App registrieren aus.
Wählen Sie google-services.json herunterladen aus. Speichern Sie die Datei dann zur späteren Verwendung in einem lokalen Ordner, und wählen Sie Weiter aus.
Klicken Sie auf Weiter.
Wählen Sie Weiter zur Konsole aus.
Hinweis
Wenn die Schaltfläche Mit Konsole fortfahren aufgrund der Überprüfung der Installation nicht aktiviert ist, wählen Sie Diesen Schritt überspringen aus.
Wählen Sie in der Firebase-Konsole das Zahnrad für Ihr Projekt aus. Wählen Sie dann Projekteinstellungen aus.
Hinweis
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 zur späteren Verwendung. Sie verwenden diesen Wert, um Ihren Notification Hub zu konfigurieren.
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 Zertifikate, Bezeichner & Profile, und wählen Sie dann Bezeichner aus. Klicken Sie hier + , um eine neue App zu registrieren.
Wählen Sie auf dem Bildschirm Neuen Bezeichner registrieren das Optionsfeld App-IDs aus. Klicken Sie anschließend auf Weiter.
Aktualisieren Sie die folgenden drei Werte für Ihre neue App, und wählen Sie dann Weiter aus:
Beschreibung: Geben Sie einen beschreibenden Namen für Ihre App ein.
Bundle-ID: Geben Sie eine Bundle-ID im Format com.organization_identifier<> ein.<>product_name, wie im App-Verteilungshandbuch erwähnt. Im folgenden Screenshot wird der
mobcat
Wert als organization-Bezeichner und der PushDemo-Wert als Produktname verwendet.Pushbenachrichtigungen: Aktivieren Sie die Option Pushbenachrichtigungen im Abschnitt Funktionen .
Diese Aktion generiert Ihre App-ID und fordert sie auf, die Informationen zu bestätigen. Wählen Sie Weiter und dann Registrieren aus, um die neue App-ID zu bestätigen.
Nachdem Sie Registrieren ausgewählt haben, wird die neue App-ID als Zeilenelement auf der Seite Zertifikate, Bezeichner & Profile angezeigt .
Suchen Sie auf der Seite Zertifikate, Bezeichner & Profile unter Bezeichner das von Ihnen erstellte App-ID-Zeilenelement. Wählen Sie dann die zugehörige Zeile aus, um den Bildschirm App-ID-Konfiguration bearbeiten anzuzeigen.
Erstellen eines Zertifikats für Notification Hubs
Ein Zertifikat ist erforderlich, damit der Notification Hub mit Apple Push Notification Services (APNS) arbeiten kann und kann auf zwei Arten bereitgestellt werden:
Erstellen eines p12-Pushzertifikats, das direkt in Notification Hub hochgeladen werden kann (der ursprüngliche Ansatz)
Erstellen eines p8-Zertifikats, das für die tokenbasierte Authentifizierung verwendet werden kann (neuer und empfohlener Ansatz)
Der neuere Ansatz bietet eine Reihe von Vorteilen, die in der tokenbasierten Authentifizierung (HTTP/2) für APNS dokumentiert sind. 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 Tutorials funktionieren.
OPTION 1: Erstellen eines p12-Pushzertifikats, das direkt in den Notification Hub hochgeladen werden kann
Führen Sie auf Ihrem Mac das Keychain Access-Tool aus. Sie kann im Ordner Hilfsprogramme oder im Ordner Andere auf dem Launchpad geöffnet werden.
Wählen Sie Schlüsselbundzugriff aus, erweitern Sie Zertifikat-Assistent, und wählen Sie dann Zertifikat von einer Zertifizierungsstelle anfordern aus.
Hinweis
Standardmäßig wählt keychain Access das erste Element in der Liste aus. Dies kann ein Problem sein, wenn Sie sich in der Kategorie Zertifikate befinden und die Apple Worldwide Developer Relations Certification Authority nicht das erste Element in der Liste ist. Stellen Sie sicher, dass Sie über ein nicht schlüsselfähiges Element verfügen oder dass der Apple Worldwide Developer Relations Certification Authority-Schlüssel ausgewählt ist, bevor Sie die CSR (Certificate Signing Request) generieren.
Wählen Sie Ihre Benutzer-Email-Adresse aus, geben Sie Ihren Common Name-Wert ein, stellen Sie sicher, dass Sie Auf Datenträger gespeichert angeben, und wählen Sie dann Weiter aus. Lassen Sie Email Adresse der Zertifizierungsstelle leer, da sie nicht erforderlich ist.
Geben Sie unter Speichern unter einen Namen für die CSR-Datei (Certificate Signing Request) ein, wählen Sie den Speicherort in Where aus, und wählen Sie dann Speichern aus.
Mit dieser Aktion wird die CSR-Datei am ausgewählten Speicherort gespeichert. Der Standardspeicherort ist Desktop. Merken Sie sich den für die Datei ausgewählten Speicherort.
Zurück auf der Seite Zertifikate, Bezeichner & Profile im iOS-Bereitstellungsportal, scrollen Sie nach unten zur aktivierten Option Pushbenachrichtigungen , und wählen Sie dann Konfigurieren aus, um das Zertifikat zu erstellen.
Das Fenster TLS/SSL-Zertifikate des Apple-Pushbenachrichtigungsdiensts wird angezeigt. Wählen Sie im Abschnitt Entwicklung TLS/SSL-Zertifikat die Schaltfläche Zertifikat erstellen aus.
Der Bildschirm Neues Zertifikat erstellen wird angezeigt.
Hinweis
In diesem Tutorial wird ein Entwicklungszertifikat verwendet. Der gleiche Prozess wird beim Registrieren eines Produktionszertifikats verwendet. Stellen Sie einfach sicher, dass Sie beim Senden von Benachrichtigungen denselben Zertifikattyp verwenden.
Wählen Sie Datei auswählen aus, navigieren Sie zu dem Speicherort, an dem Sie die CSR-Datei gespeichert haben, und doppelklicken Sie dann auf den Zertifikatnamen, um sie zu laden. Klicken Sie anschließend auf Weiter.
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 wird.
Das Zertifikat wird heruntergeladen und auf Ihrem Computer im Ordner Downloads gespeichert.
Hinweis
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 gezeigt:
Hinweis
Obwohl sich der Name in Ihrem Zertifikat möglicherweise unterscheidet, wird dem Namen das Präfix Apple Development iOS Push Services vorangestellt und der entsprechende Bundle-Bezeichner zugeordnet.
Klicken Sie in Keychain Access, Control + Klicken Sie auf das neue Pushzertifikat, das Sie in der Kategorie Zertifikate erstellt haben. Wählen Sie Exportieren, benennen Sie die Datei, wählen Sie das p12-Format und dann Speichern aus.
Sie können das Zertifikat mit einem Kennwort schützen, ein Kennwort ist jedoch optional. Klicken Sie auf OK , wenn Sie die Kennworterstellung umgehen möchten. Notieren Sie sich den Dateinamen und den Speicherort des exportierten p12-Zertifikats. Sie werden verwendet, um die Authentifizierung mit APNs zu aktivieren.
Hinweis
Ihr p12-Dateiname und -Speicherort unterscheiden sich möglicherweise von den Abbildungen in diesem Tutorial.
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
Klicken Sie zurück unter Zertifikate, Bezeichner & Profile auf Schlüssel.
Hinweis
Wenn Sie bereits einen Schlüssel für APNS konfiguriert haben, können Sie das p8-Zertifikat, das Sie direkt nach der Erstellung heruntergeladen haben, erneut verwenden. Wenn ja, können Sie die Schritte 3 bis 5 ignorieren.
Klicken Sie auf die + Schaltfläche (oder die Schaltfläche Schlüssel erstellen ), um einen neuen Schlüssel zu erstellen.
Geben Sie einen geeigneten Schlüsselnamenwert an, aktivieren 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 Herunterladen , verschieben Sie dann die p8-Datei (mit dem Präfix AuthKey_) in ein sicheres lokales Verzeichnis, und klicken Sie dann auf Fertig.
Hinweis
Bewahren Sie Ihre p8-Datei an einem sicheren Ort auf (und speichern Sie eine Sicherung). Nachdem Sie Ihren Schlüssel heruntergeladen haben, kann er nicht erneut heruntergeladen werden, da die Serverkopie entfernt wird.
Klicken Sie unter Schlüssel auf den schlüssel, den Sie erstellt haben (oder auf einen vorhandenen Schlüssel, wenn Sie diesen stattdessen verwenden möchten).
Notieren Sie sich den Schlüssel-ID-Wert .
Ö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 PRIVATE KEY-----Hinweis
Dies ist der Tokenwert , der später zum Konfigurieren des Notification Hubs verwendet wird.
Am Ende dieser Schritte sollten Sie die folgenden Informationen zur späteren Verwendung unter Konfigurieren Ihres Notification Hubs mit APNS-Informationen haben:
- 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 zurück, wählen Sie Zertifikate, Bezeichner & Profile aus, wählen Sie profile im linken Menü aus, und wählen Sie + dann ein neues Profil aus. Der Bildschirm Neues Bereitstellungsprofil registrieren wird angezeigt.
Wählen Sie unter Entwicklung als Bereitstellungsprofiltyp die Option iOS-App-Entwicklung aus, und wählen Sie dann Weiter aus.
Wählen Sie als Nächstes die app-ID aus, die Sie in der Dropdownliste App-ID erstellt haben, und wählen Sie Weiter aus.
Wählen Sie im Fenster Zertifikate auswählen das Entwicklungszertifikat aus, das Sie für die Codesignierung verwenden, und dann Weiter.
Hinweis
Dieses Zertifikat ist nicht das Pushzertifikat, das Sie im vorherigen Schritt erstellt haben. Dies ist Ihr Entwicklungszertifikat. Wenn sie nicht vorhanden ist, müssen Sie es erstellen, da dies eine Voraussetzung für dieses Tutorial ist. Entwicklerzertifikate können im Apple Developer Portal, über Xcode oder in Visual Studio erstellt werden.
Kehren Sie zur Seite Zertifikate, Bezeichner & Profile zurück, wählen Sie im linken Menü Profile aus, und wählen Sie + dann ein neues Profil aus. Der Bildschirm Neues Bereitstellungsprofil registrieren wird angezeigt.
Wählen Sie im Fenster Zertifikate auswählen das von Ihnen erstellte Entwicklungszertifikat aus. Klicken Sie anschließend auf Weiter.
Wählen Sie als Nächstes die Geräte aus, die zum Testen verwendet werden sollen, und wählen Sie Weiter aus.
Wählen Sie schließlich unter Name des Bereitstellungsprofils einen Namen für das Profil aus, und wählen Sie Generieren aus.
Wenn das neue Bereitstellungsprofil erstellt wird, wählen Sie Herunterladen aus. Merken Sie sich den Speicherort, an dem sie gespeichert wird.
Navigieren Sie zum Speicherort des Bereitstellungsprofils, und doppelklicken Sie darauf, um es auf Ihrem Entwicklungscomputer zu installieren.
Erstellen eines Notification Hubs
In diesem Abschnitt erstellen Sie einen Notification Hub und konfigurieren die Authentifizierung mit APNS. Sie können ein p12-Pushzertifikat oder eine tokenbasierte Authentifizierung verwenden. Wenn Sie einen bereits erstellten Notification Hub verwenden möchten, können Sie mit Schritt 5 fortfahren.
Melden Sie sich bei Azure an.
Klicken Sie auf Ressource erstellen, suchen Sie nach Notification Hub, und wählen Sie diese Option aus, und klicken Sie dann auf Erstellen.
Aktualisieren Sie die folgenden Felder, und klicken Sie dann auf Erstellen:
GRUNDLEGENDE DETAILS
Abonnement: Auswählen des Zielabonnements aus der Dropdownliste
Ressourcengruppe: Erstellen einer neuen Ressourcengruppe (oder Auswählen einer vorhandenen Ressourcengruppe)NAMESPACEDETAILS
Notification Hub-Namespace: Geben Sie einen global eindeutigen Namen für den Notification Hub-Namespace ein.
Hinweis
Stellen Sie sicher, dass die Option Neu erstellen für dieses Feld ausgewählt ist.
NOTIFICATION HUB-DETAILS
Notification Hub: Geben Sie einen Namen für den Notification Hub ein.
Lage: Auswählen eines geeigneten Standorts aus der Dropdownliste
Tarif: Behalten Sie die Standardoption Free bei.Hinweis
Es sei denn, Sie haben die maximale Anzahl von Hubs im Free-Tarif erreicht.
Nachdem der Notification Hub bereitgestellt wurde, navigieren Sie zu dieser Ressource.
Navigieren Sie zu Ihrem neuen Notification Hub.
Wählen Sie in der Liste Zugriffsrichtlinien aus (unter VERWALTEN).
Notieren Sie sich die Werte des Richtliniennamens zusammen mit den entsprechenden Verbindungszeichenfolgenwerten .
Konfigurieren Ihres Notification Hubs mit APNS-Informationen
Wählen Sie unter Notification Servicesdie Option Apple aus, und führen Sie dann die entsprechenden Schritte basierend auf dem Ansatz aus, den Sie zuvor im Abschnitt Erstellen eines Zertifikats für Notification Hubs ausgewählt haben.
Hinweis
Verwenden Sie den Produktionsmodus nur, wenn Sie Pushbenachrichtigungen an Benutzer senden möchten, die Ihre App im Store erworben haben.
OPTION 1: Verwenden eines P12-Pushzertifikats
Wählen Sie Certificateaus.
Wählen Sie das Dateisymbol aus.
Wählen Sie die P12-Datei aus, die Sie zuvor exportiert haben, und wählen Sie dann Öffnen aus.
Geben Sie bei Bedarf das richtige Kennwort an.
Wählen Sie den Modus Sandbox aus.
Wählen Sie Speichern aus.
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 Sandbox aus.
Wählen Sie Speichern aus.
Konfigurieren Ihres Notification Hubs mit FCM-Informationen
- Wählen Sie im linken Menü im Abschnitt Einstellungen die Option Google (GCM/FCM) aus.
- Geben Sie den Serverschlüssel ein, den Sie sich in der Google Firebase-Konsole notiert haben.
- Wählen Sie auf der Symbolleiste Speichern aus.
Erstellen einer ASP.NET Core Web-API-Back-End-Anwendung
In diesem Abschnitt erstellen Sie das ASP.NET Core Web-API-Back-End, um die Geräteregistrierung und das Senden von Benachrichtigungen an die mobile Flutter-App zu verarbeiten.
Erstellen eines Webprojekts
Wählen Sie in Visual StudioDatei>Neue Projektmappe aus.
Wählen Sie .NETCore-App>>ASP.NET Core>API>Weiter aus.
Wählen Sie im Dialogfeld Neue ASP.NET Core Web-API konfigurierendie Option Zielframework von .NET Core 3.1 aus.
Geben Sie pushDemoApi als Projektname ein, und wählen Sie dann Erstellen aus.
Starten Sie das Debuggen (Eingabetaste), + um die app mit Vorlagen zu testen.
Hinweis
Die app mit Vorlagen ist so konfiguriert, dass der WeatherForecastController als launchUrl verwendet wird. Dies wird unter Eigenschaften>launchSettings.json festgelegt.
Wenn Sie zur Meldung Ungültiges Entwicklungszertifikat gefunden aufgefordert werden:
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 Keychain einzugeben.
Klicken Sie auf Ja , wenn Sie aufgefordert werden, das neue Zertifikat zu installieren und dem neuen Zertifikat zu vertrauen, und geben Sie dann das Kennwort für Ihren Schlüsselbund ein.
Erweitern Sie den Ordner Controller , und löschen Sie dann WeatherForecastController.cs.
Löschen Sie WeatherForecast.cs.
Richten Sie lokale Konfigurationswerte mit dem Geheimnis-Manager-Tool ein. Durch das Entkoppeln der Geheimnisse von der Lösung wird sichergestellt, dass sie nicht in der Quellcodeverwaltung landen. Ö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 Notification Hub-Namen und Verbindungszeichenfolge Werte. Sie haben sich diese im Abschnitt Erstellen eines Notification Hubs notieren. Andernfalls können Sie sie in Azure nachschlagen.
NotificationHub:Name:
Weitere Informationen finden Sie unter Name in der Zusammenfassung der Grundlagen oben in der Übersicht.NotificationHub:ConnectionString:
Weitere Informationen finden Sie unter DefaultFullSharedAccessSignature unter Zugriffsrichtlinien.Hinweis
Für Produktionsszenarien können Sie Optionen wie Azure KeyVault anzeigen, um die Verbindungszeichenfolge sicher zu speichern. Der Einfachheit halber werden die Geheimnisse den Azure App Service Anwendungseinstellungen hinzugefügt.
Authentifizieren von Clients mithilfe eines API-Schlüssels (optional)
API-Schlüssel sind nicht so sicher wie Token, reichen aber für die Zwecke dieses Tutorials aus. Ein API-Schlüssel kann einfach über die ASP.NET Middleware konfiguriert werden.
Fügen Sie den lokalen Konfigurationswerten den API-Schlüssel hinzu.
dotnet user-secrets set "Authentication:ApiKey" <value>
Hinweis
Ersetzen Sie den Platzhalterwert durch Ihren eigenen Wert, und notieren Sie sich ihn.
Steuerung + Klicken Sie auf das Projekt PushDemoApi, wählen Sie im Menü Hinzufügen die Option Neuer Ordner aus, und klicken Sie dann auf Mithilfe der Authentifizierung als Ordnernamehinzufügen.
Steuerung + Klicken Sie auf den Ordner Authentifizierung, und wählen Sie dann im Menü Hinzufügen die Option Neue Datei... aus.
Wählen Sie Allgemein>Leere Klasse aus, geben Sie ApiKeyAuthOptions.cs als Name ein, und klicken Sie dann auf Neu , um die folgende Implementierung hinzuzufügen.
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 Authentifizierungsordnermit dem Namen 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)); } } }
Hinweis
Ein Authentifizierungshandler ist ein Typ, der das Verhalten eines Schemas implementiert, in diesem Fall ein benutzerdefiniertes API-Schlüsselschema.
Fügen Sie dem Authentifizierungsordner mit dem Namen 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); } } }
Hinweis
Diese Erweiterungsmethode vereinfacht den Middlewarekonfigurationscode in Startup.cs macht ihn lesbarer und im Allgemeinen einfacher zu befolgen.
Aktualisieren Sie in Startup.cs die ConfigureServices-Methode , um die API-Schlüsselauthentifizierung unterhalb des Aufrufs 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 noch in Startup.cs die Configure-Methode , um die Erweiterungsmethoden UseAuthentication und UseAuthorization für den IApplicationBuilder der App aufzurufen. Stellen Sie sicher, dass diese Methoden nach UseRouting und vor der 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(); }); }
Hinweis
Beim Aufrufen von UseAuthentication wird die Middleware registriert, die die zuvor registrierten Authentifizierungsschemas (von ConfigureServices) verwendet. Dies muss vor jeder Middleware aufgerufen werden, die von der Authentifizierung der Benutzer abhängt.
Hinzufügen von Abhängigkeiten und Konfigurieren von Diensten
ASP.NET Core unterstützt das Di-Softwareentwurfsmuster (Dependency Injection), ein Verfahren zum Erreichen der Inversion der Steuerung (Inversion of Control, IoC) zwischen Klassen und ihren Abhängigkeiten.
Die Verwendung des Notification Hubs und des Notification Hubs SDK für Back-End-Vorgänge wird in einem Dienst gekapselt. Der Dienst wird registriert und durch eine geeignete Abstraktion zur Verfügung gestellt.
Steuerung + Klicken Sie auf den Ordner Abhängigkeiten , und wählen Sie NuGet-Pakete verwalten... aus.
Suchen Sie nach Microsoft.Azure.NotificationHubs , und stellen Sie sicher, dass es aktiviert ist.
Klicken Sie auf Pakete hinzufügen und dann auf Akzeptieren , wenn Sie aufgefordert werden, die Lizenzbedingungen zu akzeptieren.
Steuerung + Klicken Sie auf das Projekt PushDemoApi, wählen Sie im Menü Hinzufügen die Option Neuer Ordner aus, und klicken Sie dann auf Mithilfe von Modellen als Ordnernamehinzufügen.
Steuerung + Klicken Sie auf den Ordner Modelle, und wählen Sie dann im Menü Hinzufügendie Option Neue Datei... aus.
Wählen Sie Allgemein>Leere Klasse aus, geben Sie als NamePushTemplates.cs ein, und klicken Sie dann auf Neu, um 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)\" }"; } } }
Hinweis
Diese Klasse enthält die tokenisierten Benachrichtigungsnutzlasten für die generischen und unbeaufsichtigten Benachrichtigungen, die für dieses Szenario erforderlich sind. Die Nutzlasten werden außerhalb der Installation definiert, um Experimente zu ermöglichen, ohne vorhandene Installationen über den Dienst aktualisieren zu müssen. Die Verarbeitung von Änderungen an Installationen auf diese Weise ist für dieses Tutorial nicht vorgesehen. Für die Produktion sollten Sie benutzerdefinierte Vorlagen berücksichtigen.
Fügen Sie dem Ordner Models mit dem Namen DeviceInstallation.cs eine weitere leere Klasse hinzu, und fügen Sie dann die folgende Implementierung hinzu.
using System.Collections.Generic; using System.ComponentModel.DataAnnotations; namespace PushDemoApi.Models { public class DeviceInstallation { [Required] public string InstallationId { get; set; } [Required] public string Platform { get; set; } [Required] public string PushChannel { get; set; } public IList<string> Tags { get; set; } = Array.Empty<string>(); } }
Fügen Sie dem Ordner Models mit dem Namen NotificationRequest.cs eine weitere leere Klasse 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 mit dem Namen NotificationHubOptions.cs eine weitere 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 einen neuen Ordner mit dem Namen Services hinzu.
Fügen Sie dem Ordner Dienste eine leere Schnittstelle mit dem Namen INotificationService.cs hinzu, 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 Ordner Services eine leere Klasse mit dem Namen NotificationHubsService.cs hinzu, und fügen Sie dann den folgenden Code hinzu, um die INotificationService-Schnittstelle zu implementieren:
using System; using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; using Microsoft.Azure.NotificationHubs; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using PushDemoApi.Models; namespace PushDemoApi.Services { public class NotificationHubService : INotificationService { readonly NotificationHubClient _hub; readonly Dictionary<string, NotificationPlatform> _installationPlatform; readonly ILogger<NotificationHubService> _logger; public NotificationHubService(IOptions<NotificationHubOptions> options, ILogger<NotificationHubService> logger) { _logger = logger; _hub = NotificationHubClient.CreateClientFromConnectionString( options.Value.ConnectionString, options.Value.Name); _installationPlatform = new Dictionary<string, NotificationPlatform> { { nameof(NotificationPlatform.Apns).ToLower(), NotificationPlatform.Apns }, { nameof(NotificationPlatform.Fcm).ToLower(), NotificationPlatform.Fcm } }; } public async Task<bool> CreateOrUpdateInstallationAsync(DeviceInstallation deviceInstallation, CancellationToken token) { if (string.IsNullOrWhiteSpace(deviceInstallation?.InstallationId) || string.IsNullOrWhiteSpace(deviceInstallation?.Platform) || string.IsNullOrWhiteSpace(deviceInstallation?.PushChannel)) return false; var installation = new Installation() { InstallationId = deviceInstallation.InstallationId, PushChannel = deviceInstallation.PushChannel, Tags = deviceInstallation.Tags }; if (_installationPlatform.TryGetValue(deviceInstallation.Platform, out var platform)) installation.Platform = platform; else return false; try { await _hub.CreateOrUpdateInstallationAsync(installation, token); } catch { return false; } return true; } public async Task<bool> DeleteInstallationByIdAsync(string installationId, CancellationToken token) { if (string.IsNullOrWhiteSpace(installationId)) return false; try { await _hub.DeleteInstallationAsync(installationId, token); } catch { return false; } return true; } public async Task<bool> RequestNotificationAsync(NotificationRequest notificationRequest, CancellationToken token) { if ((notificationRequest.Silent && string.IsNullOrWhiteSpace(notificationRequest?.Action)) || (!notificationRequest.Silent && (string.IsNullOrWhiteSpace(notificationRequest?.Text)) || string.IsNullOrWhiteSpace(notificationRequest?.Action))) return false; var androidPushTemplate = notificationRequest.Silent ? PushTemplates.Silent.Android : PushTemplates.Generic.Android; var iOSPushTemplate = notificationRequest.Silent ? PushTemplates.Silent.iOS : PushTemplates.Generic.iOS; var androidPayload = PrepareNotificationPayload( androidPushTemplate, notificationRequest.Text, notificationRequest.Action); var iOSPayload = PrepareNotificationPayload( iOSPushTemplate, notificationRequest.Text, notificationRequest.Action); try { if (notificationRequest.Tags.Length == 0) { // This will broadcast to all users registered in the notification hub await SendPlatformNotificationsAsync(androidPayload, iOSPayload, token); } else if (notificationRequest.Tags.Length <= 20) { await SendPlatformNotificationsAsync(androidPayload, iOSPayload, notificationRequest.Tags, token); } else { var notificationTasks = notificationRequest.Tags .Select((value, index) => (value, index)) .GroupBy(g => g.index / 20, i => i.value) .Select(tags => SendPlatformNotificationsAsync(androidPayload, iOSPayload, tags, token)); await Task.WhenAll(notificationTasks); } return true; } catch (Exception e) { _logger.LogError(e, "Unexpected error sending notification"); return false; } } string PrepareNotificationPayload(string template, string text, string action) => template .Replace("$(alertMessage)", text, StringComparison.InvariantCulture) .Replace("$(alertAction)", action, StringComparison.InvariantCulture); Task SendPlatformNotificationsAsync(string androidPayload, string iOSPayload, CancellationToken token) { var sendTasks = new Task[] { _hub.SendFcmNativeNotificationAsync(androidPayload, token), _hub.SendAppleNativeNotificationAsync(iOSPayload, token) }; return Task.WhenAll(sendTasks); } Task SendPlatformNotificationsAsync(string androidPayload, string iOSPayload, IEnumerable<string> tags, CancellationToken token) { var sendTasks = new Task[] { _hub.SendFcmNativeNotificationAsync(androidPayload, tags, token), _hub.SendAppleNativeNotificationAsync(iOSPayload, tags, token) }; return Task.WhenAll(sendTasks); } } }
Hinweis
Der für SendTemplateNotificationAsync bereitgestellte Tagausdruck ist auf 20 Tags beschränkt. Er ist für die meisten Operatoren auf 6 beschränkt, aber der Ausdruck enthält in diesem Fall nur ORs (||). Wenn die Anforderung mehr als 20 Tags enthält, müssen sie in mehrere Anforderungen unterteilt werden. Weitere Informationen finden Sie in der Dokumentation zu Routing- und Tagausdrücken .
Aktualisieren Sie in Startup.cs die ConfigureServices-Methode , um NotificationHubsService als Singletonimplementierung von INotificationService hinzuzufü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
Steuerung + Klicken Sie auf den Ordner Controller, und wählen Sie dann Im Menü Hinzufügen die Option Neue Datei... aus.
Wählen Sie ASP.NET Core>Web-API-Controller-Klasse aus, geben Sie NotificationsController als Namen ein, und klicken Sie dann auf Neu.
Hinweis
Wenn Sie visual Studio 2019 verwenden, wählen Sie die Api Controller-Vorlage mit Lese-/Schreibaktionen 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 }
Hinweis
Die Controller-Basisklasse bietet Unterstützung für Ansichten, dies ist in diesem Fall jedoch nicht erforderlich, sodass stattdessen ControllerBase verwendet werden kann. Wenn Sie visual Studio 2019 verwenden, können Sie diesen Schritt überspringen.
Wenn Sie den Abschnitt Authentifizieren von Clients mithilfe eines API-Schlüssels abgeschlossen haben, sollten Sie auch den NotificationsController mit dem Attribut Authorize versehen.
[Authorize]
Aktualisieren Sie den Konstruktor, um die registrierte instance von INotificationService als Argument zu akzeptieren, und weisen Sie es einem schreibgeschützten Member zu.
readonly INotificationService _notificationService; public NotificationsController(INotificationService notificationService) { _notificationService = notificationService; }
Ändern Sie in launchSettings.json (im Ordner Eigenschaften ) die launchUrl von in
weatherforecast
api/notifications , um der URL zu entsprechen, die im Attribut "RegistrationsControllerRoute " angegeben ist.Starten Sie das Debuggen (Befehlseingabe + ), um zu überprüfen, ob die App mit dem neuen NotificationsController funktioniert, und gibt einen nicht autorisierten status 401 zurück.
Hinweis
Visual Studio startet die App möglicherweise nicht automatisch im Browser. Ab diesem Zeitpunkt verwenden Sie Postman , um die API zu testen.
Legen Sie auf einer neuen Postman-Registerkarte die Anforderung auf GET fest. Geben Sie die folgende Adresse ein, und ersetzen Sie den Platzhalter <applicationUrl> durch den https applicationUrl in Properties>launchSettings.json.
<applicationUrl>/api/notifications
Hinweis
ApplicationUrl sollte für das Standardprofil "https://localhost:5001" sein. Wenn Sie IIS verwenden (Standard in Visual Studio 2019 unter Windows), sollten Sie stattdessen die im element iisSettings angegebene applicationUrl verwenden. Sie erhalten eine Antwort 404, wenn die Adresse falsch ist.
Wenn Sie den Abschnitt Authentifizieren von Clients mithilfe eines API-Schlüssels abgeschlossen haben, müssen Sie die Anforderungsheader so konfigurieren, dass sie Ihren apikey-Wert enthalten.
Schlüssel Wert apikey <your_api_key> Klicken Sie auf die Schaltfläche Senden .
Hinweis
Sie sollten eine 200 OK-status mit JSON-Inhalten erhalten.
Wenn Sie eine SSL-Zertifikatüberprüfungswarnung erhalten, können Sie die Postman-Einstellung SSL-Zertifikatüberprüfung der Anforderung in den Einstellungen deaktivieren.
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 jetzt eine API-App in Azure App Service zum Hosten des Back-End-Diensts.
Melden Sie sich beim Azure-Portal an.
Klicken Sie auf Ressource erstellen, suchen Sie nach API-App, und wählen Sie sie 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 Zielabonnement aus, in dem Sie den Notification Hub erstellt haben.Ressourcengruppe:
Wählen Sie dieselbe Ressourcengruppe aus, in der Sie den Notification Hub erstellt haben.App Service Plan/Standort:
Erstellen eines neuen App Service PlansHinweis
Ändern 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 unternehmen, 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.Navigieren Sie nach der Bereitstellung der API-App zu dieser Ressource.
Notieren Sie sich die URL-Eigenschaft in der Zusammenfassung der Grundlagen oben in der Übersicht. Diese URL ist Ihr Back-End-Endpunkt , der später in diesem Tutorial verwendet wird.
Hinweis
Die URL verwendet den zuvor angegebenen API-App-Namen im Format
https://<app_name>.azurewebsites.net
.Wählen Sie in der Liste (unter Einstellungen) die Option Konfiguration aus.
Klicken Sie für jede der folgenden Einstellungen auf Neue Anwendungseinstellung , um den Namen und einen Wert einzugeben, und klicken Sie dann auf OK.
NAME Wert Authentication:ApiKey
<api_key_value> NotificationHub:Name
<hub_name_value> NotificationHub:ConnectionString
<hub_connection_string_value> Hinweis
Dies sind dieselben Einstellungen, die Sie zuvor in den Benutzereinstellungen definiert haben. Sie sollten in der Lage sein, diese zu kopieren. Die Einstellung Authentication:ApiKey ist nur erforderlich, wenn Sie den Abschnitt Authentifizieren von Clients mithilfe eines API-Schlüssels abgeschlossen haben. Für Produktionsszenarien können Sie Optionen wie Azure KeyVault anzeigen. Diese wurden der Einfachheit halber in diesem Fall als Anwendungseinstellungen hinzugefügt.
Nachdem alle Anwendungseinstellungen hinzugefügt wurden, klicken Sie auf Speichern und dann auf Weiter.
Veröffentlichen des Back-End-Diensts
Als Nächstes stellen Sie die App in der API-App bereit, damit sie von allen Geräten aus zugänglich ist.
Hinweis
Die folgenden Schritte sind spezifisch für Visual Studio für Mac. Wenn Sie Visual Studio 2019 unter Windows verwenden, unterscheidet sich der Veröffentlichungsablauf. Weitere Informationen finden Sie unter Veröffentlichen in Azure App Service unter Windows.
Ändern Sie Ihre Konfiguration von Debuggen in Release , wenn Sie dies noch nicht getan haben.
Steuerung + Klicken Sie auf das Projekt PushDemoApi, und wählen Sie dann im Menü Veröffentlichen die Option In Azure veröffentlichen... aus.
Befolgen Sie den Authentifizierungsflow, wenn Sie dazu aufgefordert werden. Verwenden Sie das Konto, das Sie im vorherigen Erstellen des Abschnitts API-App verwendet haben.
Wählen Sie die Azure App Service API-App, die Sie zuvor erstellt haben, aus der Liste als Veröffentlichungsziel aus, 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 Sie dies noch nicht getan haben. Diese URL ist Ihr Back-End-Endpunkt , der später in diesem Tutorial verwendet wird.
Überprüfen der veröffentlichten API
Öffnen Sie in Postman eine neue Registerkarte, 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 Abschnitt zum Veröffentlichen des Back-End-Diensts notieren haben.
https://<app_name>.azurewebsites.net/api/notifications/installations
Hinweis
Die Basisadresse sollte das Format aufweisen.
https://<app_name>.azurewebsites.net/
Wenn Sie den Abschnitt Authentifizieren von Clients mithilfe eines API-Schlüssels abgeschlossen haben, müssen Sie die Anforderungsheader so konfigurieren, dass sie Ihren apikey-Wert enthalten.
Schlüssel Wert apikey <your_api_key> Wählen Sie die Raw-Option für den Text aus, wählen Sie dann JSON aus der Liste der Formatoptionen aus, und fügen Sie dann einige Platzhalter-JSON-Inhalte ein:
{}
Klicken Sie auf Send.
Hinweis
Sie sollten eine 422 UnprocessableEntity-status vom Dienst erhalten.
Führen Sie die Schritte 1 bis 4 erneut aus, aber geben Sie diesmal den Anforderungsendpunkt an, um zu überprüfen, dass Sie eine Antwort mit 400 fehlerhaften Anforderungen erhalten.
https://<app_name>.azurewebsites.net/api/notifications/requests
Hinweis
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 Flutter-Anwendung
In diesem Abschnitt erstellen Sie eine mobile Flutter-Anwendung , die Pushbenachrichtigungen plattformübergreifend implementiert.
Sie können sich über den von Ihnen erstellten Back-End-Dienst bei einem Notification Hub registrieren und die Registrierung aufheben.
Eine Warnung wird angezeigt, wenn eine Aktion angegeben wird und sich die App im Vordergrund befindet. Andernfalls werden Benachrichtigungen im Notification Center angezeigt.
Hinweis
In der Regel führen Sie die Registrierungsaktionen (und die Registrierung aufheben) während des entsprechenden Punkts im Anwendungslebenszyklus (oder vielleicht als Teil Ihrer Ersten Ausführung) ohne explizite Benutzerregistrierungs-/Deregistrierungseingaben aus. Dieses Beispiel erfordert jedoch eine explizite Benutzereingabe, damit diese Funktionalität leichter untersucht und getestet werden kann.
Erstellen der Flutter-Lösung
Öffnen Sie eine neue instance von Visual Studio Code.
Öffnen Sie die Befehlspalette (Umschaltbefehl + + P).
Wählen Sie den Befehl Flutter: Neues Projekt aus, und drücken Sie dann die EINGABETASTE.
Geben Sie als Projektnamepush_demo ein, und wählen Sie dann einen Projektspeicherort aus.
Wenn Sie dazu aufgefordert werden, wählen Sie Pakete abrufen aus.
Steuerung + Klicken Sie auf den Ordner kotlin (unter app>src>Standard), und wählen Sie dann Im Finder anzeigen aus. Benennen Sie dann die untergeordneten Ordner (unter dem Ordner kotlin) in ,
<your_organization>
bzwpushdemo
. umcom
.Hinweis
Wenn Sie die Visual Studio Code-Vorlage verwenden, wird für diese Ordner standardmäßig com verwendet, z. B<. project_name>. Wenn mobcat für die organization verwendet wird, sollte die Ordnerstruktur indikativ wie folgt aussehen:
- kotlin
- Com
- mobcat
- pushdemo
- mobcat
- Com
- kotlin
Aktualisieren Sie in Visual Studio Code den Wert applicationId in der Android-App>>build.gradle auf
com.<your_organization>.pushdemo
.Hinweis
Sie sollten Ihren eigenen organization Namen für den <your_organization> Platzhalter verwenden. Die Verwendung von mobcat als organization führt beispielsweise zu einem Paketnamenswertvon com.mobcat.pushdemo.
Aktualisieren Sie das Paketattribute in den AndroidManifest.xml-Dateien unter src>debug, src>Standard bzw. src-Profil>. Stellen Sie sicher, dass die Werte mit der applicationId übereinstimmen, die 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>Standard in PushDemo. Fügen Sie dann dasandroid:allowBackup
Attribut direkt unterandroid:label
hinzu, und legen Sie seinen Wert auf false fest.<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 (Android-App>>build.gradle), und aktualisieren Sie dann compileSdkVersion (aus dem Android-Abschnitt), um API 29 zu verwenden. Aktualisieren Sie dann die Werte minSdkVersion und targetSdkVersion (aus dem Abschnitt defaultConfig ) auf 26 bzw. 29 .
Hinweis
Nur Geräte mit API-Ebene 26 und höher werden für die Zwecke dieses Tutorials unterstützt. Sie können es jedoch erweitern, um Geräte zu unterstützen, auf denen ältere Versionen ausgeführt werden.
Steuerung + Klicken Sie auf den Ordner ios , und wählen Sie dann In Xcode öffnen aus.
Klicken Sie in Xcode auf Runner (das xcodeproj oben, nicht auf den Ordner). Wählen Sie dann das Ziel Runner aus, und wählen Sie die Registerkarte Allgemein aus. Aktualisieren Sie den Bundle-Bezeichner
com.<your_organization>.PushDemo
auf, wenn die Konfiguration "Alle Build" ausgewählt ist.Hinweis
Sie sollten Ihren eigenen organization Namen für den <your_organization> Platzhalter verwenden. Die Verwendung von mobcat als organization führt beispielsweise zu einem Bundle Identifier-Wert von com.mobcat.PushDemo.
Klicken Sie auf Info.plist, und aktualisieren Sie den Wert des Bundlenamens auf PushDemo.
Schließen Sie Xcode , und kehren Sie zu Visual Studio Code zurück.
Öffnen Sie wieder in Visual Studio Codepubspec.yaml, fügen Sie die pakete http und flutter_secure_storageDart 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 im Terminal das Verzeichnis in den Ordner ios (für Ihr Flutter-Projekt). Führen Sie dann den Befehl Podinstallation aus, um neue Pods zu installieren (erforderlich für das flutter_secure_storage-Paket ).
Steuerung + Klicken Sie auf den Ordner lib , und wählen Sie dann Neue Datei aus dem Menü mit main_page.dart als Dateinamen aus. 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 Standard.dart den 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 und führen Sie die App im Terminal auf jeder Zielplattform aus, um die Ausführung der app-Vorlagen auf Ihrem(n) Gerät(n) zu testen. Stellen Sie sicher, dass unterstützte Geräte verbunden sind.
flutter run
Implementieren der plattformübergreifenden Komponenten
Steuerung + Klicken Sie auf den Ordner lib, und wählen Sie dann Im Menü mit Modellen als Ordnername die Option Neuer Ordner aus.
Steuerung + Klicken Sie auf den Ordner models , und wählen Sie dann Neue Datei im Menü 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 dem Ordner models eine neue Datei mit dem Namen push_demo_action.dart hinzu, um die Enumeration der in diesem Beispiel unterstützten Aktionen zu definieren.
enum PushDemoAction { actionA, actionB, }
Fügen Sie dem Projekt einen neuen Ordner namens Services hinzu, und fügen Sie dann mit der folgenden Implementierung eine neue Datei mit dem Namen device_installation_service.dart zu diesem Ordner 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); } }
Hinweis
Sie sollten Ihren eigenen organization Namen für den <your_organization> Platzhalter verwenden. Die Verwendung von mobcat als organization führt beispielsweise zu einem MethodChannel-Namenvon com.mobcat.pushdemo/deviceinstallation.
Diese Klasse kapselt die Arbeit mit der zugrunde liegenden nativen Plattform, um die erforderlichen Geräteinstallationsdetails zu erhalten. Ein MethodChannel erleichtert die bidirektionale asynchrone Kommunikation mit den zugrunde liegenden nativen Plattformen. Das plattformspezifische Pendant für diesen Kanal wird in den späteren Schritten erstellt.
Fügen Sie diesem Ordner mit der folgenden Implementierung eine weitere Datei namens notification_action_service.dart 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; } } }
Hinweis
Dies wird als einfacher Mechanismus verwendet, um die Verarbeitung von Benachrichtigungsaktionen zu zentralisieren, sodass diese plattformübergreifend mithilfe einer stark typisierten Enumeration verarbeitet werden können. Der Dienst ermöglicht es der zugrunde liegenden nativen Plattform, eine Aktion auszulösen, wenn eine in der Benachrichtigungsnutzlast angegeben ist. Außerdem kann der allgemeine Code rückwirkend überprüfen, ob eine Aktion während des Anwendungsstarts angegeben wurde, sobald Flutter bereit ist, sie zu verarbeiten. Beispielsweise, wenn die App gestartet wird, indem Sie im Notification Center auf eine Benachrichtigung tippen.
Fügen Sie dem Dienstordnernotification_registration_service.dart mit der folgenden Implementierung eine neue Datei 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; } } }
Hinweis
Diese Klasse kapselt die Verwendung von DeviceInstallationService und die Anforderungen an den Back-End-Dienst zum Ausführen der erforderlichen Registrierungs-, Deregistrierungs- und Aktualisierungsaktionen. Das apiKey-Argument ist nur erforderlich, wenn Sie den Abschnitt Authentifizieren von Clients mithilfe eines API-Schlüssels abgeschlossen haben.
Fügen Sie dem lib-Ordnerconfig.dart mit der folgenden Implementierung eine neue Datei hinzu.
class Config { static String apiKey = "API_KEY"; static String backendServiceEndpoint = "BACKEND_SERVICE_ENDPOINT"; }
Hinweis
Dies wird als einfache Möglichkeit zum Definieren von App-Geheimnissen verwendet. Ersetzen Sie die Platzhalterwerte durch Ihre eigenen Werte. Sie sollten sich diese beim Erstellen des Back-End-Diensts notieren. Die API-App-URL sollte sein
https://<api_app_name>.azurewebsites.net/
. Das apiKey-Element ist nur erforderlich, wenn Sie den Abschnitt Authentifizieren von Clients mithilfe eines API-Schlüssels abgeschlossen haben.Fügen Sie dies ihrer gitignore-Datei hinzu, um zu vermeiden, dass diese Geheimnisse an die Quellcodeverwaltung übergeben werden.
Implementieren der plattformübergreifenden Benutzeroberfläche
Ersetzen Sie in main_page.dart die Buildfunktion 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 _MainPageState-Klasse ein Feld hinzu, um einen Verweis auf den NotificationRegistrationService zu speichern.
final notificationRegistrationService = NotificationRegistrationService(Config.backendServiceEndpoint, Config.apiKey);
Implementieren Sie in der _MainPageState-Klasse die Ereignishandler für die Schaltflächen Registrieren und Registrieren aufhebenfür Komprimierte Ereignisse. Rufen Sie die entsprechendenRegister-Deregistrierungsmethoden/ auf, und zeigen Sie dann eine Warnung an, um das Ergebnis anzugeben.
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 nun in Standard.dart sicher, dass die folgenden Importe oben in 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, um den Verweis auf eine instance von NotificationActionService zu speichern, 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 Standard-Funktion, um die NotificationActionService-AktionTriggered-Stream zu beobachten, und überprüfen Sie, ob alle Aktionen 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(); }
Hinweis
Dies ist einfach, um den Empfang und die Weitergabe von Pushbenachrichtigungsaktionen zu veranschaulichen. In der Regel werden diese im Hintergrund behandelt, z. B. beim Navigieren zu einer bestimmten Ansicht oder beim Aktualisieren einiger Daten, anstatt in diesem Fall eine Warnung anzuzeigen.
Konfigurieren des nativen Android-Projekts für Pushbenachrichtigungen
Hinzufügen der JSON-Datei von Google Services
Steuerung + Klicken Sie auf den Android-Ordner , und wählen Sie dann In Android Studio öffnen aus. Wechseln Sie dann zur Projektansicht (sofern noch nicht vorhanden).
Suchen Sie die google-services.json-Datei , die Sie zuvor heruntergeladen haben, als Sie das PushDemo-Projekt in der Firebase-Konsole eingerichtet haben. Ziehen Sie es dann in das Stammverzeichnis des App-Moduls (Android-Android-App>).>
Konfigurieren von Buildeinstellungen und -berechtigungen
Wechseln Sie die Projektansicht auf Android.
Öffnen Sie AndroidManifest.xml, fügen Sie dann das INTERNET hinzu und READ_PHONE_STATE Berechtigungen nach dem Anwendungselement vor dem schließenden Tag.
<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 Studio die Datei build.gradle auf Projektebene (Gradle Scripts>build.gradle (Project: android)). und stellen Sie sicher, dass Sie über den Klassenpfad "com.google.gms:google-services" im
buildscript
>Knoten "Abhängigkeiten " 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 // ... } }
Hinweis
Stellen Sie sicher, dass Sie gemäß den Anweisungen in der Firebase-Konsole beim Erstellen des Android-Projekts auf die neueste Version verweisen.
Wenden Sie in der Datei build.gradle auf App-Ebene (Gradle Scripts>build.gradle (Modul: app)) das Google Services Gradle-Plug-In an. 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 im Knoten "Abhängigkeiten" die Abhängigkeit für die Cloud Messaging-Android-Bibliothek hinzu.
dependencies { // ... implementation 'com.google.firebase:firebase-messaging:20.2.0' }
Hinweis
Stellen Sie sicher, dass Sie auf die neueste Version gemäß der Cloud Messaging Android-Clientdokumentation verweisen.
Speichern Sie die Änderungen, und klicken Sie dann auf die Schaltfläche Jetzt synchronisieren (in der Symbolleistenaufforderung) oder Auf Projekt mit Gradle-Dateien synchronisieren.
Behandeln von Pushbenachrichtigungen für Android
Klicken Sie in Android Studiomit Steuerelement + Klicken Sie auf den Paketordner com.your_organization.pushdemo<> (app>src>Standard>kotlin), und wählen Sie im Menü Neu die Option Paket aus. Geben Sie Dienste als Namen ein, und drücken Sie dann die EINGABETASTE.
Steuerung + Klicken Sie auf den Ordner dienste , und wählen Sie kotlin File/Class aus dem Menü Neu aus. Geben Sie DeviceInstallationService als Namen ein, und drücken Sie dann die EINGABETASTE.
Implementieren Sie 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" } }
Hinweis
Diese Klasse implementiert das plattformspezifische Pendant für den
com.<your_organization>.pushdemo/deviceinstallation
Kanal. Dies wurde im Bereich "Flutter" der App in DeviceInstallationService.dart definiert. In diesem Fall werden die Aufrufe vom allgemeinen Code an den nativen Host ausgeführt. Ersetzen Sie <unbedingt your_organization> durch Ihre eigenen organization, wo immer dies verwendet wird.Diese Klasse stellt eine eindeutige ID (mit Secure.AndroidId) als Teil der Notification Hub-Registrierungsnutzlast bereit.
Fügen Sie dem DienstordnerNotificationRegistrationService eine weitere Kotlin-Datei/Klasse 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) } }
Hinweis
Diese Klasse implementiert das plattformspezifische Pendant für den
com.<your_organization>.pushdemo/notificationregistration
Kanal. Dies wurde im Bereich "Flutter" der App in NotificationRegistrationService.dart definiert. In diesem Fall werden die Aufrufe vom nativen Host an den allgemeinen Code ausgeführt. Achten Sie auch hier darauf, your_organization> durch Ihre eigenen organization zu ersetzen<, wo immer dies verwendet wird.Fügen Sie dem DienstordnerNotificationActionService eine weitere Kotlin-Datei/Klasse 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() } } } }
Hinweis
Diese Klasse implementiert das plattformspezifische Pendant für den
com.<your_organization>.pushdemo/notificationaction
Kanal. Dies wurde im Flutter-Teil der App in NotificationActionService.dart definiert. Anrufe können in diesem Fall in beide Richtungen erfolgen. Ersetzen Sie <unbedingt your_organization> durch Ihre eigenen organization, wo immer dies verwendet wird.Fügen Sie dem com.your_organization.pushdemo-Paket<> eine neue Kotlin-Datei/Klasse namens PushNotificationsFirebaseMessagingService hinzu, und 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)) } } } }
Hinweis
Diese Klasse ist für die Verarbeitung von Benachrichtigungen zuständig, wenn die App im Vordergrund ausgeführt wird. Es ruft die triggerAction für den NotificationActionService bedingt auf, wenn eine Aktion in der Benachrichtigungsnutzlast enthalten ist, die in onMessageReceived empfangen wird. Dadurch wird auch refreshRegistration für den NotificationRegistrationService aufgerufen, wenn das Firebase-Token durch Überschreiben der onNewToken-Funktion neu generiert wird.
Achten Sie erneut darauf, your_organization> durch Ihre eigene organization zu ersetzen<, wo immer sie verwendet wird.
Fügen Sie inAndroidManifest.xml (app>src>Standard) den PushNotificationsFirebaseMessagingService am unteren Rand des Anwendungselements mit dem
com.google.firebase.MESSAGING_EVENT
Absichtsfilter 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>
Zurück in DeviceInstallationService stellen Sie sicher, dass die folgenden Importe oben in der Datei vorhanden sind.
package com.<your_organization>.pushdemo import com.<your_organization>.pushdemo.services.PushNotificationsFirebaseMessagingService
Hinweis
Ersetzen Sie <your_organization> durch Ihren eigenen organization Wert.
Aktualisieren Sie den Platzhaltertext Placeholder_Get_Value_From_FirebaseMessagingService_Implementation , um den Tokenwert von 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 MainActivity sicher, dass die folgenden Importe oben in 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
Hinweis
Ersetzen Sie <your_organization> durch Ihren eigenen organization Wert.
Fügen Sie eine Variable hinzu, um einen Verweis auf DeviceInstallationService zu speichern.
private lateinit var deviceInstallationService: DeviceInstallationService
Fügen Sie eine Funktion namens processNotificationActions hinzu, um zu überprüfen, ob eine Absicht über einen zusätzlichen Wert namens action verfügt. Lösen Sie diese Aktion bedingt aus, oder speichern Sie sie zur späteren Verwendung, 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 processNotificationActions aufzurufen.
override fun onNewIntent(intent: Intent) { super.onNewIntent(intent) processNotificationActions(intent) }
Hinweis
Da LaunchMode für MainActivity auf SingleTop festgelegt ist, wird eine Absicht über die onNewIntent-Funktion und nicht über die onCreate-Funktion an die vorhandene Aktivität instance gesendet. Daher müssen Sie eine eingehende Absicht sowohl in den Funktionen onCreate als auch onNewIntent behandeln.
Überschreiben Sie die onCreate-Funktion, und legen Sie deviceInstallationService auf eine neue instance 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 PushNotificationFirebaseMessagingServices fest.
flutterEngine?.let { deviceInstallationService = DeviceInstallationService(context, it) PushNotificationsFirebaseMessagingService.notificationActionService = NotificationActionService(it) PushNotificationsFirebaseMessagingService.notificationRegistrationService = NotificationRegistrationService(it) }
Rufen Sie in derselben Funktion bedingt FirebaseInstanceId.getInstance().instanceId auf. Implementieren Sie OnCompleteListener , um den resultierenden Tokenwert auf PushNotificationFirebaseMessagingService festzulegen, bevor sie refreshRegistration aufrufen.
if(deviceInstallationService?.playServicesAvailable) { FirebaseInstanceId.getInstance().instanceId .addOnCompleteListener(OnCompleteListener { task -> if (!task.isSuccessful) return@OnCompleteListener PushNotificationsFirebaseMessagingService.token = task.result?.token PushNotificationsFirebaseMessagingService.notificationRegistrationService?.refreshRegistration() }) }
Rufen Sie noch onCreate auf, rufen Sie processNotificationActions 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)
Hinweis
Sie müssen die App jedes Mal neu registrieren, wenn Sie sie ausführen, und sie in einer Debugsitzung beenden, um weiterhin Pushbenachrichtigungen zu erhalten.
Konfigurieren des nativen iOS-Projekts für Pushbenachrichtigungen
Konfigurieren des Runnerziels und info.plist
Klicken Sie in Visual Studio Codesteuerelement + Klicken Sie auf den Ordner ios , und wählen Sie dann In Xcode öffnen aus.
Klicken Sie in Xcode auf Runner (das xcodeproj oben, nicht auf den Ordner), wählen Sie dann das Runner-Ziel und dann Signieren & Funktionen aus. Wählen Sie bei ausgewählter Alle Buildkonfiguration Ihr Entwicklerkonto für das Team aus. Stellen Sie sicher, dass die Option "Signatur automatisch verwalten" aktiviert ist und Ihr Signaturzertifikat und Ihr Bereitstellungsprofil automatisch ausgewählt sind.
Hinweis
Wenn der neue Wert für das Bereitstellungsprofil nicht angezeigt wird, versuchen Sie, die Profile für die Signaturidentität zu aktualisieren, indem SieXcode-Einstellungskonto>> auswählen und dann die Schaltfläche Manuelle Profile herunterladen auswählen, um die Profile herunterzuladen.
Klicken Sie auf + Funktion, und suchen Sie dann nach Pushbenachrichtigungen. Doppelklicken Sie auf Pushbenachrichtigungen , um diese Funktion hinzuzufügen.
Öffnen Sie Info.plist , und legen Sie Mindestsystemversion auf 13.0 fest.
Hinweis
Nur Geräte mit iOS 13.0 und höher werden für die Zwecke dieses Tutorials unterstützt. Sie können es jedoch erweitern, um Geräte mit älteren Versionen zu unterstützen.
Öffnen Sie Runner.entitlements , und stellen Sie sicher, dass die Einstellung APS-Umgebung auf Entwicklung festgelegt ist.
Behandeln von Pushbenachrichtigungen für iOS
Steuerung + Klicken Sie auf den Ordner Runner (innerhalb des Runner-Projekts), und wählen Sie dann Neue Gruppe mit Diensten als Namen aus.
Steuerung + Klicken Sie auf den Ordner Dienste , und wählen Sie dann Neue Datei... aus. Wählen Sie dann Swift File (Swift File) aus, und klicken Sie auf Weiter. Geben Sie DeviceInstallationService als Namen an, und klicken Sie dann auf Erstellen.
Implementieren Sie DeviceInstallationService.swift mit dem folgenden Code.
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." } }
Hinweis
Diese Klasse implementiert das plattformspezifische Pendant für den
com.<your_organization>.pushdemo/deviceinstallation
Kanal. Dies wurde im Bereich "Flutter" der App in DeviceInstallationService.dart definiert. In diesem Fall werden die Aufrufe vom allgemeinen Code an den nativen Host ausgeführt. Ersetzen Sie <unbedingt your_organization> durch Ihre eigenen organization, wo immer dies verwendet wird.Diese Klasse stellt eine eindeutige ID (unter Verwendung des UIDevice.identifierForVendor-Werts ) als Teil der Notification Hub-Registrierungsnutzlast bereit.
Fügen Sie dem Ordner Services eine weitere Swift-Datei namens NotificationRegistrationService hinzu, 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) } }
Hinweis
Diese Klasse implementiert das plattformspezifische Pendant für den
com.<your_organization>.pushdemo/notificationregistration
Kanal. Dies wurde im Bereich "Flutter" der App in NotificationRegistrationService.dart definiert. In diesem Fall werden die Aufrufe vom nativen Host an den allgemeinen Code ausgeführt. Achten Sie auch hier darauf, your_organization> durch Ihre eigenen organization zu ersetzen<, wo immer dies verwendet wird.Fügen Sie dem Ordner Services eine weitere Swift-Datei namens NotificationActionService 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) } } }
Hinweis
Diese Klasse implementiert das plattformspezifische Pendant für den
com.<your_organization>.pushdemo/notificationaction
Kanal. Dies wurde im Flutter-Teil der App in NotificationActionService.dart definiert. Anrufe können in diesem Fall in beide Richtungen erfolgen. Ersetzen Sie <unbedingt your_organization> durch Ihre eigenen organization, wo immer dies verwendet wird.Fügen Sie in AppDelegate.swift Variablen 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 zur späteren Verwendung, 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 funktion didRegisterForRemoteNotificationsWithDeviceToken , die den Tokenwert für deviceInstallationService festlegt. Rufen Sie anschließend refreshRegistration auf notificationRegistrationService auf.
override func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) { deviceInstallationService?.token = deviceToken notificationRegistrationService?.refreshRegistration() }
Überschreiben Sie die didReceiveRemoteNotification-Funktion , die das userInfo-Argument an die processNotificationActions-Funktion übergibt.
override func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any]) { processNotificationActions(userInfo: userInfo) }
Überschreiben Sie die funktion didFailToRegisterForRemoteNotificationsWithError , um den Fehler zu protokollieren.
override func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) { print(error); }
Hinweis
Dies ist sehr viel ein Platzhalter. Sie sollten eine ordnungsgemäße Protokollierung und Fehlerbehandlung für Produktionsszenarien implementieren.
Instanziieren Sie in didFinishLaunchingWithOptions die Variablen deviceInstallationService, notificationRegistrationService und notificationActionService .
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 bedingt die Autorisierung 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 launchOptions den remoteNotification-Schlüssel enthält, rufen Sie processNotificationActions am Ende der funktion didFinishLaunchingWithOptions auf. Übergeben Sie das resultierende userInfo-Objekt , und verwenden Sie true für das launchAction-Argument . Ein true-Wert gibt 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 in Postman eine neue Registerkarte.
Legen Sie die Anforderung auf POST fest, und geben Sie die folgende Adresse ein:
https://<app_name>.azurewebsites.net/api/notifications/requests
Wenn Sie den Abschnitt Authentifizieren von Clients mithilfe eines API-Schlüssels abgeschlossen haben, müssen Sie die Anforderungsheader so konfigurieren, dass sie Ihren apikey-Wert enthalten.
Schlüssel Wert apikey <your_api_key> Wählen Sie die Raw-Option für den Text aus, wählen Sie dann JSON aus der Liste der Formatoptionen aus, und fügen Sie dann einige Platzhalter-JSON-Inhalte ein:
{ "text": "Message from Postman!", "action": "action_a" }
Wählen Sie die Schaltfläche Code aus, die sich unter der Schaltfläche Speichern oben rechts im Fenster befindet. Die Anforderung sollte ähnlich wie das folgende Beispiel aussehen, wenn sie für HTML angezeigt wird (je nachdem, ob Sie einen apikey-Header enthalten 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 (Android und iOS) aus.
Hinweis
Wenn Sie unter Android testen, stellen Sie sicher, dass Sie nicht in Debuggen ausgeführt werden, oder wenn die App bereitgestellt wurde, indem Sie die Anwendung ausführen, dann erzwingen Sie das Schließen der App, und starten Sie sie über das Startprogramm erneut.
Tippen Sie in der PushDemo-App auf die Schaltfläche Registrieren .
Zurück zu Postman, schließen Sie das Fenster Codeausschnitte generieren (falls sie dies noch nicht getan haben), 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 angezeigt wird, die AktionA-Aktion empfangen.
Schließen Sie die PushDemo-App, und klicken Sie dann in Postman erneut auf die Schaltfläche Senden.
Überprüfen Sie, ob Sie in Postman erneut eine Antwort mit 200 OK 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 die App geöffnet und die AktionA-Warnung empfangen wurde .
Ändern Sie zurück in Postman den vorherigen Anforderungstext, um eine unbeaufsichtigte Benachrichtigung zu senden, die action_b anstelle von action_a für den Aktionswert 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, die Die Aktion B-Aktion empfangen anstelle der empfangenen AktionA-Aktion anzeigt.
Schließen Sie die PushDemo-App, und klicken Sie dann in Postman erneut auf die Schaltfläche Senden.
Überprüfen Sie, ob Sie eine Antwort mit 200 OK in Postman erhalten und dass die unbeaufsichtigte Benachrichtigung nicht im Benachrichtigungsbereich angezeigt wird.
Problembehandlung
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 Sie mit der Azure-API-App testen, überprüfen Sie, ob der Dienst ausgeführt wird und bereitgestellt wurde und ohne Fehler gestartet wurde.
Vergewissern Sie sich, dass Sie die Basisadresse beim Testen über den Client in Postman oder in der Konfiguration der mobilen App korrekt angegeben haben. Die Basisadresse sollte indikativ oder beim lokalen Testen sein https://<api_name>.azurewebsites.net/
https://localhost:5001/
.
Keine 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. Auch die Notification Hub-Installation muss aktualisiert werden.
Empfangen eines 401-status-Codes vom Back-End-Dienst
Überprüfen Sie, ob Sie den apikey-Anforderungsheader festlegen und dieser Wert mit dem Wert übereinstimmt, 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 von der API verwendeten Wert für die Benutzereinstellung Authentication:ApiKey entspricht.
Wenn Sie mit einer API-App testen, stellen Sie sicher, dass der Schlüsselwert in der Clientkonfigurationsdatei der Anwendungseinstellung Authentication:ApiKey entspricht, die Sie in der API-App verwenden.
Hinweis
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 den Abschnitt Clients mithilfe eines API-Schlüssels authentifizieren nicht abschließen möchten, stellen Sie sicher, dass Sie das Authorize-Attribut nicht auf die NotificationsController-Klasse angewendet haben.
Empfangen eines 404-status-Codes vom Back-End-Dienst
Überprüfen Sie, ob der Endpunkt und die HTTP-Anforderungsmethode korrekt sind. Die Endpunkte sollten z. B. indikativ sein:
- [PUT]
https://<api_name>.azurewebsites.net/api/notifications/installations
- [LÖSCHEN]
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
- [LÖSCHEN]
https://localhost:5001/api/notifications/installations/<installation_id>
- [POST]
https://localhost:5001/api/notifications/requests
Wenn Sie die Basisadresse in der Client-App angeben, stellen Sie sicher, dass sie mit einem /
endet. Die Basisadresse sollte indikativ oder beim lokalen Testen sein https://<api_name>.azurewebsites.net/
https://localhost:5001/
.
Registrierung nicht möglich, und eine Notification Hub-Fehlermeldung wird angezeigt
Vergewissern Sie sich, dass das Testgerät über Netzwerkkonnektivität verfügt. Bestimmen Sie dann die HTTP-Antwort status Code, indem Sie einen Haltepunkt festlegen, um den StatusCode-Eigenschaftswert in der HttpResponse zu überprüfen.
Überprüfen Sie ggf. die vorherigen Problembehandlungsvorschläge basierend auf dem status Code.
Legen Sie einen Haltepunkt für die Zeilen fest, die diese spezifischen status Codes 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 über Postman mit der entsprechenden Nutzlast wie erwartet funktioniert. Verwenden Sie die tatsächliche Nutzlast, die vom Clientcode für die betreffende Plattform erstellt wurde.
Überprüfen Sie die abschnitte zur plattformspezifischen Konfiguration, 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.
Eine ID für die Angezeigte Gerätefehlermeldung kann nicht aufgelöst werden.
Überprüfen Sie die abschnitte zur plattformspezifischen Konfiguration, um sicherzustellen, dass keine Schritte verpasst wurden.
Verwandte Links
- Übersicht über Azure Notification Hubs
- Installieren von Flutter unter macOS
- Installieren von Flutter unter Windows
- Notification Hubs SDK für Back-End-Vorgänge
- Notification Hubs-SDK auf GitHub
- Registrieren beim Anwendungs-Back-End
- Registrierungsverwaltung
- Arbeiten mit Tags
- Arbeiten mit benutzerdefinierten Vorlagen
Nächste Schritte
Sie sollten jetzt über eine einfache Flutter-App verfügen, die über einen Back-End-Dienst mit einem Notification Hub verbunden ist und Benachrichtigungen senden und empfangen kann.
Wahrscheinlich müssen Sie das in diesem Tutorial verwendete Beispiel an Ihr eigenes Szenario anpassen. Es wird auch empfohlen, eine robustere Fehlerbehandlung, Wiederholungslogik und Protokollierung zu implementieren.
Visual Studio App Center kann schnell in mobile Apps integriert werden, die Analysen und Diagnose bereitstellen, um die Problembehandlung zu unterstützen.