Samouczek: wysyłanie powiadomień wypychanych do aplikacji platformy Xamarin.Forms 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 platformy Xamarin. Forms przeznaczonej dla 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 platformy Xamarin.Forms.
- 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.
- Komputer Mac z zainstalowanym programem
Visual Studio dla komputerów Mac lub komputerem z programem Visual Studio 2019 . - użytkownicy programu Visual Studio 2019 muszą również mieć zainstalowane Programowanie aplikacji mobilnych przy użyciu platformy .NET oraz ASP.NET i tworzenia aplikacji internetowych obciążeń.
- 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 i internetowego interfejsu API
- konsoli Google Firebase Console
- microsoft Azure i Wysyłanie powiadomień wypychanych do aplikacji systemu iOS przy użyciu usługi Azure Notification Hubs.
- Xamarin i zestawu narzędzi Xamarin.Forms.
Ważny
Podane kroki są specyficzne dla programu Visual Studio dla komputerów Mac. Można użyć Visual Studio 2019, ale mogą istnieć pewne różnice, które należy uzgodnić. Na przykład opisy interfejsu użytkownika i przepływów pracy, nazwy szablonów, konfiguracja środowiska itd.
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 platformy
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 platformy Xamarin.Forms
W tej sekcji utworzysz aplikacji mobilnej platformy Xamarin.Forms 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 Xamarin.Forms
W programie Visual Studioutwórz nowe rozwiązanie Xamarin.Forms przy użyciu pustej aplikacji formularzy jako szablonu i wprowadź pushDemo dla nazwy projektu .
Nuta
W oknie dialogowym Konfigurowanie pustej aplikacji formularzy upewnij się, że identyfikator organizacji jest zgodny z wartością użytą wcześniej i że zaznaczono zarówno systemu Android, jak i obiektów docelowych systemu iOS.
Control + Click on the PushDemo solution, a następnie wybierz pozycję Update NuGet Packages.
Control + Click on the PushDemo solution, a następnie wybierz pozycję Zarządzaj pakietami NuGet..
Wyszukaj Newtonsoft.Json i upewnij się, że jest zaznaczone.
Kliknij przycisk Dodaj pakiety, a następnie kliknij pozycję Akceptuj po wyświetleniu monitu o zaakceptowanie postanowień licencyjnych.
Skompiluj i uruchom aplikację na każdej platformie docelowej (Command + Enter), aby przetestować uruchamianie szablonów aplikacji na urządzeniach.
Implementowanie składników międzyplatformowych
Control Click on thePushDemo project(PushDemo) wybierz New Folder z menuAdd (DodajAdd usingModels as theFolder Name ).Control + Kliknij w folderze Models, a następnie wybierz pozycję Nowy plik... z menu Dodaj.
Wybierz pozycję Ogólne>Empty Class, wprowadź DeviceInstallation.cs, a następnie dodaj następującą implementację.
using System.Collections.Generic; using Newtonsoft.Json; namespace PushDemo.Models { public class DeviceInstallation { [JsonProperty("installationId")] public string InstallationId { get; set; } [JsonProperty("platform")] public string Platform { get; set; } [JsonProperty("pushChannel")] public string PushChannel { get; set; } [JsonProperty("tags")] public List<string> Tags { get; set; } = new List<string>(); } }
Dodaj
Empty Enumeration do folderu ModelsModels o nazwie PushDemoAction.cs z następującą implementacją.namespace PushDemo.Models { public enum PushDemoAction { ActionA, ActionB } }
Dodaj nowy folder do projektu
PushDemo o nazwieServices następnie dodaj klasyempty do tego folderu o nazwie ServiceContainer.cs z następującą implementacją.using System; using System.Collections.Generic; namespace PushDemo.Services { public static class ServiceContainer { static readonly Dictionary<Type, Lazy<object>> services = new Dictionary<Type, Lazy<object>>(); public static void Register<T>(Func<T> function) => services[typeof(T)] = new Lazy<object>(() => function()); public static T Resolve<T>() => (T)Resolve(typeof(T)); public static object Resolve(Type type) { { if (services.TryGetValue(type, out var service)) return service.Value; throw new KeyNotFoundException($"Service not found for type '{type}'"); } } } }
Nuta
Jest to przycięta wersja
ServiceContainer klasy z repozytoriumXamCAT. Będzie on używany jako lekki kontener IoC (inversion of Control). Dodaj pusty interfejs
do folderu Services o nazwie IDeviceInstallationService.cs , a następnie dodaj następujący kod.using PushDemo.Models; namespace PushDemo.Services { public interface IDeviceInstallationService { string Token { get; set; } bool NotificationsSupported { get; } string GetDeviceId(); DeviceInstallation GetDeviceInstallation(params string[] tags); } }
Nuta
Ten interfejs zostanie zaimplementowany i uruchomiony przez każdy element docelowy później, aby zapewnić funkcjonalność specyficzną dla platformy i deviceInstallation informacje wymagane przez usługę zaplecza.
Dodaj kolejny Empty Interface do folderu Services o nazwie INotificationRegistrationService.cs, a następnie dodaj następujący kod.
using System.Threading.Tasks; namespace PushDemo.Services { public interface INotificationRegistrationService { Task DeregisterDeviceAsync(); Task RegisterDeviceAsync(params string[] tags); Task RefreshRegistrationAsync(); } }
Nuta
Będzie to obsługiwać interakcję między klientem a usługą zaplecza.
Dodaj kolejny
Empty Interface do folderu servicesServices o nazwie INotificationActionService.cs , a następnie dodaj następujący kod.namespace PushDemo.Services { public interface INotificationActionService { void TriggerAction(string action); } }
Nuta
Jest to używany jako prosty mechanizm umożliwiający scentralizowanie obsługi akcji powiadomień.
Dodaj pusty interfejs
do folderu usług o nazwie IPushDemoNotificationActionService.cs pochodzącego zINotificationActionService z następującą implementacją.using System; using PushDemo.Models; namespace PushDemo.Services { public interface IPushDemoNotificationActionService : INotificationActionService { event EventHandler<PushDemoAction> ActionTriggered; } }
Nuta
Ten typ jest specyficzny dla aplikacji PushDemo i używa PushDemoAction wyliczania w celu zidentyfikowania akcji wyzwalanej w sposób silnie typiczny.
Dodaj
Empty Class do folderuServices o nazwie NotificationRegistrationService.cs implementowaniaINotificationRegistrationService przy użyciu następującego kodu.using System; using System.Net.Http; using System.Text; using System.Threading.Tasks; using Newtonsoft.Json; using PushDemo.Models; using Xamarin.Essentials; namespace PushDemo.Services { public class NotificationRegistrationService : INotificationRegistrationService { const string RequestUrl = "api/notifications/installations"; const string CachedDeviceTokenKey = "cached_device_token"; const string CachedTagsKey = "cached_tags"; string _baseApiUrl; HttpClient _client; IDeviceInstallationService _deviceInstallationService; public NotificationRegistrationService(string baseApiUri, string apiKey) { _client = new HttpClient(); _client.DefaultRequestHeaders.Add("Accept", "application/json"); _client.DefaultRequestHeaders.Add("apikey", apiKey); _baseApiUrl = baseApiUri; } IDeviceInstallationService DeviceInstallationService => _deviceInstallationService ?? (_deviceInstallationService = ServiceContainer.Resolve<IDeviceInstallationService>()); public async Task DeregisterDeviceAsync() { var cachedToken = await SecureStorage.GetAsync(CachedDeviceTokenKey) .ConfigureAwait(false); if (cachedToken == null) return; var deviceId = DeviceInstallationService?.GetDeviceId(); if (string.IsNullOrWhiteSpace(deviceId)) throw new Exception("Unable to resolve an ID for the device."); await SendAsync(HttpMethod.Delete, $"{RequestUrl}/{deviceId}") .ConfigureAwait(false); SecureStorage.Remove(CachedDeviceTokenKey); SecureStorage.Remove(CachedTagsKey); } public async Task RegisterDeviceAsync(params string[] tags) { var deviceInstallation = DeviceInstallationService?.GetDeviceInstallation(tags); await SendAsync<DeviceInstallation>(HttpMethod.Put, RequestUrl, deviceInstallation) .ConfigureAwait(false); await SecureStorage.SetAsync(CachedDeviceTokenKey, deviceInstallation.PushChannel) .ConfigureAwait(false); await SecureStorage.SetAsync(CachedTagsKey, JsonConvert.SerializeObject(tags)); } public async Task RefreshRegistrationAsync() { var cachedToken = await SecureStorage.GetAsync(CachedDeviceTokenKey) .ConfigureAwait(false); var serializedTags = await SecureStorage.GetAsync(CachedTagsKey) .ConfigureAwait(false); if (string.IsNullOrWhiteSpace(cachedToken) || string.IsNullOrWhiteSpace(serializedTags) || string.IsNullOrWhiteSpace(DeviceInstallationService.Token) || cachedToken == DeviceInstallationService.Token) return; var tags = JsonConvert.DeserializeObject<string[]>(serializedTags); await RegisterDeviceAsync(tags); } async Task SendAsync<T>(HttpMethod requestType, string requestUri, T obj) { string serializedContent = null; await Task.Run(() => serializedContent = JsonConvert.SerializeObject(obj)) .ConfigureAwait(false); await SendAsync(requestType, requestUri, serializedContent); } async Task SendAsync( HttpMethod requestType, string requestUri, string jsonRequest = null) { var request = new HttpRequestMessage(requestType, new Uri($"{_baseApiUrl}{requestUri}")); if (jsonRequest != null) request.Content = new StringContent(jsonRequest, Encoding.UTF8, "application/json"); var response = await _client.SendAsync(request).ConfigureAwait(false); response.EnsureSuccessStatusCode(); } } }
Nuta
Argument apiKey
jest wymagany tylko w przypadku wybrania uwierzytelnienia klientów przy użyciu klucza interfejsu API.Dodaj
Empty Class do folderuServices o nazwie PushDemoNotificationActionService.cs implementowaniaIPushDemoNotificationActionService przy użyciu następującego kodu.using System; using System.Collections.Generic; using System.Linq; using PushDemo.Models; namespace PushDemo.Services { public class PushDemoNotificationActionService : IPushDemoNotificationActionService { readonly Dictionary<string, PushDemoAction> _actionMappings = new Dictionary<string, PushDemoAction> { { "action_a", PushDemoAction.ActionA }, { "action_b", PushDemoAction.ActionB } }; public event EventHandler<PushDemoAction> ActionTriggered = delegate { }; public void TriggerAction(string action) { if (!_actionMappings.TryGetValue(action, out var pushDemoAction)) return; List<Exception> exceptions = new List<Exception>(); foreach (var handler in ActionTriggered?.GetInvocationList()) { try { handler.DynamicInvoke(this, pushDemoAction); } catch (Exception ex) { exceptions.Add(ex); } } if (exceptions.Any()) throw new AggregateException(exceptions); } } }
Dodaj
Empty Class do projektuPushDemo o nazwie Config.cs z następującą implementacją.namespace PushDemo { public static partial class Config { public static string ApiKey = "API_KEY"; public static string BackendServiceEndpoint = "BACKEND_SERVICE_ENDPOINT"; } }
Nuta
Jest to prosty sposób na zachowanie wpisów tajnych poza kontrolą źródła. Możesz zastąpić te wartości w ramach zautomatyzowanej kompilacji lub zastąpić je przy użyciu lokalnej klasy częściowej. Zrobisz to w następnym kroku.
Pole ApiKey jest wymagane tylko wtedy, gdy wybrano opcję ukończenia Uwierzytelnianie klientów przy użyciu klucza interfejsu API.
Dodaj kolejny Empty Class do projektu PushDemo tym razem o nazwie Config.local_secrets.cs z następującą implementacją.
namespace PushDemo { public static partial class Config { static Config() { ApiKey = "<your_api_key>"; BackendServiceEndpoint = "<your_api_app_url>"; } } }
Nuta
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ć . Pamiętaj, aby dodać *.local_secrets.*
do pliku gitignore, aby uniknąć zatwierdzania tego pliku.Pole ApiKey jest wymagane tylko wtedy, gdy wybrano opcję ukończenia Uwierzytelnianie klientów przy użyciu klucza interfejsu API.
Dodaj Empty Class do projektu PushDemo o nazwie Bootstrap.cs z następującą implementacją.
using System; using PushDemo.Services; namespace PushDemo { public static class Bootstrap { public static void Begin(Func<IDeviceInstallationService> deviceInstallationService) { ServiceContainer.Register(deviceInstallationService); ServiceContainer.Register<IPushDemoNotificationActionService>(() => new PushDemoNotificationActionService()); ServiceContainer.Register<INotificationRegistrationService>(() => new NotificationRegistrationService( Config.BackendServiceEndpoint, Config.ApiKey)); } } }
Nuta
Metoda Begin będzie wywoływana przez każdą platformę po uruchomieniu aplikacji przekazującej implementację specyficzną dla platformy IDeviceInstallationService.
Argument konstruktora NotificationRegistrationServiceapiKey jest wymagany tylko w przypadku wybrania ukończenia Uwierzytelnianie klientów przy użyciu klucza interfejsu API.
Implementowanie międzyplatformowego interfejsu użytkownika
W projekcie
PushDemo otwórz MainPage.xaml i zastąp kontrolkę StackLayout następującym kodem.<StackLayout VerticalOptions="EndAndExpand" HorizontalOptions="FillAndExpand" Padding="20,40"> <Button x:Name="RegisterButton" Text="Register" Clicked="RegisterButtonClicked" /> <Button x:Name="DeregisterButton" Text="Deregister" Clicked="DeregisterButtonClicked" /> </StackLayout>
Teraz w MainPage.xaml.csdodaj pole zapasowe do przechowywania odwołania do implementacji INotificationRegistrationService.
readonly INotificationRegistrationService _notificationRegistrationService;
W konstruktorze
MainPage rozwiąż implementację INotificationRegistrationService przy użyciuServiceContainer i przypisz ją do pola .notificationRegistrationService public MainPage() { InitializeComponent(); _notificationRegistrationService = ServiceContainer.Resolve<INotificationRegistrationService>(); }
Zaimplementuj programy obsługi zdarzeń dla przycisków
RegisterButton iDeregisterButton przyciskówklikniętymi zdarzeniami wywołującymi odpowiednie metodyRegister Deregister .void RegisterButtonClicked(object sender, EventArgs e) => _notificationRegistrationService.RegisterDeviceAsync().ContinueWith((task) => { ShowAlert(task.IsFaulted ? task.Exception.Message : $"Device registered"); }); void DeregisterButtonClicked(object sender, EventArgs e) => _notificationRegistrationService.DeregisterDeviceAsync().ContinueWith((task) => { ShowAlert(task.IsFaulted ? task.Exception.Message : $"Device deregistered"); }); void ShowAlert(string message) => MainThread.BeginInvokeOnMainThread(() => DisplayAlert("PushDemo", message, "OK").ContinueWith((task) => { if (task.IsFaulted) throw task.Exception; }));
Teraz w App.xaml.csupewnij się, że następujące przestrzenie nazw są przywołyne.
using PushDemo.Models; using PushDemo.Services; using Xamarin.Essentials; using Xamarin.Forms;
Zaimplementuj program obsługi zdarzeń dla zdarzenia IPushDemoNotificationActionServiceActionTriggered zdarzenia.
void NotificationActionTriggered(object sender, PushDemoAction e) => ShowActionAlert(e); void ShowActionAlert(PushDemoAction action) => MainThread.BeginInvokeOnMainThread(() => MainPage?.DisplayAlert("PushDemo", $"{action} action received", "OK") .ContinueWith((task) => { if (task.IsFaulted) throw task.Exception; }));
W konstruktorze App rozwiąż implementację IPushNotificationActionService przy użyciu zdarzenia ServiceContainer i zasubskrybuj zdarzenie IPushDemoNotificationActionServiceActionTriggered.
public App() { InitializeComponent(); ServiceContainer.Resolve<IPushDemoNotificationActionService>() .ActionTriggered += NotificationActionTriggered; MainPage = new MainPage(); }
Nuta
Jest to po prostu zademonstrowanie potwierdzenia i propagacji akcji powiadomień wypychanych. Zazwyczaj są one obsługiwane w trybie dyskretnym, na przykład przechodzenie do określonego widoku lub odświeżanie niektórych danych zamiast wyświetlania alertu za pośrednictwem strony głównej , MainPage w tym przypadku.
Konfigurowanie natywnego projektu systemu Android na potrzeby powiadomień wypychanych
Weryfikowanie nazwy i uprawnień pakietu
W
PushDemo.Android otwórz Opcje projektu , a następnieaplikacji systemu Android w sekcjiBuild .Sprawdź, czy nazwa pakietu
odpowiada wartości użytej w projekcie Firebase Console PushDemo. Nazwa pakietu miała format com.<organization>.pushdemo
.Ustaw minimalną wersję systemu Android
na Android 8.0 (poziom interfejsu API 26) orazdocelową wersję systemu Android na najnowszy poziom interfejsu API . 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.
Upewnij się, że uprawnienia INTERNET i READ_PHONE_STATE są włączone w obszarze Wymagane uprawnienia.
Kliknij przycisk OK
Dodawanie bazowych usług Xamarin Google Play i pakietów Xamarin.Firebase.Messaging
W
PushDemo.Android Control Kliknij w folderzePackages , a następnie wybierz pozycjęZarządzaj pakietami NuGet... .Wyszukaj Xamarin.GooglePlayServices.Base (nie Piwnica) i upewnij się, że jest zaznaczone.
Wyszukaj Xamarin.Firebase.Messaging i upewnij się, że jest zaznaczone.
Kliknij pozycję Dodaj pakiety, a następnie kliknij pozycję Zaakceptuj po wyświetleniu monitu o zaakceptowanie postanowień licencyjnych .
Dodawanie pliku JSON usług Google Services
Kontrolka + Kliknij w projekcie
PushDemo.Android
, a następnie wybierz pozycję Istniejący plik... z menu Dodaj.Wybierz pobrany wcześniej plik
google-services.json podczas konfigurowania projektuPushDemo w konsoli programuFirebase, a następnie kliknij pozycję Otwórz .Po wyświetleniu monitu wybierz opcję Skopiuj plik do katalogu.
Kontrolka + Kliknij w pliku google-services.json z poziomu projektu
PushDemo.Android
, a następnie upewnij się, że GoogleServicesJson jest ustawiona jako Akcja kompilacji.
Obsługa powiadomień wypychanych dla systemu Android
Control + Kliknij w projekcie
PushDemo.Android
, wybierz pozycję New Folder w menu Dodaj, a następnie kliknij przycisk Dodaj przy użyciu Services jako nazwę folderu .Kontrolka Kliknij w folderze usługServices, a następnie wybierz pozycję Nowy plik... z menuDodaj .Wybierz
Pusta klasa , wprowadźDeviceInstallationService.cs dlanazwa, a następnie kliknij pozycję Nowa dodając następującą implementację.using System; using Android.App; using Android.Gms.Common; using PushDemo.Models; using PushDemo.Services; using static Android.Provider.Settings; namespace PushDemo.Droid.Services { public class DeviceInstallationService : IDeviceInstallationService { public string Token { get; set; } public bool NotificationsSupported => GoogleApiAvailability.Instance .IsGooglePlayServicesAvailable(Application.Context) == ConnectionResult.Success; public string GetDeviceId() => Secure.GetString(Application.Context.ContentResolver, Secure.AndroidId); public DeviceInstallation GetDeviceInstallation(params string[] tags) { if (!NotificationsSupported) throw new Exception(GetPlayServicesError()); if (string.IsNullOrWhiteSpace(Token)) throw new Exception("Unable to resolve token for FCM"); var installation = new DeviceInstallation { InstallationId = GetDeviceId(), Platform = "fcm", PushChannel = Token }; installation.Tags.AddRange(tags); return installation; } string GetPlayServicesError() { int resultCode = GoogleApiAvailability.Instance.IsGooglePlayServicesAvailable(Application.Context); if (resultCode != ConnectionResult.Success) return GoogleApiAvailability.Instance.IsUserResolvableError(resultCode) ? GoogleApiAvailability.Instance.GetErrorString(resultCode) : "This device is not supported"; return "An error occurred preventing the use of push notifications"; } } }
Nuta
Ta klasa udostępnia unikatowy identyfikator (przy użyciu Secure.AndroidId) w ramach ładunku rejestracji centrum powiadomień.
Dodaj kolejny
Empty Class do folderu servicesServices o nazwie PushNotificationFirebaseMessagingService.cs , a następnie dodaj następującą implementację.using Android.App; using Android.Content; using Firebase.Messaging; using PushDemo.Services; namespace PushDemo.Droid.Services { [Service] [IntentFilter(new[] { "com.google.firebase.MESSAGING_EVENT" })] public class PushNotificationFirebaseMessagingService : FirebaseMessagingService { IPushDemoNotificationActionService _notificationActionService; INotificationRegistrationService _notificationRegistrationService; IDeviceInstallationService _deviceInstallationService; IPushDemoNotificationActionService NotificationActionService => _notificationActionService ?? (_notificationActionService = ServiceContainer.Resolve<IPushDemoNotificationActionService>()); INotificationRegistrationService NotificationRegistrationService => _notificationRegistrationService ?? (_notificationRegistrationService = ServiceContainer.Resolve<INotificationRegistrationService>()); IDeviceInstallationService DeviceInstallationService => _deviceInstallationService ?? (_deviceInstallationService = ServiceContainer.Resolve<IDeviceInstallationService>()); public override void OnNewToken(string token) { DeviceInstallationService.Token = token; NotificationRegistrationService.RefreshRegistrationAsync() .ContinueWith((task) => { if (task.IsFaulted) throw task.Exception; }); } public override void OnMessageReceived(RemoteMessage message) { if(message.Data.TryGetValue("action", out var messageAction)) NotificationActionService.TriggerAction(messageAction); } } }
W MainActivity.csupewnij się, że następujące przestrzenie nazw zostały dodane na początku pliku.
using System; using Android.App; using Android.Content; using Android.Content.PM; using Android.OS; using Android.Runtime; using Firebase.Iid; using PushDemo.Droid.Services; using PushDemo.Services;
W MainActivity.csustaw LaunchMode na SingleTop, aby MainActivity nie zostanie ponownie utworzona po otwarciu.
[Activity( Label = "PushDemo", LaunchMode = LaunchMode.SingleTop, Icon = "@mipmap/icon", Theme = "@style/MainTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
Dodaj właściwości prywatne i odpowiadające im pola zapasowe, aby przechowywać odwołanie do implementacji usługi IPushNotificationActionService i IDeviceInstallationService.
IPushDemoNotificationActionService _notificationActionService; IDeviceInstallationService _deviceInstallationService; IPushDemoNotificationActionService NotificationActionService => _notificationActionService ?? (_notificationActionService = ServiceContainer.Resolve<IPushDemoNotificationActionService>()); IDeviceInstallationService DeviceInstallationService => _deviceInstallationService ?? (_deviceInstallationService = ServiceContainer.Resolve<IDeviceInstallationService>());
Zaimplementuj interfejs
IOnSuccessListener , aby pobrać i zapisać tokenFirebase. public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity, Android.Gms.Tasks.IOnSuccessListener { ... public void OnSuccess(Java.Lang.Object result) => DeviceInstallationService.Token = result.Class.GetMethod("getToken").Invoke(result).ToString(); }
Dodaj nową metodę o nazwie ProcessNotificationActions, która sprawdzi, czy dana Intent ma dodatkową wartość o nazwie akcji. Warunkowe wyzwalanie tej akcji przy użyciu implementacji IPushDemoNotificationActionService.
void ProcessNotificationActions(Intent intent) { try { if (intent?.HasExtra("action") == true) { var action = intent.GetStringExtra("action"); if (!string.IsNullOrEmpty(action)) NotificationActionService.TriggerAction(action); } } catch (Exception ex) { System.Diagnostics.Debug.WriteLine(ex.Message); } }
Zastąpi metodę OnNewIntent, aby wywołać metodę ProcessNotificationActions.
protected override void OnNewIntent(Intent intent) { base.OnNewIntent(intent); ProcessNotificationActions(intent); }
Nuta
Ponieważ
LaunchMode dla działania jest ustawiona na SingleTop, intencja zostanie wysłana do istniejącego wystąpienia działania za pośrednictwem Metoda OnNewIntentzamiast metody on OnCreate i dlatego należy obsługiwać intencję przychodzącą zarówno wmetodach on OnCreate , jak iOnNewIntent .Zaktualizuj metodę OnCreate, aby wywołać metodę
Bootstrap.Begin
bezpośrednio po wywołaniu w celubase.OnCreate
przekazania implementacji IDeviceInstallationService.Bootstrap.Begin(() => new DeviceInstallationService());
W tej samej metodzie warunkowo wywołaj GetInstanceId w wystąpieniu usługi FirebaseApp bezpośrednio po wywołaniu metody
Bootstrap.Begin
, dodając MainActivity jako IOnSuccessListener.if (DeviceInstallationService.NotificationsSupported) { FirebaseInstanceId.GetInstance(Firebase.FirebaseApp.Instance) .GetInstanceId() .AddOnSuccessListener(this); }
Nadal w OnCreatewywołaj ProcessNotificationActions natychmiast po wywołaniu
LoadApplication
przekazania bieżącej Intent.... LoadApplication(new App()); ProcessNotificationActions(Intent);
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 pliku Info.plist i Entitlements.plist
Upewnij się, że zalogowano się do konta dewelopera
Firmy Apple wpreferencjach programu Visual Studio ... konta deweloperów firmy Apple oraz pobrano odpowiednicertyfikat i profil aprowizacji. Te zasoby powinny zostać utworzone w ramach poprzednich kroków. W
PushDemo.iOS otwórz plikInfo.plist i upewnij się, że BundleIdentifierjest zgodna z wartością użytą dla odpowiedniego profilu aprowizacji w witrynie Apple Developer Portal . BundleIdentifier był w formaciecom.<organization>.PushDemo
.W tym samym pliku ustaw minimalną wersję systemu na 13.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 opcje projektu
dla PushDemo.iOS (kliknij dwukrotnie projekt).W opcje projektuw obszarze Kompilacja > podpisywania pakietów systemu iOSupewnij się, że konto dewelopera zostało wybrane w obszarze Team. Następnie upewnij się, że opcja "Automatyczne zarządzanie podpisywaniem" jest zaznaczona, a certyfikat podpisywania i profil aprowizacji są wybierane automatycznie.
Nuta
Jeśli certyfikat podpisywania
i profil aprowizacji teamnie zostały wybrane automatycznie, wybierz pozycję tożsamości podpisywaniaManual Provisioning , a następnie kliknij pozycjęBundle Signing Options . Upewnij się, żedla wybrano profil aprowizacji dla Debugowanie i konfiguracjeRelease upewnij się, żeiPhone platformyw obu przypadkach. W
PushDemo.iOS otwórzEntitlements.plist i upewnij się, żewłącz powiadomienia wypychane jest sprawdzane po wyświetleniu na karcieUpoważnienia . Następnie upewnij się, że ustawienie środowiska usługi APSjest ustawione na programistyczne po wyświetleniu na karcie źródła .
Obsługa powiadomień wypychanych dla systemu iOS
Control + Kliknij w projekcie PushDemo.iOS wybierz pozycję New Folder z menu Add (Dodaj Add using Services as the Folder Name).
Kontrolka Kliknij w folderze usługServices, a następnie wybierz pozycję Nowy plik... z menuDodaj .Wybierz
Pusta klasa , wprowadźDeviceInstallationService.cs dlanazwa, a następnie kliknij pozycję Nowa dodając następującą implementację.using System; using PushDemo.Models; using PushDemo.Services; using UIKit; namespace PushDemo.iOS.Services { public class DeviceInstallationService : IDeviceInstallationService { const int SupportedVersionMajor = 13; const int SupportedVersionMinor = 0; public string Token { get; set; } public bool NotificationsSupported => UIDevice.CurrentDevice.CheckSystemVersion(SupportedVersionMajor, SupportedVersionMinor); public string GetDeviceId() => UIDevice.CurrentDevice.IdentifierForVendor.ToString(); public DeviceInstallation GetDeviceInstallation(params string[] tags) { if (!NotificationsSupported) throw new Exception(GetNotificationsSupportError()); if (string.IsNullOrWhiteSpace(Token)) throw new Exception("Unable to resolve token for APNS"); var installation = new DeviceInstallation { InstallationId = GetDeviceId(), Platform = "apns", PushChannel = Token }; installation.Tags.AddRange(tags); return installation; } string GetNotificationsSupportError() { if (!NotificationsSupported) return $"This app only supports notifications on iOS {SupportedVersionMajor}.{SupportedVersionMinor} and above. You are running {UIDevice.CurrentDevice.SystemVersion}."; if (Token == null) return $"This app can support notifications but you must enable this in your settings."; return "An error occurred preventing the use of push notifications"; } } }
Nuta
Ta klasa zawiera unikatowy identyfikator (przy użyciu wartości UIDevice.IdentifierForVendor) i ładunku rejestracji centrum powiadomień.
Dodaj nowy folder do projektu PushDemo.iOS o nazwie Extensions następnie dodaj Empty Class do tego folderu o nazwie NSDataExtensions.cs z następującą implementacją.
using System.Text; using Foundation; namespace PushDemo.iOS.Extensions { internal static class NSDataExtensions { internal static string ToHexString(this NSData data) { var bytes = data.ToArray(); if (bytes == null) return null; StringBuilder sb = new StringBuilder(bytes.Length * 2); foreach (byte b in bytes) sb.AppendFormat("{0:x2}", b); return sb.ToString().ToUpperInvariant(); } } }
W AppDelegate.csupewnij się, że następujące przestrzenie nazw zostały dodane na początku pliku.
using System; using System.Diagnostics; using System.Threading.Tasks; using Foundation; using PushDemo.iOS.Extensions; using PushDemo.iOS.Services; using PushDemo.Services; using UIKit; using UserNotifications; using Xamarin.Essentials;
Dodaj właściwości prywatne i odpowiednie pola kopii zapasowej, aby przechowywać odwołanie do IPushDemoNotificationActionService, INotificationRegistrationServicei implementacji IDeviceInstallationService.
IPushDemoNotificationActionService _notificationActionService; INotificationRegistrationService _notificationRegistrationService; IDeviceInstallationService _deviceInstallationService; IPushDemoNotificationActionService NotificationActionService => _notificationActionService ?? (_notificationActionService = ServiceContainer.Resolve<IPushDemoNotificationActionService>()); INotificationRegistrationService NotificationRegistrationService => _notificationRegistrationService ?? (_notificationRegistrationService = ServiceContainer.Resolve<INotificationRegistrationService>()); IDeviceInstallationService DeviceInstallationService => _deviceInstallationService ?? (_deviceInstallationService = ServiceContainer.Resolve<IDeviceInstallationService>());
Dodaj metodę RegisterForRemoteNotifications, aby zarejestrować ustawienia powiadomień użytkownika, a następnie na potrzeby powiadomień zdalnych za pomocą usługi APNS.
void RegisterForRemoteNotifications() { MainThread.BeginInvokeOnMainThread(() => { var pushSettings = UIUserNotificationSettings.GetSettingsForTypes( UIUserNotificationType.Alert | UIUserNotificationType.Badge | UIUserNotificationType.Sound, new NSSet()); UIApplication.SharedApplication.RegisterUserNotificationSettings(pushSettings); UIApplication.SharedApplication.RegisterForRemoteNotifications(); }); }
Dodaj metodę CompleteRegistrationAsync, aby ustawić wartość właściwości
IDeviceInstallationService.Token
. Odśwież rejestrację i buforuj token urządzenia, jeśli został on zaktualizowany od czasu jego ostatniego przechowywania.Task CompleteRegistrationAsync(NSData deviceToken) { DeviceInstallationService.Token = deviceToken.ToHexString(); return NotificationRegistrationService.RefreshRegistrationAsync(); }
Dodaj metodę
ProcessNotificationActions do przetwarzania danych powiadomieńNSDictionary i warunkowo wywołując NotificationActionService.TriggerAction .void ProcessNotificationActions(NSDictionary userInfo) { if (userInfo == null) return; try { var actionValue = userInfo.ObjectForKey(new NSString("action")) as NSString; if (!string.IsNullOrWhiteSpace(actionValue?.Description)) NotificationActionService.TriggerAction(actionValue.Description); } catch (Exception ex) { Debug.WriteLine(ex.Message); } }
Zastąpij metodę
RegisteredForRemoteNotifications przekazującą argument deviceTokenken do metody CompleteRegistrationAsync .public override void RegisteredForRemoteNotifications( UIApplication application, NSData deviceToken) => CompleteRegistrationAsync(deviceToken).ContinueWith((task) => { if (task.IsFaulted) throw task.Exception; });
Zastąp metodę ReceivedRemoteNotification przekazującą argument userInfo do metody ProcessNotificationActions.
public override void ReceivedRemoteNotification( UIApplication application, NSDictionary userInfo) => ProcessNotificationActions(userInfo);
Zastąpij metodę FailedToRegisterForRemoteNotifications, aby zarejestrować błąd.
public override void FailedToRegisterForRemoteNotifications( UIApplication application, NSError error) => Debug.WriteLine(error.Description);
Nuta
Jest to bardzo symbol zastępczy. W scenariuszach produkcyjnych należy zaimplementować odpowiednie rejestrowanie i obsługę błędów.
Zaktualizuj metodę finishedLaunching, aby wywołać metodę
Bootstrap.Begin
bezpośrednio po wywołaniu w celuForms.Init
przekazania implementacji IDeviceInstallationService.Bootstrap.Begin(() => new DeviceInstallationService());
W tej samej metodzie warunkowo żądaj autoryzacji i zarejestruj się w celu otrzymywania powiadomień zdalnych natychmiast po
Bootstrap.Begin
.if (DeviceInstallationService.NotificationsSupported) { UNUserNotificationCenter.Current.RequestAuthorization( UNAuthorizationOptions.Alert | UNAuthorizationOptions.Badge | UNAuthorizationOptions.Sound, (approvalGranted, error) => { if (approvalGranted && error == null) RegisterForRemoteNotifications(); }); }
Nadal w FinishedLaunchingwywołaj ProcessNotificationActions natychmiast po wywołaniu metody
LoadApplication
, jeśli argument opcji zawiera UIApplication.LaunchOptionsRemoteNotificationKey przekazując wynikowy obiekt userInfo.using (var userInfo = options?.ObjectForKey( UIApplication.LaunchOptionsRemoteNotificationKey) as NSDictionary) ProcessNotificationActions(userInfo);
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 programu Visual Studio dla komputerów Mac
- Instalowanie platformy Xamarin 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 platformy Xamarin.Forms 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.