Samouczek: wysyłanie powiadomień wypychanych do aplikacji Flutter przy użyciu usługi Azure Notification Hubs za pośrednictwem usługi zaplecza
- zestawu narzędzi Xamarin.Forms
- Flutter
Natywna React
W tym samouczku użyjesz usługi Azure Notification Hubs do wypychania powiadomień do aplikacji Flutter przeznaczonej dla systemu Android i systemu iOS.
Zaplecze internetowego interfejsu API platformy
Te operacje są obsługiwane przy użyciu zestawu SDK usługi Notification Hubs na potrzeby operacji zaplecza. Dalsze szczegółowe informacje na temat ogólnego podejścia przedstawiono w dokumentacji Rejestrowanie z zaplecza aplikacji.
Ten samouczek zawiera następujące kroki:
- konfigurowanie usług powiadomień wypychanych i usługi Azure Notification Hubs.
- Tworzenie aplikacji zaplecza internetowego interfejsu API platformy ASP.NET Core.
- Tworzenie międzyplatformowej aplikacji Flutter.
- Skonfiguruj natywny projekt systemu Android na potrzeby powiadomień wypychanych.
- Konfigurowanie natywnego projektu systemu iOS na potrzeby powiadomień wypychanych.
- przetestować rozwiązanie.
Warunki wstępne
Aby wykonać następujące czynności, wymagane są następujące elementy:
- Subskrypcja platformy Azure , w której można tworzyć zasoby i zarządzać nimi.
- Zestaw narzędzi Flutter (wraz z wymaganiami wstępnymi).
programu Visual Studio Code z zainstalowanymi wtyczk ami Flutter i Dart. - cocoaPods zainstalowane na potrzeby zarządzania zależnościami biblioteki.
- Możliwość uruchamiania aplikacji na urządzeniach z systemem Android (fizycznych lub emulatorowych) lub systemu iOS (tylko urządzenia fizyczne).
W przypadku systemu Android musisz mieć następujące elementy:
- Odblokowane urządzenie fizyczne dewelopera lub emulator (z zainstalowanym interfejsem API 26 lub nowszym z zainstalowanymi usługami Google Play).
W przypadku systemu iOS musisz mieć następujące elementy:
- Aktywne konto dewelopera firmy Apple.
- Fizyczne urządzenie z systemem iOS zarejestrowane na koncie dewelopera(z systemem iOS 13.0 lub nowszym).
- Certyfikat dewelopera
.p12 zainstalowany w pęku kluczy umożliwia uruchamianie aplikacji na urządzeniu fizycznym .
Nuta
Symulator systemu iOS nie obsługuje powiadomień zdalnych, dlatego urządzenie fizyczne jest wymagane podczas eksplorowania tego przykładu w systemie iOS. Nie trzeba jednak uruchamiać aplikacji zarówno w android, jak i systemu iOS, aby ukończyć ten samouczek.
Możesz wykonać kroki opisane w tym przykładzie z pierwszymi zasadami bez wcześniejszego doświadczenia. Jednak skorzystasz z znajomości następujących aspektów.
- Portal dla deweloperów firmy Apple.
- ASP.NET Core.
- konsoli Google Firebase console.
- microsoft Azure i Wysyłanie powiadomień wypychanych do aplikacji systemu iOS przy użyciu usługi Azure Notification Hubs.
- Flutter i Dart na potrzeby programowania międzyplatformowego.
- Kotlin i Swift natywnych dla systemów Android i iOS.
Podane kroki dotyczą systemu macOS. W windows można śledzić, pomijając aspekty iOS.
Konfigurowanie usług powiadomień wypychanych i Usługi Azure Notification Hub
W tej sekcji skonfigurujesz usługę Firebase Cloud Messaging (FCM) i usług Apple Push Notification Services (APNS). Następnie utworzysz i skonfigurujesz centrum powiadomień do pracy z tymi usługami.
Tworzenie projektu Firebase i włączanie usługi Firebase Cloud Messaging dla systemu Android
Zaloguj się do konsoli programu Firebase. Utwórz nowy projekt Firebase wprowadzający PushDemo jako nazwę projektu .
Nuta
Zostanie wygenerowana unikatowa nazwa. Domyślnie składa się to z małego wariantu podanej nazwy oraz wygenerowanej liczby rozdzielonej kreską. Możesz to zmienić, jeśli chcesz podać, że jest ona nadal unikatowa globalnie.
Po utworzeniu projektu wybierz pozycję Dodaj bazę firebase do aplikacji systemu Android.
Na stronie Dodaj bazę firebase do aplikacji systemu Android wykonaj następujące kroki.
W polu nazwa pakietu systemu Android wprowadź nazwę pakietu. Na przykład:
com.<organization_identifier>.<package_name>
.Wybierz pozycję Zarejestruj aplikację.
Wybierz pozycję Pobierz google-services.json. Następnie zapisz plik w folderze lokalnym do późniejszego użycia i wybierz pozycję Dalej.
Wybierz pozycję Dalej.
Wybierz pozycję Kontynuuj, aby konsoli
Nuta
Jeśli przycisk Kontynuuj konsoli nie jest włączony, ponieważ sprawdzić instalacji, wybierz pozycję Pomiń ten krok.
W konsoli Firebase wybierz koła zębatego dla projektu. Następnie wybierz pozycję Ustawienia projektu.
Nuta
Jeśli nie pobrano pliku google-services.json, możesz go pobrać na tej stronie.
Przejdź do karty
Cloud Messaging u góry. Skopiuj i zapisz klucz serwerado późniejszego użycia. Ta wartość służy do konfigurowania centrum powiadomień.
Rejestrowanie aplikacji systemu iOS na potrzeby powiadomień wypychanych
Aby wysyłać powiadomienia wypychane do aplikacji systemu iOS, zarejestruj aplikację w usłudze Apple, a także zarejestruj się w celu otrzymywania powiadomień wypychanych.
Jeśli aplikacja nie została jeszcze zarejestrowana, przejdź do portalu aprowizacji systemu iOS w Centrum deweloperów firmy Apple. Zaloguj się do portalu przy użyciu identyfikatora Apple ID, przejdź do pozycji certyfikaty , identyfikatory & profile, a następnie wybierz pozycję identyfikatory . Kliknij +, aby zarejestrować nową aplikację.
Na ekranie Zarejestruj nowy identyfikator wybierz przycisk radiowy Identyfikatory aplikacji. Następnie wybierz pozycję Kontynuuj.
Zaktualizuj następujące trzy wartości dla nowej aplikacji, a następnie wybierz pozycję Kontynuuj:
Opis: wpisz opisową nazwę aplikacji.
identyfikator pakietu: wprowadź identyfikator pakietu formularza com.<organization_identifier>.<product_name> jak wspomniano w przewodniku dystrybucji aplikacji . Na poniższym zrzucie ekranu wartość
mobcat
jest używana jako identyfikator organizacji, a wartość PushDemo jest używana jako nazwa produktu.powiadomienia wypychane : sprawdź opcjępowiadomienia wypychane w sekcjiCapabilities (Możliwości ). formularz
Ta akcja generuje identyfikator aplikacji i żąda potwierdzenia informacji. Wybierz pozycję Kontynuuj, a następnie wybierz pozycję Zarejestruj, aby potwierdzić nowy identyfikator aplikacji.
nowego identyfikatora aplikacji
Po wybraniu pozycji
Zarejestruj zostanie wyświetlony nowy identyfikator aplikacji jako element wiersza na stronieCertificates, Identifiers & Profiles ( Identyfikatory & Profiles).
Na stronie Certificates (Certyfikaty) identyfikatory & Profiles w obszarze Identifiers (Identyfikatory) znajdź utworzony element wiersza Identyfikator aplikacji. Następnie wybierz wiersz, aby wyświetlić ekran Edytuj konfigurację identyfikatora aplikacji ekranu.
Tworzenie certyfikatu dla usługi Notification Hubs
Certyfikat jest wymagany, aby umożliwić centrum powiadomień pracę z usługą Apple Push Notification Services (APNS) i można je udostępnić na jeden z dwóch sposobów:
Tworzenie certyfikatu wypychania p12, który można przekazać bezpośrednio do usługi Notification Hub (oryginalne podejście)
Tworzenie certyfikatu p8, który może służyć do uwierzytelniania opartego na tokenach (nowsze i zalecane podejście)
Nowsze podejście ma wiele korzyści, jak opisano w uwierzytelnianie oparte na tokenach (HTTP/2) dla usługi APNS. Wymagana jest mniejsza liczba kroków, ale jest również wymagana w przypadku określonych scenariuszy. Jednak kroki zostały podane dla obu metod, ponieważ oba te metody będą działać na potrzeby tego samouczka.
OPCJA 1. Tworzenie certyfikatu wypychania p12, który można przekazać bezpośrednio do centrum powiadomień
Na komputerze Mac uruchom narzędzie Keychain Access. Można go otworzyć z folderu Utilities lub folderu Other na launchpad.
Wybierz dostępu do pęku kluczy, rozwiń Asystent certyfikatów, a następnie wybierz pozycję Zażądaj certyfikatu zurzędu certyfikacji.
Nuta
Domyślnie dostęp do pęku kluczy wybiera pierwszy element na liście. Może to być problem, jeśli jesteś w kategorii certyfikatów
i Urząd certyfikacji Relacji deweloperów firmy Apple nie jest pierwszym elementem na liście. Przed wygenerowaniem żądania CSR (żądanie podpisania certyfikatu) upewnij się, że masz element inny niż klucz lub urzędu certyfikacji Apple Worldwide Developer Relations Authority.Wybierzadres e-mail użytkownika
, wprowadź wartość nazwa pospolita, upewnij się, że określonoZapisano na dysku , a następnie wybierz pozycjęKontynuuj . Pozostaw adres e-mail urzędu certyfikacji puste, ponieważ nie jest to wymagane.Wprowadź nazwę pliku żądania podpisania certyfikatu (CSR) w Zapisz jakowybierz lokalizację w Gdzie, a następnie wybierz Zapisz.
certyfikatu
Ta akcja zapisuje plik CSR w wybranej lokalizacji. Domyślną lokalizacją jest Desktop. Zapamiętaj lokalizację wybraną dla pliku.
Po powrocie do strony Certificates, Identifiers & Profiles na stronie iOS Provisioning Portalprzewiń w dół do zaznaczonej opcji Wypychane powiadomienia, a następnie wybierz pozycję Konfiguruj, aby utworzyć certyfikat.
Zostanie wyświetlone okno Certyfikat y TLS/SSL usługi Apple Push Notification Service. Wybierz przycisk
Utwórz certyfikat w sekcjiProgramowanie certyfikatu TLS/SSL. Zostanie wyświetlony ekran tworzenie nowego certyfikatu
. Nuta
W tym samouczku jest używany certyfikat programowania. Ten sam proces jest używany podczas rejestrowania certyfikatu produkcyjnego. Podczas wysyłania powiadomień upewnij się, że używasz tego samego typu certyfikatu.
Wybierz pozycję Wybierz plik, przejdź do lokalizacji, w której zapisano plik CSR, a następnie kliknij dwukrotnie nazwę certyfikatu, aby go załadować. Następnie wybierz pozycję Kontynuuj.
Po utworzeniu certyfikatu w portalu wybierz przycisk Pobierz. Zapisz certyfikat i zapamiętaj lokalizację, do której został zapisany.
strona pobierania certyfikatu wygenerowanego
Certyfikat jest pobierany i zapisywany na komputerze w folderze Pobrane.
Nuta
Domyślnie pobrany certyfikat dewelopera ma nazwę aps_development.cer.
Kliknij dwukrotnie pobrany certyfikat wypychania aps_development.cer. Ta akcja powoduje zainstalowanie nowego certyfikatu w łańcucha kluczy, jak pokazano na poniższej ilustracji:
lista certyfikatów dostępu łańcucha kluczy certyfikatów
Nuta
Mimo że nazwa certyfikatu może być inna, nazwa będzie poprzedzona Apple Development iOS Push Services i ma skojarzony z nim odpowiedni identyfikator pakietu.
W obszarze Dostęp do pęku kluczy
Kontrola kliknij na nowym certyfikacie wypychania utworzonym w kategorii certyfikatów. Wybierz pozycję Eksportuj, nadaj plikowi nazwę, wybierz format p12, a następnie wybierz pozycję Zapisz. formatu p12
Możesz wybrać ochronę certyfikatu przy użyciu hasła, ale hasło jest opcjonalne. Kliknij przycisk OK, jeśli chcesz pominąć tworzenie haseł. Zanotuj nazwę pliku i lokalizację wyeksportowanego certyfikatu p12. Są one używane do włączania uwierzytelniania za pomocą usługi APNs.
Nuta
Nazwa i lokalizacja pliku p12 mogą być inne niż to, co zostało na zdjęciu w tym samouczku.
OPCJA 2: Tworzenie certyfikatu p8, który może być używany do uwierzytelniania opartego na tokenach
Zanotuj następujące szczegóły:
- prefiks identyfikatora aplikacji (identyfikator zespołu)
- identyfikator pakietu
Po powrocie do certyfikatów identyfikatory & Profileskliknij pozycję Keys.
Nuta
Jeśli masz już klucz skonfigurowany dla usługi APNS, możesz ponownie użyć certyfikatu p8 pobranego bezpośrednio po jego utworzeniu. Jeśli tak, możesz zignorować kroki 3 za pośrednictwem 5.
Kliknij przycisk + (lub przycisk Utwórz klucz), aby utworzyć nowy klucz.
Podaj odpowiednią wartość Nazwa klucza, a następnie zaznacz opcję Apple Push Notifications Service (APNS), a następnie kliknij przycisk Kontynuuj, a następnie Zarejestruj na następnym ekranie.
Kliknij Pobierz, a następnie przenieś plik p8 (poprzedzony AuthKey_) do bezpiecznego katalogu lokalnego, a następnie kliknij przycisk Gotowe.
Nuta
Pamiętaj, aby zachować plik p8 w bezpiecznym miejscu (i zapisać kopię zapasową). Po pobraniu klucza nie można go ponownie pobrać, ponieważ kopia serwera zostanie usunięta.
Na Kluczekliknij utworzony klucz (lub istniejący klucz, jeśli chcesz go użyć).
Zanotuj wartość identyfikatora klucza
. Otwórz certyfikat p8 w odpowiedniej wybranej aplikacji, takiej jak Visual Studio Code. Zanotuj wartość klucza (między kluczem prywatnym -----BEGIN----- a -----END PRIVATE KEY-----).
-----BEGIN KLUCZ PRYWATNY-----
<key_value>
-----END PRIVATE KEY-----Nuta
Jest to wartość tokenu , która będzie używana później do konfigurowania Notification Hub.
Na końcu tych kroków powinny być dostępne następujące informacje do późniejszego użycia w Konfigurowanie centrum powiadomień przy użyciu informacji usługi APNS:
- identyfikator zespołu (zobacz krok 1)
- identyfikator pakietu (zobacz krok 1)
- identyfikator klucza (zobacz krok 7)
- wartość tokenu (wartość klucza p8 uzyskana w kroku 8)
Tworzenie profilu aprowizacji dla aplikacji
Wróć do portalu aprowizacji systemu iOS, wybierz pozycję certyfikaty , identyfikatory & profile, wybierz pozycję profile z menu po lewej stronie, a następnie wybierz pozycję +, aby utworzyć nowy profil. Zostanie wyświetlony ekran Rejestrowanie nowego profilu aprowizacji.
Wybierz pozycję tworzenie aplikacji systemu iOS w obszarze Development jako typ profilu aprowizacji, a następnie wybierz pozycję Kontynuuj.
lista profilów aprowizacji
Następnie wybierz identyfikator aplikacji utworzony z listy rozwijanej Identyfikator aplikacji, a następnie wybierz pozycję Kontynuuj.
identyfikatora aplikacji
W oknie Wybierz certyfikaty wybierz certyfikat dewelopera używany do podpisywania kodu, a następnie wybierz pozycję Kontynuuj.
Nuta
Ten certyfikat nie jest certyfikatem wypychania utworzonym w poprzednim kroku . Jest to certyfikat dewelopera. Jeśli taki nie istnieje, musisz go utworzyć, ponieważ jest to wymagania wstępne dla tego samouczka. Certyfikaty deweloperów można utworzyć w witrynie Apple Developer Portalza pośrednictwem Xcode lub programu Visual Studio.
Wróć do strony certyfikatów , identyfikatorów & profilów, wybierz pozycję Profile z menu po lewej stronie, a następnie wybierz pozycję +, aby utworzyć nowy profil. Zostanie wyświetlony ekran Rejestrowanie nowego profilu aprowizacji.
W oknie Wybierz certyfikaty wybierz utworzony certyfikat dewelopera. Następnie wybierz pozycję Kontynuuj.
Następnie wybierz urządzenia do użycia do testowania, a następnie wybierz pozycję Kontynuuj.
Na koniec wybierz nazwę profilu w Nazwa profilu aprowizacji, a następnie wybierz pozycję Wygeneruj.
Po utworzeniu nowego profilu aprowizacji wybierz pozycję Pobierz. Zapamiętaj lokalizację, do której został zapisany.
Przejdź do lokalizacji profilu aprowizacji, a następnie kliknij go dwukrotnie, aby zainstalować go na maszynie dewelopera.
Tworzenie centrum powiadomień
W tej sekcji utworzysz centrum powiadomień i skonfigurujesz uwierzytelnianie za pomocą usługi APNS. Możesz użyć certyfikatu wypychania p12 lub uwierzytelniania opartego na tokenach. Jeśli chcesz użyć centrum powiadomień, które zostało już utworzone, możesz przejść do kroku 5.
Zaloguj się do usługi Azure.
Kliknij pozycję Utwórz zasób, a następnie wyszukaj i wybierz pozycję Notification Hub, a następnie kliknij pozycję Utwórz.
Zaktualizuj następujące pola, a następnie kliknij pozycję Utwórz:
PODSTAWOWE SZCZEGÓŁY
subskrypcja : wybierz docelową subskrypcję z listy rozwijanej
grupa zasobów: Utwórz nową grupę zasobów (lub wybierz istniejącą)SZCZEGÓŁY PRZESTRZENI NAZW
przestrzeń nazw centrum powiadomień: wprowadź globalnie unikatową nazwę Notification Hub przestrzeni nazw
Nuta
Upewnij się , że dla tego pola jest wybrana opcja Utwórz nowy.
SZCZEGÓŁY CENTRUM POWIADOMIEŃ
Notification Hub: wprowadź nazwę usługi Notification Hub
Lokalizacja: Wybierz odpowiednią lokalizację z listy rozwijanej
Warstwa cenowa: Zachowaj domyślną opcję BezpłatnaNuta
Chyba że osiągnięto maksymalną liczbę centrów w warstwie Bezpłatna.
Po aprowizowaniu usługi Notification Hub przejdź do tego zasobu.
Przejdź do nowego centrum powiadomień .
Wybierz zasady dostępu z listy (w obszarze ZARZĄDZAJ).
Zanotuj wartości nazwa zasad
wraz z odpowiednimi wartościami parametrów połączenia .
Konfigurowanie centrum powiadomień przy użyciu informacji usługi APNS
W obszarze Notification Serviceswybierz pozycję apple a następnie wykonaj odpowiednie kroki na podstawie podejścia wybranego wcześniej w sekcji Tworzenie certyfikatu dla usługi Notification Hubs.
Nuta
Użyj produkcyjnej dla trybu aplikacji tylko wtedy, gdy chcesz wysyłać powiadomienia wypychane do użytkowników, którzy kupili aplikację ze sklepu.
OPCJA 1: Używanie certyfikatu wypychania p12
Wybierz pozycję Certificate.
Wybierz ikonę pliku.
Wybierz wyeksportowany wcześniej plik p12, a następnie wybierz pozycję Otwórz.
W razie potrzeby określ poprawne hasło.
Wybierz tryb piaskownicy
. Wybierz pozycję Zapisz.
OPCJA 2: Używanie uwierzytelniania opartego na tokenach
Wybierz pozycję Token.
Wprowadź następujące wartości uzyskane wcześniej:
- identyfikator klucza
- identyfikator pakietu
- identyfikator zespołu
- tokenu
- identyfikator klucza
Wybierz pozycję Piaskownica.
Wybierz pozycję Zapisz.
Konfigurowanie centrum powiadomień przy użyciu informacji o usłudze FCM
- Wybierz pozycję
Google (GCM/FCM) w sekcji ustawieniaw menu po lewej stronie. - Wprowadź klucz serwera zanotowany w konsoli Google Firebase Console.
- Wybierz pozycję Zapisz na pasku narzędzi.
Tworzenie aplikacji zaplecza internetowego interfejsu API platformy ASP.NET Core
W tej sekcji utworzysz zaplecze internetowego interfejsu API
Tworzenie projektu internetowego
W programu Visual Studiowybierz pozycję plik >nowe rozwiązanie.
Wybierz pozycję .NET Core>App>ASP.NET Core>API>Next.
W oknie dialogowym Konfigurowanie nowego internetowego interfejsu API ASP.NET Core wybierz pozycję Target Framework platformy .NET Core 3.1.
Wprowadź PushDemoApi dla nazwa projektu, a następnie wybierz pozycję Utwórz.
Rozpocznij debugowanie (Command + Enter), aby przetestować aplikację szablonu.
Nuta
Aplikacja szablonu jest skonfigurowana do używania WeatherForecastController jako launchUrl. Jest on ustawiany w Właściwości>launchSettings.json.
Jeśli zostanie wyświetlony monit o znaleziono nieprawidłowy certyfikat programowania komunikat:
Kliknij przycisk Tak, aby wyrazić zgodę na uruchomienie narzędzia "dotnet dev-certs https", aby rozwiązać ten problem. Narzędzie "dotnet dev-certs https" wyświetli monit o wprowadzenie hasła do certyfikatu i hasła dla pęku kluczy.
Kliknij pozycję
Tak po wyświetleniu monitu oInstall and trust the new certificate (Zainstaluj i ufaj nowemu certyfikatowi), a następnie wprowadź hasło dla pęku kluczy.
Rozwiń folder kontrolerów , a następnie usuń WeatherForecastController.cs.
Usuń WeatherForecast.cs.
Skonfiguruj lokalne wartości konfiguracji przy użyciu narzędzia Secret Manager. Oddzielenie wpisów tajnych z rozwiązania gwarantuje, że nie zostaną one zakończone w kontroli źródła. Otwórz Terminal następnie przejdź do katalogu pliku projektu i uruchom następujące polecenia:
dotnet user-secrets init dotnet user-secrets set "NotificationHub:Name" <value> dotnet user-secrets set "NotificationHub:ConnectionString" <value>
Zastąp wartości symboli zastępczych własną nazwą centrum powiadomień i wartościami parametrów połączenia. Zanotuj je w sekcji tworzenia centrum powiadomień. W przeciwnym razie możesz wyszukać je w usłudze Azure.
NotificationHub:Name:
ZobaczName (Nazwa) w podsumowaniuEssentials w górnej części Overview .NotificationHub:ConnectionString:
Zobacz DefaultFullSharedAccessSignature w zasadach dostępuNuta
W przypadku scenariuszy produkcyjnych możesz zapoznać się z opcjami, takimi jak Azure KeyVault, aby bezpiecznie przechowywać parametry połączenia. Dla uproszczenia wpisy tajne zostaną dodane do ustawień aplikacji Azure App Service.
Uwierzytelnianie klientów przy użyciu klucza interfejsu API (opcjonalnie)
Klucze interfejsu API nie są tak bezpieczne jak tokeny, ale wystarczy do celów tego samouczka. Klucz interfejsu API można łatwo skonfigurować za pomocą oprogramowania pośredniczącego ASP.NET.
Dodaj klucz interfejsu API
do wartości konfiguracji lokalnej. dotnet user-secrets set "Authentication:ApiKey" <value>
Nuta
Należy zastąpić wartość symbolu zastępczego własną wartością i zanotować ją.
Control + Kliknij w projekcie PushDemoApi wybierz pozycję Nowy folder z menu Dodaj, a następnie kliknij pozycję Dodaj przy użyciu uwierzytelniania jako nazwę folderu .
Control Kliknij w folderze uwierzytelniania, a następnie wybierz pozycję Nowy plik... z menuDodaj .Wybierz pozycję
Ogólne Empty Class , wprowadźApiKeyAuthOptions.cs dlanazwa, a następnie kliknij przycisk New dodając następującą implementację.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; } } }
Dodaj kolejny Empty Class do folderu Authentication o nazwie ApiKeyAuthHandler.cs, a następnie dodaj następującą implementację.
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)); } } }
Dodaj kolejny Empty Class do folderu Authentication o nazwie ApiKeyAuthenticationBuilderExtensions.cs, a następnie dodaj następującą implementację.
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); } } }
Nuta
Ta metoda rozszerzenia upraszcza kod konfiguracji oprogramowania pośredniczącego w Startup.cs co sprawia, że jest bardziej czytelny i ogólnie łatwiejszy do naśladowania.
W Startup.cszaktualizuj metodę ConfigureServices, aby skonfigurować uwierzytelnianie klucza interfejsu API poniżej wywołania usług . AddControllers, metoda.
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); }
Nadal w Startup.cszaktualizuj metodę Configure, aby wywołać metodę UseAuthentication i useAuthorization extension methods w aplikacji IApplicationBuilder. Upewnij się, że te metody są wywoływane po UseRouting i przed aplikacji. Użyjpunktów końcowych.
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(); }); }
Nuta
Wywoływanie UseAuthentication rejestruje oprogramowanie pośredniczące korzystające z wcześniej zarejestrowanych schematów uwierzytelniania (z ConfigureServices). Należy to wywołać przed każdym oprogramowaniem pośredniczącym, które zależy od uwierzytelnienia użytkowników.
Dodawanie zależności i konfigurowanie usług
ASP.NET Core obsługuje wzorzec projektowania
Korzystanie z centrum powiadomień i zestawu SDK usługi Notification Hubs na potrzeby operacji zaplecza jest hermetyzowane w ramach usługi. Usługa jest zarejestrowana i udostępniana za pośrednictwem odpowiedniej abstrakcji.
control + Click on the Dependencies folder, a następnie wybierz pozycję Zarządzaj pakietami NuGet....
Wyszukaj Microsoft.Azure.NotificationHubs i upewnij się, że jest zaznaczone.
Kliknij przycisk Dodaj pakiety, a następnie kliknij pozycję Akceptuj po wyświetleniu monitu o zaakceptowanie postanowień licencyjnych.
Control + Click w projekcie PushDemoApi wybierz pozycję New Folder z menu Dodaj, a następnie kliknij pozycję Dodaj przy użyciu Models jako nazwę folderu .
Control + Kliknij w folderze Models, a następnie wybierz pozycję Nowy plik... z menu Dodaj.
Wybierz pozycję
Ogólne Empty Class , wprowadźPushTemplates.cs dlaName , a następnie kliknij przyciskNew dodanie następującej implementacji.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)\" }"; } } }
Nuta
Ta klasa zawiera tokenizowane ładunki powiadomień dla ogólnych i dyskretnych powiadomień wymaganych przez ten scenariusz. Ładunki są definiowane poza Instalacja, aby umożliwić eksperymentowanie bez konieczności aktualizowania istniejących instalacji za pośrednictwem usługi. Obsługa zmian w instalacjach w ten sposób jest poza zakresem tego samouczka. W przypadku środowiska produkcyjnego rozważ szablony niestandardowe.
Dodaj kolejny Empty Class do folderu Models o nazwie DeviceInstallation.cs, a następnie dodaj następującą implementację.
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>(); } }
Dodaj kolejny Empty Class do folderu Models o nazwie NotificationRequest.cs, a następnie dodaj następującą implementację.
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; } } }
Dodaj kolejny Empty Class do folderu Models o nazwie NotificationHubOptions.cs, a następnie dodaj następującą implementację.
using System.ComponentModel.DataAnnotations; namespace PushDemoApi.Models { public class NotificationHubOptions { [Required] public string Name { get; set; } [Required] public string ConnectionString { get; set; } } }
Dodaj nowy folder do projektu
PushDemoApi o nazwie Services .Dodaj pusty interfejs
do folderu services Services o nazwie INotificationService.cs , a następnie dodaj następującą implementację.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); } }
Dodaj
Empty Class do folderuServices o nazwie NotificationHubsService.cs , a następnie dodaj następujący kod, aby zaimplementować interfejsINotificationService :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); } } }
Nuta
Wyrażenie tagu dostarczone do SendTemplateNotificationAsync jest ograniczone do 20 tagów. Jest on ograniczony do 6 dla większości operatorów, ale wyrażenie zawiera tylko jednostki ORS (||) w tym przypadku. Jeśli w żądaniu istnieje więcej niż 20 tagów, należy je podzielić na wiele żądań. Aby uzyskać więcej szczegółów, zobacz dokumentację Routing i Wyrażenia tagów.
W Startup.cszaktualizuj metodę ConfigureServices, aby dodać NotificationHubsService jako pojedynczą implementację INotificationService.
using PushDemoApi.Models; using PushDemoApi.Services; public void ConfigureServices(IServiceCollection services) { ... services.AddSingleton<INotificationService, NotificationHubService>(); services.AddOptions<NotificationHubOptions>() .Configure(Configuration.GetSection("NotificationHub").Bind) .ValidateDataAnnotations(); }
Tworzenie interfejsu API powiadomień
control Click on theControllers folder, a następnie wybierz pozycjęNew File... z menuAdd (Dodaj).Wybierz
ASP.NET Core Web API Controller Class , wprowadźNotificationsController dlanazwa, a następnie kliknij Nowy .Nuta
Jeśli korzystasz z Visual Studio 2019, wybierz kontroler interfejsu API z akcjami odczytu/zapisu szablonu.
Dodaj następujące przestrzenie nazw na początku pliku.
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;
Zaktualizuj szablon kontrolera, aby pochodził z ControllerBase i jest ozdobiony atrybutem ApiController.
[ApiController] [Route("api/[controller]")] public class NotificationsController : ControllerBase { // Templated methods here }
Nuta
Kontroler kontroler klasy bazowej zapewnia obsługę widoków, ale nie jest to konieczne w tym przypadku i dlatego można użyć ControllerBase. Jeśli korzystasz z Visual Studio 2019, możesz pominąć ten krok.
Jeśli zdecydujesz się ukończyć
uwierzytelniać klientów przy użyciu klucza interfejsu API, należy również ozdobićNotificationsController za pomocą atrybutu Autoryzuj .[Authorize]
Zaktualizuj konstruktor, aby akceptował zarejestrowane wystąpienie usługi INotificationService jako argument i przypisz go do elementu członkowskiego readonly.
readonly INotificationService _notificationService; public NotificationsController(INotificationService notificationService) { _notificationService = notificationService; }
W
launchSettings.json (w folderze właściwości) zmień launchUrl zna api/notifications , aby pasować do adresu URL określonego w atrybucieRegistrationsController Route .Rozpocznij debugowanie (Command + Enter), aby sprawdzić, czy aplikacja współpracuje z nowym NotificationsController i zwraca stan 401 Brak autoryzacji.
Nuta
Program Visual Studio może nie uruchamiać automatycznie aplikacji w przeglądarce. Użyjesz postman do przetestowania interfejsu API od tego momentu.
Na nowej karcie Postman ustaw żądanie GET. Wprowadź poniższy adres zastępując symbol zastępczy <applicationUrl> ciągiem https applicationUrl znalezionym w Properties>launchSettings.json.
<applicationUrl>/api/notifications
Nuta
applicationUrl powinien mieć wartość " " dla profilu domyślnego. Jeśli używasz IIS (domyślnie w programie Visual Studio 2019 w systemie Windows), należy zamiast tego użyćapplicationUrl określonego w elemencie iisSettings . Jeśli adres jest niepoprawny, otrzymasz odpowiedź 404.Jeśli wybrano opcję ukończenia Uwierzytelnianie klientów przy użyciu klucza interfejsu API, pamiętaj, aby skonfigurować nagłówki żądań tak, aby zawierały wartość apikey.
Klucz Wartość apikey <your_api_key> Kliknij przycisk Wyślij
. Nuta
Powinien zostać wyświetlony stan
200 OK z zawartością JSON. Jeśli zostanie wyświetlone ostrzeżenie weryfikacji certyfikatu SSL, możesz przełączyć żądanie weryfikacji certyfikatu SSL Postman ustawienie w ustawieniach .
Zastąp metody klas szablonu w NotificationsController.cs następującym kodem.
[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(); }
Tworzenie aplikacji interfejsu API
Teraz utworzysz aplikację interfejsu API w usłudze Azure App Service na potrzeby hostowania usługi zaplecza.
Zaloguj się do witryny Azure Portal.
Kliknij pozycję Utwórz zasób, a następnie wyszukaj i wybierz pozycję API App, a następnie kliknij pozycję Utwórz.
Zaktualizuj następujące pola, a następnie kliknij pozycję Utwórz.
nazwa aplikacji :
Wprowadź globalnie unikatową nazwę aplikacji interfejsu APIsubskrypcja :
Wybierz ten sam docelowy Subskrypcja, w którym utworzono centrum powiadomień.grupa zasobów :
Wybierz tę samą grupę zasobów utworzoną w centrum powiadomień.plan/lokalizacja usługi App Service:
Tworzenie nowego planu usługi App ServiceNuta
Zmień opcję domyślną na plan obejmujący obsługę SSL. W przeciwnym razie należy wykonać odpowiednie kroki podczas pracy z aplikacją mobilną, aby zapobiec zablokowaniu żądań http
http. Application Insights:
Zachowaj sugerowaną opcję (nowy zasób zostanie utworzony przy użyciu tej nazwy) lub wybierz istniejący zasób.Po aprowizacji aplikacji interfejsu API przejdź do tego zasobu.
Zanotuj właściwość adresu URL
w podsumowaniu Essentials w górnej częściPrzegląd . Ten adres URL to punkt końcowy zaplecza, który będzie używany w dalszej części tego samouczka. Nuta
Adres URL używa określonej wcześniej nazwy aplikacji interfejsu API z formatem
https://<app_name>.azurewebsites.net
.Wybierz pozycję Configuration z listy (w obszarze Settings).
Dla każdego z poniższych ustawień kliknij nowe ustawienie aplikacji, aby wprowadzić Nazwa i wartość , a następnie kliknij przycisk OK.
Nazwa Wartość Authentication:ApiKey
<api_key_value> NotificationHub:Name
<hub_name_value> NotificationHub:ConnectionString
<hub_connection_string_value> Nuta
Są to te same ustawienia zdefiniowane wcześniej w ustawieniach użytkownika. Powinno być możliwe skopiowanie tych kopii. Ustawienie Authentication:ApiKey jest wymagane tylko w przypadku wybrania opcji ukończenia Uwierzytelnianie klientów przy użyciu klucza interfejsu API. W przypadku scenariuszy produkcyjnych można zapoznać się z opcjami, takimi jak azure KeyVault. Zostały one dodane jako ustawienia aplikacji dla uproszczenia w tym przypadku.
Po dodaniu wszystkich ustawień aplikacji kliknij pozycję Zapisz, a następnie Kontynuuj.
Publikowanie usługi zaplecza
Następnie wdrożysz aplikację w aplikacji interfejsu API, aby była dostępna ze wszystkich urządzeń.
Nuta
Poniższe kroki są specyficzne dla programu Visual Studio dla komputerów Mac. Jeśli korzystasz z Visual Studio 2019 w systemie Windows, przepływ publikowania będzie inny. Zobacz Publikowanie w usłudze Azure App Service w systemie Windows.
Zmień konfigurację z Debugowanie na Release, jeśli jeszcze tego nie zrobiono.
Control Kliknij projektuPushDemoApi , a następnie wybierz pozycjęPublikuj na platformie Azure... z menu Publikowanie. Jeśli zostanie wyświetlony monit, postępuj zgodnie z przepływem uwierzytelniania. Użyj konta użytego w poprzedniej utworzyć sekcję App interfejsu API.
Wybierz aplikację interfejsu API usługi Azure App Service
utworzoną wcześniej z listy jako element docelowy publikowania, a następnie kliknij pozycję Publikuj .
Po zakończeniu pracy kreatora publikuje ona aplikację na platformie Azure, a następnie otwiera aplikację. Zanotuj adres URL , jeśli jeszcze tego nie zrobiono. Ten adres URL to punkt końcowy zaplecza używany w dalszej części tego samouczka.
Weryfikowanie opublikowanego interfejsu API
W Postman otwórz nową kartę, ustaw żądanie na PUT i wprowadź poniższy adres. Zastąp symbol zastępczy adresem podstawowym zanotowanymi w poprzedniej opublikować sekcję usługi zaplecza.
https://<app_name>.azurewebsites.net/api/notifications/installations
Nuta
Adres podstawowy powinien mieć format
https://<app_name>.azurewebsites.net/
Jeśli wybrano opcję ukończenia Uwierzytelnianie klientów przy użyciu klucza interfejsu API, pamiętaj, aby skonfigurować nagłówki żądań tak, aby zawierały wartość apikey.
Klucz Wartość apikey <your_api_key> Wybierz opcję raw dla Body, a następnie wybierz JSON z listy opcji formatowania, a następnie dołącz symbol zastępczy zawartości JSON:
{}
Kliknij pozycję Wyślij.
Nuta
Z usługi powinien zostać wyświetlony stan 422 UnprocessableEntity.
Wykonaj ponownie kroki 1–4, ale tym razem określając punkt końcowy żądań w celu zweryfikowania, czy otrzymasz odpowiedź 400 Nieprawidłowe żądanie.
https://<app_name>.azurewebsites.net/api/notifications/requests
Nuta
Nie można jeszcze przetestować interfejsu API przy użyciu prawidłowych danych żądania, ponieważ będzie to wymagać informacji specyficznych dla platformy z aplikacji mobilnej klienta.
Tworzenie międzyplatformowej aplikacji Flutter
W tej sekcji utworzysz Flutter aplikacji mobilnej implementowania powiadomień wypychanych w sposób międzyplatformowy.
Umożliwia ona rejestrowanie i wyrejestrowanie z centrum powiadomień za pośrednictwem utworzonej usługi zaplecza.
Alert jest wyświetlany po określeniu akcji, a aplikacja znajduje się na pierwszym planie. W przeciwnym razie powiadomienia są wyświetlane w centrum powiadomień.
Nuta
Zazwyczaj wykonuje się akcje rejestracji (i wyrejestrowania) w odpowiednim punkcie cyklu życia aplikacji (lub w ramach środowiska pierwszego uruchomienia) bez jawnego rejestrowania/wyrejestrowania danych wejściowych użytkownika. Jednak w tym przykładzie wymagane będą jawne dane wejściowe użytkownika, aby umożliwić łatwiejsze eksplorowanie i przetestowanie tej funkcji.
Tworzenie rozwiązania Flutter
Otwórz nowe wystąpienie programu Visual Studio Code.
Otwórz Command Palette (Shift + Command + P).
Wybierz polecenie Flutter: New Project i naciśnij Enter.
Wprowadź push_demo w polu Nazwa projektu , a następnie wybierz lokalizację projektu .
Po wyświetleniu monitu o to wybierz pozycję Pobierz pakiety.
Control + Click on the kotlin folder (w obszarze app>src>main), a następnie wybierz pozycję Reveal in Finder. Następnie zmień nazwę folderów podrzędnych (w folderze kotlin) na odpowiednio
com
,<your_organization>
ipushdemo
.Nuta
W przypadku korzystania z szablonu programu
Visual Studio Code te foldery są domyślnie com ,przykład , . Przy założeniu, że mobcat jest używany dla organizacji , struktura folderów powinna być widoczna jako:project_name - kotlin
- Com
- mobcat
- pushdemo
- mobcat
- Com
- kotlin
Po powrocie do
programu Visual Studio Code zaktualizuj wartość applicationId android app build.gradle , aby. Nuta
Jako symbol zastępczy <your_organization> należy użyć własnej nazwy organizacji. Na przykład użycie mobcat jako organizacji spowoduje nazwę pakietu wartość com.mobcat.pushdemo.
Zaktualizuj atrybut pakietu
w plikach AndroidManifest.xml w obszarzesrc debugowania ,src głównego iprofilu src . Upewnij się, że wartości są zgodne z identyfikatorem applicationId użytym w poprzednim kroku. <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.<your_organization>.pushdemo>"> ... </manifest>
Zaktualizuj atrybut
android:label
w pliku AndroidManifest.xml w obszarze src>main, aby PushDemo. Następnie dodaj atrybutandroid:allowBackup
bezpośrednio w obszarzeandroid:label
, ustawiając jego wartość na wartość false.<application android:name="io.flutter.app.FlutterApplication" android:label="PushDemo" android:allowBackup="false" android:icon="@mipmap/ic_launcher"> ... </application>
Otwórz plik
build.gradle (app app build.gradle ), a następnie zaktualizujcompileSdkVersion (w sekcjiandroid ), aby użyćinterfejsu API 29 . Następnie zaktualizuj wartości minSdkVersion i targetSdkVersion (z sekcji defaultConfig), aby odpowiednio 26 i 29.Nuta
Tylko te urządzenia z systemem interfejsu API na poziomie 26 i wyższym są obsługiwane na potrzeby tego samouczka, ale można rozszerzyć go na urządzenia obsługujące starsze wersje.
Control + Kliknij w folderze systemu ios, a następnie wybierz pozycję Otwórz w programie Xcode.
W Xcode kliknij pozycję Runner (xcodeproj u góry, a nie folderu). Następnie wybierz docelowy element docelowy modułu uruchamiającego
i wybierz kartę Ogólne . Po wybraniu konfiguracji kompilacjiWszystkie zaktualizuj identyfikator pakietu, aby . Nuta
Jako symbol zastępczy <your_organization> należy użyć własnej nazwy organizacji. Na przykład użycie mobcat
jako organizacji spowoduje wartość identyfikatora pakietu wartościcom.mobcat.PushDemo .Kliknij
Info.plist, a następnie zaktualizuj wartość nazwa pakietu , aby PushDemo Zamknij Xcode i wróć do programu Visual Studio Code.
Po powrocie do programu Visual Studio Code otwórz pubspec.yaml, dodaj http i pakiety flutter_secure_storageDart jako zależności. Następnie zapisz plik i kliknij przycisk Pobierz pakiety po wyświetleniu monitu o to.
dependencies: flutter: sdk: flutter http: ^0.12.1 flutter_secure_storage: ^3.3.3
W
terminalu zmień katalog na foldersystemu ios (dla projektu Flutter). Następnie wykonaj polecenie zasobnik zainstaluj, aby zainstalować nowe zasobniki (wymagane przez pakiet flutter_secure_storage). control + Click on the lib folder, a następnie wybierz New File z menu przy użyciu main_page.dart jako nazwy pliku. Następnie dodaj następujący kod.
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>[], ) ) ); } }
W main.dartzastąp kod szablonu poniższym kodem.
import 'package:flutter/material.dart'; import 'package:push_demo/main_page.dart'; final navigatorKey = GlobalKey<NavigatorState>(); void main() => runApp(MaterialApp(home: MainPage(), navigatorKey: navigatorKey));
W terminaluskompiluj i uruchom aplikację na każdej platformie docelowej, aby przetestować działanie szablonu aplikacji na urządzeniach. Upewnij się, że obsługiwane urządzenia są połączone.
flutter run
Implementowanie składników międzyplatformowych
control + Click on the lib folder, a następnie wybierz New Folder z menu przy użyciu modeli jako nazwy folderu .
control + Click on the models folder, a następnie wybierz New File z menu przy użyciu device_installation.dart jako nazwy pliku. Następnie dodaj następujący kod.
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, }; }
Dodaj nowy plik do folderu models o nazwie push_demo_action.dart definiujący wyliczanie akcji obsługiwanych w tym przykładzie.
enum PushDemoAction { actionA, actionB, }
Dodaj nowy folder do projektu o nazwie services następnie dodaj nowy plik do tego folderu o nazwie device_installation_service.dart z następującą implementacją.
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); } }
Nuta
Jako symbol zastępczy <your_organization> należy użyć własnej nazwy organizacji. Na przykład użycie mobcat, ponieważ organizacja spowoduje MethodChannel nazwę com.mobcat.pushdemo/deviceinstallation.
Ta klasa hermetyzuje pracę z podstawową platformą natywną w celu uzyskania szczegółowych informacji o wymaganej instalacji urządzenia. MethodChannel ułatwia dwukierunkową asynchroniczną komunikację z podstawowymi platformami natywnymi. Odpowiedni odpowiednik specyficzny dla platformy dla tego kanału zostanie utworzony w kolejnych krokach.
Dodaj kolejny plik do tego folderu o nazwie notification_action_service.dart z następującą implementacją.
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; } } }
Nuta
Jest to używany jako prosty mechanizm umożliwiający scentralizowanie obsługi akcji powiadomień, dzięki czemu można je obsłużyć w sposób międzyplatformowy przy użyciu silnie typizowanego wyliczenia. Usługa umożliwia podstawowej platformie natywnej wyzwalanie akcji po określeniu jej w ładunku powiadomień. Umożliwia również wspólne kodowi retrospektywne sprawdzanie, czy akcja została określona podczas uruchamiania aplikacji, gdy flutter jest gotowy do jego przetworzenia. Na przykład po uruchomieniu aplikacji przez naciśnięcie powiadomienia z centrum powiadomień.
Dodaj nowy plik do folderu usług
o nazwie notification_registration_service.dart z następującą implementacją.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; } } }
Nuta
Ta klasa hermetyzuje użycie DeviceInstallationService oraz żądań do usługi zaplecza w celu wykonania wymaganych akcji rejestracji, wyrejestrowania i odświeżania. Argument apiKey
jest wymagany tylko w przypadku wybrania uwierzytelnienia klientów przy użyciu klucza interfejsu API.Dodaj nowy plik do folderu lib
o nazwie config.dart z następującą implementacją.class Config { static String apiKey = "API_KEY"; static String backendServiceEndpoint = "BACKEND_SERVICE_ENDPOINT"; }
Nuta
Jest to prosty sposób definiowania wpisów tajnych aplikacji. Zastąp wartości symboli zastępczych własnymi. Podczas tworzenia usługi zaplecza należy zanotować te informacje. Adres URL aplikacji interfejsu API
powinien być apiKey. Element członkowski jest wymagany tylko w przypadku wybrania uwierzytelnienia klientów przy użyciu klucza interfejsu API.Pamiętaj, aby dodać go do pliku gitignore, aby uniknąć zatwierdzania tych wpisów tajnych do kontroli źródła.
Implementowanie międzyplatformowego interfejsu użytkownika
W pliku
main_page.dart zastąp funkcję kompilacjinastępującym kodem. @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, ), ], ), ), ); }
Dodaj wymagane importy na początku pliku main_page.dart.
import 'package:push_demo/services/notification_registration_service.dart'; import 'config.dart';
Dodaj pole do klasy _MainPageState, aby zapisać odwołanie do NotificationRegistrationService.
final notificationRegistrationService = NotificationRegistrationService(Config.backendServiceEndpoint, Config.apiKey);
W klasie _MainPageState zaimplementuj programy obsługi zdarzeń dla Register i deregister przycisków onPressed. Wywołaj odpowiednie metody Register/Deregister, a następnie wyświetl alert wskazujący wynik.
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(); }, ), ], ); }, ); }
Teraz w main.dartupewnij się, że w górnej części pliku znajdują się następujące importy.
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';
Zadeklaruj zmienną do przechowywania odwołania do wystąpienia NotificationActionService i zainicjuj je.
final notificationActionService = NotificationActionService();
Dodaj funkcje do obsługi wyświetlania alertu po wyzwoleniu akcji.
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(); }, ), ], ); }, ); }
Zaktualizuj funkcję main, aby obserwować akcję NotificationActionServiceTriggered strumienia i sprawdzać wszystkie akcje przechwycone podczas uruchamiania aplikacji.
void main() async { runApp(MaterialApp(home: MainPage(), navigatorKey: navigatorKey,)); notificationActionService.actionTriggered.listen((event) { notificationActionTriggered(event as PushDemoAction); }); await notificationActionService.checkLaunchAction(); }
Nuta
Jest to po prostu zademonstrowanie potwierdzenia i propagacji akcji powiadomień wypychanych. Zazwyczaj są one obsługiwane w trybie dyskretnym, na przykład przejście do określonego widoku lub odświeżenie niektórych danych zamiast wyświetlania alertu w tym przypadku.
Konfigurowanie natywnego projektu systemu Android na potrzeby powiadomień wypychanych
Dodawanie pliku JSON usług Google Services
Control + Click on the android folder, a następnie wybierz pozycję Otwórz w programie Android Studio. Następnie przejdź do widoku Project (jeśli jeszcze tego nie ma).
Znajdź pobrany wcześniej plik google-services.json podczas konfigurowania projektu PushDemo w programie Firebase Console. Następnie przeciągnij go do katalogu głównego modułu app (android>>app).
Konfigurowanie ustawień i uprawnień kompilacji
Przełącz widok
Project na Android .Otwórz
AndroidManifest.xml , a następnie dodaj uprawnieniaINTERNET iREAD_PHONE_STATE po elemecie aplikacjiprzed tagiem zamykającym . <manifest> <application>...</application> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.READ_PHONE_STATE" /> </manifest>
Dodawanie zestawów SDK programu Firebase
W
Android Studio otwórz plik build.gradle (Gradle Scripts build.gradle (Project: android) ). i upewnij się, że masz ścieżkę klasy "com.google.gms:google-services" w węźlebuildscript
>zależności.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 // ... } }
Nuta
Upewnij się, że odwołujesz się do najnowszej wersji zgodnie z instrukcjami podanymi w konsoli programu
Firebase podczas tworzenia programu Android Project .W pliku
build.gradle (Gradle Scripts build.gradle (Module: app) ) zastosuj wtyczkęGoogle Services Gradle . Zastosuj wtyczkę bezpośrednio nad węzłem android.// ... // Add the following line: apply plugin: 'com.google.gms.google-services' // Google Services plugin android { // ... }
W tym samym pliku w węźle zależności dodaj zależność dla biblioteki Cloud Messaging Android.
dependencies { // ... implementation 'com.google.firebase:firebase-messaging:20.2.0' }
Nuta
Upewnij się, że odwołujesz się do najnowszej wersji zgodnie z dokumentacją klienta Cloud Messaging dla systemu Android.
Zapisz zmiany, a następnie kliknij przycisk Synchronizuj teraz (w wierszu polecenia paska narzędzi) lub Sync Project with Gradle Files.
Obsługa powiadomień wypychanych dla systemu Android
W Android Studio Control + Click click on the com.<your_organization>.pushdemo package folder (app>src>main>kotlin) wybierz pozycję Package z menu New. Wprowadź services jako nazwę, a następnie naciśnij Return.
Control Kliknij w folderze usług, wybierz pozycję plik/klasa Kotlin z menu Nowy . Wprowadź DeviceInstallationService jako nazwę, a następnie naciśnij Return.Zaimplementuj DeviceInstallationService przy użyciu następującego kodu.
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" } }
Nuta
Ta klasa implementuje odpowiedni odpowiednik specyficzny dla platformy dla kanału
com.<your_organization>.pushdemo/deviceinstallation
. Zostało to zdefiniowane w części Flutter aplikacji w DeviceInstallationService.dart. W takim przypadku wywołania są wykonywane z wspólnego kodu do hosta natywnego. Pamiętaj, aby zastąpić <your_organization> własną organizacją, gdziekolwiek jest używana.Ta klasa udostępnia unikatowy identyfikator (przy użyciu Secure.AndroidId) w ramach ładunku rejestracji centrum powiadomień.
Dodaj kolejny
plik/klasę Kotlin do folderu usługo nazwie NotificationRegistrationService , a następnie dodaj następujący kod.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) } }
Nuta
Ta klasa implementuje odpowiedni odpowiednik specyficzny dla platformy dla kanału
com.<your_organization>.pushdemo/notificationregistration
. Zostało to zdefiniowane w części Flutter aplikacji w NotificationRegistrationService.dart. W takim przypadku wywołania są wykonywane z hosta natywnego do wspólnego kodu. Ponownie zastąp <your_organization> własną organizacją wszędzie tam, gdzie jest używana.Dodaj kolejny
plików/klas Kotlin do folderu usług o nazwie NotificationActionService , a następnie dodaj następujący kod.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() } } } }
Nuta
Ta klasa implementuje odpowiedni odpowiednik specyficzny dla platformy dla kanału
com.<your_organization>.pushdemo/notificationaction
. To zostało zdefiniowane w części Flutter aplikacji w NotificationActionService.dart. Wywołania mogą być wykonywane w obu kierunkach w tym przypadku. Pamiętaj, aby zastąpić <your_organization> własną organizacją, gdziekolwiek jest używana.Dodaj nowy plik/klasę Kotlin do witryny com.<your_organization>.pushdemo o nazwie PushNotificationsFirebaseMessagingService, a następnie zaimplementuj przy użyciu następującego kodu.
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)) } } } }
Nuta
Ta klasa jest odpowiedzialna za obsługę powiadomień, gdy aplikacja jest uruchomiona na pierwszym planie. Warunkowo wywoła triggerAction w NotificationActionService, jeśli akcja zostanie uwzględniona w ładunku powiadomienia odebranym w onMessageReceived. Spowoduje to również wywołanie
refreshRegistration wNotificationRegistrationService, gdy token Firebase zostanie wygenerowany ponownie przez zastąpienie funkcji onNewToken .Po raz kolejny zastąp <your_organization> własną organizacją wszędzie tam, gdzie jest używana.
W AndroidManifest.xml (app>src>main), dodaj PushNotificationsFirebaseMessagingService do dołu aplikacji z filtrem intencji
com.google.firebase.MESSAGING_EVENT
.<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>
Po powrocie do DeviceInstallationServiceupewnij się, że w górnej części pliku znajdują się następujące importy.
package com.<your_organization>.pushdemo import com.<your_organization>.pushdemo.services.PushNotificationsFirebaseMessagingService
Nuta
Zastąp <your_organization> własną wartością organizacji.
Zaktualizuj tekst zastępczy Placeholder_Get_Value_From_FirebaseMessagingService_Implementation, aby uzyskać wartość tokenu z PushNotificationFirebaseMessagingService.
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 }
W MainActivityupewnij się, że w górnej części pliku znajdują się następujące importy.
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
Nuta
Zastąp <your_organization> własną wartością organizacji.
Dodaj zmienną do przechowywania odwołania do DeviceInstallationService.
private lateinit var deviceInstallationService: DeviceInstallationService
Dodaj funkcję o nazwie processNotificationActions, aby sprawdzić, czy Intent ma dodatkową wartość o nazwie action. Warunkowo wyzwól akcję lub zapisz ją do użycia później, jeśli akcja jest przetwarzana podczas uruchamiania aplikacji.
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) } } } }
Zastąpij funkcję onNewIntent w celu wywołania processNotificationActions.
override fun onNewIntent(intent: Intent) { super.onNewIntent(intent) processNotificationActions(intent) }
Nuta
Ponieważ LaunchMode
dla MainActivity jest ustawiona naSingleTop, intencja zostanie wysłana do istniejącego wystąpienia działania za pośrednictwemonNe Funkcja , a nieonCreate , dlatego należy obsługiwać przychodząceIntent zarówno wonCreate , jak ionNewIntent functions.Zastąpij funkcję onCreate, ustaw deviceInstallationService na nowe wystąpienie DeviceInstallationService.
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) flutterEngine?.let { deviceInstallationService = DeviceInstallationService(context, it) } }
Ustaw właściwości notificationActionService i notificationRegistrationService w PushNotificationFirebaseMessagingServices.
flutterEngine?.let { deviceInstallationService = DeviceInstallationService(context, it) PushNotificationsFirebaseMessagingService.notificationActionService = NotificationActionService(it) PushNotificationsFirebaseMessagingService.notificationRegistrationService = NotificationRegistrationService(it) }
W tej samej funkcji warunkowo wywołaj FirebaseInstanceId.getInstance().instanceId. Zaimplementuj wartość OnCompleteListener, aby ustawić wynikowy token na PushNotificationFirebaseMessagingService przed wywołaniem refreshRegistration.
if(deviceInstallationService?.playServicesAvailable) { FirebaseInstanceId.getInstance().instanceId .addOnCompleteListener(OnCompleteListener { task -> if (!task.isSuccessful) return@OnCompleteListener PushNotificationsFirebaseMessagingService.token = task.result?.token PushNotificationsFirebaseMessagingService.notificationRegistrationService?.refreshRegistration() }) }
Nadal w onCreatewywołaj metodę processNotificationActions na końcu funkcji. Użyj true dla argumentu launchAction , aby wskazać, że ta akcja jest przetwarzana podczas uruchamiania aplikacji.
processNotificationActions(this.intent, true)
Nuta
Musisz ponownie zarejestrować aplikację przy każdym uruchomieniu i zatrzymać ją z sesji debugowania, aby kontynuować odbieranie powiadomień wypychanych.
Konfigurowanie natywnego projektu systemu iOS na potrzeby powiadomień wypychanych
Konfigurowanie elementu docelowego modułu uruchamiającego i pliku Info.plist
W
Visual Studio Code Control Kliknij w folderzeios , a następnie wybierz pozycjęOtwórz w programie Xcode .W
Xcode kliknij pozycję Runner (xcodeproj u góry, a nie folderu), a następnie wybierz element docelowy modułu uruchamiającego, a następnie możliwości podpisywania & . Po wybraniu konfiguracji kompilacjiWszystkie wybierz konto dewelopera dlazespołu. Upewnij się, że opcja "Automatyczne zarządzanie podpisywaniem" jest zaznaczona, a certyfikat podpisywania i profil aprowizacji są wybierane automatycznie. Nuta
Jeśli nie widzisz nowej wartości profilu aprowizacji, spróbuj odświeżyć profile tożsamości podpisywania, wybierając pozycję preferencje programu Xcode>>konto następnie wybierz przycisk Pobierz profile ręczne, aby pobrać profile.
Kliknij pozycję + capability, a następnie wyszukaj push notifications. kliknij dwukrotniepowiadomienia wypychane, aby dodać tę możliwość.
Otwórz
Info.plist i ustaw minimalną wersję systemu na13.0 .Nuta
Tylko te urządzenia z systemem iOS 13.0 lub nowszym są obsługiwane na potrzeby tego samouczka, jednak można rozszerzyć go na urządzenia obsługujące starsze wersje.
Otwórz Runner.entitlements i upewnij się, że ustawienie APS Environment jest ustawione na programowanie.
Obsługa powiadomień wypychanych dla systemu iOS
Control + Click on the Runner folder (w projekcie Moduł uruchamiający), a następnie wybierz pozycję Nowa grupa przy użyciu usługi Services jako nazwy.
Control Kliknij w folderze usługServices, a następnie wybierz pozycję Nowy plik... . Następnie wybierzplik Swift i kliknij przycisk Dalej . Określ DeviceInstallationService jako nazwę, a następnie kliknij pozycję Utwórz.Zaimplementuj DeviceInstallationService.swift przy użyciu następującego kodu.
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." } }
Nuta
Ta klasa implementuje odpowiedni odpowiednik specyficzny dla platformy dla kanału
com.<your_organization>.pushdemo/deviceinstallation
. Zostało to zdefiniowane w części Flutter aplikacji w DeviceInstallationService.dart. W takim przypadku wywołania są wykonywane z wspólnego kodu do hosta natywnego. Pamiętaj, aby zastąpić <your_organization> własną organizacją, gdziekolwiek jest używana.Ta klasa udostępnia unikatowy identyfikator (przy użyciu wartości UIDevice.identifierForVendor) w ramach ładunku rejestracji centrum powiadomień.
Dodaj kolejny
plik Swift do folderu usług Services o nazwie NotificationRegistrationService , a następnie dodaj następujący kod.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) } }
Nuta
Ta klasa implementuje odpowiedni odpowiednik specyficzny dla platformy dla kanału
com.<your_organization>.pushdemo/notificationregistration
. Zostało to zdefiniowane w części Flutter aplikacji w NotificationRegistrationService.dart. W takim przypadku wywołania są wykonywane z hosta natywnego do wspólnego kodu. Ponownie zastąp <your_organization> własną organizacją wszędzie tam, gdzie jest używana.Dodaj kolejny plik
Swift do folderu usługo nazwie NotificationActionService , a następnie dodaj następujący kod.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) } } }
Nuta
Ta klasa implementuje odpowiedni odpowiednik specyficzny dla platformy dla kanału
com.<your_organization>.pushdemo/notificationaction
. To zostało zdefiniowane w części Flutter aplikacji w NotificationActionService.dart. Wywołania mogą być wykonywane w obu kierunkach w tym przypadku. Pamiętaj, aby zastąpić <your_organization> własną organizacją, gdziekolwiek jest używana.W AppDelegate.swiftdodaj zmienne do przechowywania odwołania do utworzonych wcześniej usług.
var deviceInstallationService : DeviceInstallationService? var notificationRegistrationService : NotificationRegistrationService? var notificationActionService : NotificationActionService?
Dodaj funkcję o nazwie processNotificationActions do przetwarzania danych powiadomień. Warunkowo wyzwól akcję lub zapisz ją do użycia później, jeśli akcja jest przetwarzana podczas uruchamiania aplikacji.
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) } } }
Zastąp funkcję
nieRegisterForRemoteNotificationsWithDeviceToken ustawiając wartość tokenudla DeviceInstallationService. Następnie wywołaj refreshRegistrationNotificationRegistrationService. override func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) { deviceInstallationService?.token = deviceToken notificationRegistrationService?.refreshRegistration() }
Zastąp funkcję
didReceiveRemoteNotification przekazującą argument userInfodo funkcji processNotificationActions .override func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any]) { processNotificationActions(userInfo: userInfo) }
Zastąp funkcję didFailToRegisterForRemoteNotificationsWithError, aby zarejestrować błąd.
override func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) { print(error); }
Nuta
Jest to bardzo symbol zastępczy. W scenariuszach produkcyjnych należy zaimplementować odpowiednie rejestrowanie i obsługę błędów.
W finishLaunchingWithOptions utwórz wystąpienie zmiennych deviceInstallationService, notificationRegistrationServicei notificationActionService.
let controller : FlutterViewController = window?.rootViewController as! FlutterViewController deviceInstallationService = DeviceInstallationService(withBinaryMessenger: controller.binaryMessenger) notificationRegistrationService = NotificationRegistrationService(withBinaryMessenger: controller.binaryMessenger) notificationActionService = NotificationActionService(withBinaryMessenger: controller.binaryMessenger)
W tej samej funkcji warunkowo żądaj autoryzacji i zarejestruj się w celu otrzymywania powiadomień zdalnych.
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() } } } }
Jeśli launchOptions zawiera klucz remoteNotification, wywołaj processNotificationActions na końcu funkcji didFinishLaunchingWithOptions. Przekaż wynikowy obiekt userInfo i użyj true dla argumentu launchAction . Wartość true oznacza, że akcja jest przetwarzana podczas uruchamiania aplikacji.
if let userInfo = launchOptions?[.remoteNotification] as? [AnyHashable : Any] { processNotificationActions(userInfo: userInfo, launchAction: true) }
Testowanie rozwiązania
Teraz możesz przetestować wysyłanie powiadomień za pośrednictwem usługi zaplecza.
Wysyłanie powiadomienia testowego
Otwórz nową kartę w programie Postman.
Ustaw żądanie na POST, a następnie wprowadź następujący adres:
https://<app_name>.azurewebsites.net/api/notifications/requests
Jeśli wybrano opcję ukończenia Uwierzytelnianie klientów przy użyciu klucza interfejsu API, pamiętaj, aby skonfigurować nagłówki żądań tak, aby zawierały wartość apikey.
Klucz Wartość apikey <your_api_key> Wybierz opcję raw dla Body, a następnie wybierz JSON z listy opcji formatowania, a następnie dołącz symbol zastępczy zawartości JSON:
{ "text": "Message from Postman!", "action": "action_a" }
Wybierz przycisk kod
, który znajduje się pod przyciskiem Zapisz w prawym górnym rogu okna. Żądanie powinno wyglądać podobnie do poniższego przykładu wyświetlanego dla HTML (w zależności od tego, czy dołączono nagłówek apikey):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" }
Uruchom aplikację
PushDemo na jednej lub obu platformach docelowych (Android i iOS). Nuta
Jeśli testujesz android upewnij się, że nie działasz w Debugowanielub jeśli aplikacja została wdrożona, uruchamiając aplikację, wymuś zamknięcie aplikacji i uruchom ją ponownie z poziomu modułu uruchamiania.
W aplikacji
PushDemo naciśnij przycisk Zarejestruj .Po powrocie Postmanzamknij okno Generuj fragmenty kodu (jeśli jeszcze tego nie zrobiono), a następnie kliknij przycisk Wyślij.
Sprawdź, czy otrzymasz odpowiedź 200 OK w Postman, a alert zostanie wyświetlony w aplikacji z akcję ActionA odebraną.
Zamknij aplikację
PushDemo, a następnie ponownie kliknij przycisk Wyślij w .Postman Sprawdź, czy ponownie 200 OK odpowiedzi w Postman. Sprawdź, czy powiadomienie jest wyświetlane w obszarze powiadomień dla aplikacji PushDemo z poprawnym komunikatem.
Naciśnij powiadomienie, aby potwierdzić otwarcie aplikacji i wyświetlenie akcji ActionA odebranych alertu.
Wróć
, zmodyfikuj poprzednią treść żądania, aby wysłać powiadomienie dyskretne określającePostman action_b zamiastaction_a dla wartości akcji. { "action": "action_b", "silent": true }
Po otwarciu aplikacji kliknij przycisk Wyślij w Postman.
Sprawdź, czy otrzymasz odpowiedź
200 OK w i że alert jest wyświetlany w aplikacji zPostman akcję ActionB odebraną zamiast odebranej akcjiActionA .Zamknij aplikację
PushDemo, a następnie ponownie kliknij przycisk Wyślij w .Postman Sprawdź, czy otrzymasz odpowiedź 200 OK w Postman i że powiadomienie dyskretne nie jest wyświetlane w obszarze powiadomień.
Rozwiązywanie problemów
Brak odpowiedzi z usługi zaplecza
Podczas testowania lokalnego upewnij się, że usługa zaplecza jest uruchomiona i używa poprawnego portu.
Jeśli testowanie pod kątem aplikacji interfejsu API platformy Azure, sprawdź, czy usługa jest uruchomiona i została wdrożona i została uruchomiona bez błędów.
Upewnij się, że adres podstawowy został poprawnie określony w postman lub w konfiguracji aplikacji mobilnej podczas testowania za pośrednictwem klienta. Adres podstawowy powinien wskazywać https://<api_name>.azurewebsites.net/
lub https://localhost:5001/
podczas testowania lokalnego.
Nie otrzymuję powiadomień w systemie Android po uruchomieniu lub zatrzymaniu sesji debugowania
Upewnij się, że zarejestrujesz się ponownie po uruchomieniu lub zatrzymaniu sesji debugowania. Debuger spowoduje wygenerowanie nowego tokenu Firebase. Należy również zaktualizować instalację centrum powiadomień.
Odbieranie kodu stanu 401 z usługi zaplecza
Sprawdź, czy ustawiasz nagłówek żądania apikey, a ta wartość jest zgodna z wartością skonfigurowaną dla usługi zaplecza.
Jeśli ten błąd występuje podczas testowania lokalnego, upewnij się, że wartość klucza zdefiniowana w konfiguracji klienta jest zgodna z wartością Authentication:ApiKey wartością ustawienia użytkownika używaną przez interfejs API .
Jeśli testujesz przy użyciuaplikacji interfejsu API
Nuta
Jeśli to ustawienie zostało utworzone lub zmienione po wdrożeniu usługi zaplecza, musisz ponownie uruchomić usługę w celu jej zastosowania.
Jeśli nie chcesz ukończyć uwierzytelniać klientów przy użyciu klucza interfejsu API, upewnij się, że nie zastosowano atrybutu Authorize do klasy NotificationsController.
Odbieranie kodu stanu 404 z usługi zaplecza
Sprawdź, czy punkt końcowy i metoda żądania HTTP są poprawne. Na przykład punkty końcowe powinny wskazywać na:
-
[PUT]
https://<api_name>.azurewebsites.net/api/notifications/installations
-
[DELETE]
https://<api_name>.azurewebsites.net/api/notifications/installations/<installation_id>
-
[POST]
https://<api_name>.azurewebsites.net/api/notifications/requests
Lub podczas testowania lokalnego:
-
[PUT]
https://localhost:5001/api/notifications/installations
-
[DELETE]
https://localhost:5001/api/notifications/installations/<installation_id>
-
[POST]
https://localhost:5001/api/notifications/requests
Podczas określania adresu podstawowego w aplikacji klienckiej upewnij się, że kończy się /
. Adres podstawowy powinien wskazywać https://<api_name>.azurewebsites.net/
lub https://localhost:5001/
podczas testowania lokalnego.
Nie można zarejestrować i zostanie wyświetlony komunikat o błędzie centrum powiadomień
Sprawdź, czy urządzenie testowe ma łączność sieciową. Następnie określ kod stanu odpowiedzi Http, ustawiając punkt przerwania w celu sprawdzenia wartości właściwości
Przejrzyj poprzednie sugestie dotyczące rozwiązywania problemów, jeśli mają zastosowanie na podstawie kodu stanu.
Ustaw punkt przerwania w wierszach, które zwracają te określone kody stanu dla odpowiedniego interfejsu API. Następnie spróbuj wywołać usługę zaplecza podczas lokalnego debugowania.
Sprawdź, czy usługa zaplecza działa zgodnie z oczekiwaniami za pośrednictwem Postman przy użyciu odpowiedniego ładunku. Użyj rzeczywistego ładunku utworzonego przez kod klienta dla danej platformy.
Przejrzyj sekcje konfiguracji specyficzne dla platformy, aby upewnić się, że nie pominięto żadnych kroków. Sprawdź, czy odpowiednie wartości są rozpoznawane dla zmiennych installation id
i token
dla odpowiedniej platformy.
Nie można rozpoznać identyfikatora komunikatu o błędzie urządzenia
Przejrzyj sekcje konfiguracji specyficzne dla platformy, aby upewnić się, że nie pominięto żadnych kroków.
Powiązane linki
- omówienie usługi Azure Notification Hubs
- instalowanie flutter w systemie macOS
- Instalowanie flutter w systemie Windows
- zestaw SDK usługi Notification Hubs na potrzeby operacji zaplecza
- zestaw SDK usługi Notification Hubs w usłudze GitHub
- Rejestrowanie przy użyciu zaplecza aplikacji
- zarządzanie rejestracją
- Praca z tagami
- Praca z szablonami niestandardowymi
Następne kroki
Teraz powinna istnieć podstawowa aplikacja Flutter połączona z centrum powiadomień za pośrednictwem usługi zaplecza i może wysyłać i odbierać powiadomienia.
Prawdopodobnie musisz dostosować przykład użyty w tym samouczku, aby dopasować go do własnego scenariusza. Zalecane jest również zaimplementowanie bardziej niezawodnej obsługi błędów, logiki ponawiania prób i rejestrowania.
programu Visual Studio App Center można szybko włączyć do aplikacji mobilnych, zapewniając analizy i diagnostyki, aby ułatwić rozwiązywanie problemów.