Udostępnij za pośrednictwem


Samouczek: wysyłanie powiadomień wypychanych do aplikacji MAUI platformy .NET przy użyciu usługi Azure Notification Hubs za pośrednictwem usługi zaplecza

Przeglądaj przykład. Przeglądanie przykładu

Powiadomienia wypychane dostarczają informacje z systemu zaplecza do aplikacji klienckiej. Firmy Apple, Google i inne platformy mają własną usługę powiadomień wypychanych (PNS). Usługa Azure Notification Hubs umożliwia scentralizowanie powiadomień na różnych platformach, dzięki czemu aplikacja zaplecza może komunikować się z jednym koncentratorem, który zajmuje się dystrybucją powiadomień do poszczególnych systemów powiadomień.

Usługa Azure Notification Hubs wymaga od aplikacji zarejestrowania się w centrum i opcjonalnie definiowania szablonów i/lub subskrybowania tagów:

  • Wykonanie instalacji urządzenia łączy dojście pnS do identyfikatora w usłudze Azure Notification Hub. Aby uzyskać więcej informacji na temat rejestracji, zobacz Zarządzanie rejestracją.
  • Szablony umożliwiają urządzeniom określanie sparametryzowanych szablonów komunikatów. Komunikaty przychodzące można dostosować na urządzenie. Aby uzyskać więcej informacji, zobacz Szablony usługi Notification Hubs.
  • Tagi mogą służyć do subskrybowania kategorii wiadomości, takich jak wiadomości, sport i pogoda. Aby uzyskać więcej informacji, zobacz Routing i wyrażenia tagów.

W tym samouczku użyjesz usługi Azure Notification Hubs do wysyłania powiadomień wypychanych do aplikacji wieloplatformowej interfejsu użytkownika aplikacji platformy .NET (.NET MAUI) przeznaczonej dla systemów Android i iOS. Zaplecze internetowego interfejsu API platformy ASP.NET Core służy do obsługi rejestracji urządzeń dla klienta i inicjowania powiadomień wypychanych. Te operacje są obsługiwane przy użyciu pakietu NuGet Microsoft.Azure.NotificationHubs . Aby uzyskać więcej informacji na temat ogólnego podejścia, zobacz Zarządzanie rejestracją z zaplecza.

W tym samouczku zostały wykonane następujące czynności:

  • Konfigurowanie usług powiadomień wypychanych i usługi Azure Notification Hub.
  • Utwórz aplikację zaplecza interfejsu WebAPI platformy ASP.NET Core.
  • Utwórz aplikację .NET MAUI.
  • Skonfiguruj aplikację systemu Android na potrzeby powiadomień wypychanych.
  • Skonfiguruj aplikację systemu iOS na potrzeby powiadomień wypychanych.
  • Testowanie aplikacji.
  • Rozwiąż wszelkie problemy z konfiguracją i konfiguracją.

Wymagania wstępne

Do ukończenia tego samouczka wymagane są następujące elementy:

  • Konto platformy Azure z aktywną subskrypcją.
  • Komputer PC lub Mac z najnowszą wersją programu Visual Studio/Visual Studio Code z obciążeniem tworzenia aplikacji wieloplatformowych platformy .NET oraz zainstalowanymi obciążeniami tworzenia aplikacji ASP.NET i aplikacji internetowych.

W przypadku systemu Android musisz mieć następujące elementy:

  • Odblokowane przez dewelopera urządzenie fizyczne 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.
  • Komputer Mac z uruchomionym programem Xcode wraz z prawidłowym certyfikatem dewelopera zainstalowanym w pęku kluczy.

Następnie w systemie iOS należy mieć:

  • Symulator systemu iOS 16+ działający w systemie macOS 13 lub nowszym na komputerach Mac z procesorami krzemowymi firmy Apple lub T2.

    LUB

  • Fizyczne urządzenie z systemem iOS zarejestrowane na koncie dewelopera (z systemem iOS 13.0 lub nowszym).

  • Urządzenie fizyczne zarejestrowane na koncie dewelopera firmy Apple i skojarzone z certyfikatem.

Ważne

Symulator systemu iOS obsługuje powiadomienia zdalne w systemie iOS 16 lub nowszym podczas uruchamiania w systemie macOS 13 lub nowszym na komputerach Mac z procesorami krzemowymi firmy Apple lub T2. Jeśli nie spełniasz tych wymagań sprzętowych, musisz mieć aktywne konto dewelopera firmy Apple i urządzenie fizyczne.

Aby wykonać czynności opisane w tym samouczku, musisz zapoznać się z następującymi tematami:

Chociaż ten samouczek jest przeznaczony dla programu Visual Studio, można go wykonać przy użyciu programu Visual Studio Code na komputerze PC lub Mac. Jednak będą istnieć pewne różnice, które wymagają uzgadniania. Na przykład opisy interfejsu użytkownika i przepływów pracy, nazw szablonów i konfiguracji środowiska.

Konfigurowanie usług powiadomień wypychanych i usługi Azure Notification Hub

W tej sekcji skonfigurujesz usługę Firebase Cloud Messaging i Apple Push Notification Services (APNS). Następnie utworzysz i skonfigurujesz usługę Azure Notification Hub do pracy z tymi usługami.

Tworzenie projektu Firebase

Aby utworzyć projekt Firebase:

  1. W przeglądarce internetowej zaloguj się do konsoli firebase.

  2. W konsoli Firebase wybierz przycisk Dodaj projekt i utwórz nowy projekt Firebase, wprowadzając wartość PushDemo jako nazwę projektu.

    Uwaga

    Zostanie wygenerowana unikatowa nazwa. Domyślnie składa się z małego wariantu podanej nazwy oraz wygenerowanej liczby rozdzielonej kreską. Możesz to zmienić, jeśli chcesz, pod warunkiem, że zmiany są nadal unikatowe globalnie.

  3. Po utworzeniu projektu wybierz logo systemu Android, aby dodać aplikację Firebase do aplikacji systemu Android:

    Zrzut ekranu przedstawiający dodawanie aplikacji Firebase do aplikacji systemu Android w konsoli Firebase Cloud Messaging.

  4. Na stronie Dodawanie aplikacji Firebase do aplikacji systemu Android wprowadź nazwę pakietu, opcjonalnie pseudonim aplikacji i wybierz przycisk Zarejestruj aplikację :

    Zrzut ekranu przedstawiający rejestrowanie aplikacji systemu Android przy użyciu aplikacji Firebase.

  5. Na stronie Dodawanie programu Firebase do aplikacji systemu Android wybierz przycisk Pobierz google-services.json i zapisz plik w folderze lokalnym przed wybraniem przycisku Dalej :

    Zrzut ekranu przedstawiający pobieranie pliku JSON usług google.

  6. Na stronie Dodawanie aplikacji Firebase do aplikacji systemu Android wybierz przycisk Dalej.

  7. Na stronie Dodawanie bazy danych Firebase do aplikacji systemu Android wybierz przycisk Kontynuuj w konsoli.

  8. W konsoli Firebase wybierz ikonę Przegląd projektu, a następnie wybierz pozycję Ustawienia projektu:

    Zrzut ekranu przedstawiający wybieranie ustawień projektu w konsoli Firebase Cloud Messaging.

  9. W ustawieniach projektu wybierz kartę Cloud Messaging (Obsługa komunikatów w chmurze). Zobaczysz, że interfejs API usługi Firebase Cloud Messaging (V1) jest włączony:

    Zrzut ekranu przedstawiający potwierdzenie włączenia usługi Firebase Cloud Messaging V1.

  10. W ustawieniach projektu wybierz kartę Konta usług, a następnie wybierz przycisk Generuj nowy klucz prywatny.

  11. W oknie dialogowym Generowanie nowego klucza prywatnego wybierz przycisk Generuj klucz:

    Zrzut ekranu przedstawiający generowanie nowego klucza prywatnego w konsoli Firebase Cloud Messaging.

    Zostanie pobrany plik JSON, który będzie zawierać wartości wprowadzone w usłudze Azure Notification Hub.

Rejestrowanie aplikacji systemu iOS na potrzeby powiadomień wypychanych

Aby wysyłać powiadomienia wypychane do aplikacji systemu iOS, musisz zarejestrować aplikację w usłudze Apple i zarejestrować się w celu otrzymywania powiadomień wypychanych. Można to zrobić, wykonując kroki opisane w następującej dokumentacji usługi Azure Notification Hub:

Jeśli chcesz otrzymywać powiadomienia wypychane na urządzeniu fizycznym, musisz również utworzyć profil aprowizacji.

Ważne

Aby otrzymywać powiadomienia w tle w systemie iOS, musisz dodać tryb tła powiadomień zdalnych do aplikacji. Aby uzyskać więcej informacji, zobacz Włączanie możliwości powiadomień zdalnych w developer.apple.com.

Tworzenie centrum powiadomień platformy Azure

Aby utworzyć centrum powiadomień w witrynie Azure Portal:

  1. W przeglądarce internetowej zaloguj się do witryny Azure Portal.
  2. W witrynie Azure Portal kliknij przycisk Utwórz zasób , a następnie wyszukaj i wybierz pozycję Centrum powiadomień przed wybraniem przycisku Utwórz .
  3. Na stronie Centrum powiadomień wykonaj następujące kroki:
    1. W polu Subskrypcja wybierz nazwę subskrypcji platformy Azure, której chcesz użyć, a następnie wybierz istniejącą grupę zasobów lub utwórz nową.

    2. W polu Szczegóły przestrzeni nazw wprowadź unikatową nazwę nowej przestrzeni nazw.

    3. W polu Szczegóły centrum powiadomień wpisz nazwę centrum powiadomień. Jest to wymagane, ponieważ przestrzeń nazw zawiera co najmniej jedno centrum powiadomień.

    4. Z listy rozwijanej Lokalizacja wybierz wartość określającą lokalizację, w której chcesz utworzyć centrum powiadomień.

    5. Przejrzyj opcję Strefy dostępności. Jeśli wybrano region ze strefami dostępności, pole wyboru jest zaznaczone domyślnie.

      Uwaga

      Strefy dostępności to funkcja płatna, więc dodatkowa opłata jest dodawana do warstwy.

    6. Wybierz opcję Odzyskiwania po awarii: brak, sparowany region odzyskiwania lub elastyczny region odzyskiwania. Jeśli wybierzesz region odzyskiwania sparowanego, zostanie wyświetlony region trybu failover. Jeśli wybierzesz pozycję Elastyczny region odzyskiwania, użyj listy rozwijanej, aby wybrać z listy regionów odzyskiwania.

    7. Zaznacz przycisk Utwórz. Zostanie utworzone centrum powiadomień.

  4. W witrynie Azure Portal przejdź do nowo utworzonego centrum powiadomień, a następnie w bloku Zarządzanie zasadami > dostępu.
  5. W bloku Zasady dostępu zanotuj parametry połączenia zasadDefaultFullSharedAccessSignature. Będzie to wymagane później podczas tworzenia usługi zaplecza, która komunikuje się z centrum powiadomień.

Aby uzyskać więcej informacji na temat tworzenia centrum powiadomień, zobacz Tworzenie centrum powiadomień platformy Azure w witrynie Azure Portal.

Konfigurowanie usługi Firebase Cloud Messaging w centrum powiadomień

Aby skonfigurować centrum powiadomień do komunikowania się z usługą Firebase Cloud Messaging:

  1. W witrynie Azure Portal przejdź do centrum powiadomień i wybierz blok Ustawienia > Google (FCM v1).

  2. W bloku Google (FCM v1) wprowadź wartości pól Klucz prywatny, Adres e-mail klienta i Identyfikator projektu. Te wartości można znaleźć w pliku JSON klucza prywatnego pobranym z usługi Firebase Cloud Messaging:

    Pole platformy Azure Klucz JSON Przykład wartości JSON
    Klucz prywatny private_key Ta wartość powinna zaczynać się od -----BEGIN PRIVATE KEY-----\n i kończyć ciągiem -----END PRIVATE KEY-----\n.
    Adres e-mail klienta client_email firebase-adminsdk-55sfg@pushdemo-d6ab2.iam.gserviceaccount.com
    Identyfikator projektu project_id pushdemo-d6ab2
  3. W bloku Google (FCM v1) wybierz przycisk Zapisz.

Konfigurowanie usługi Apple Push Notification Service w centrum powiadomień

W witrynie Azure Portal przejdź do centrum powiadomień i wybierz blok Ustawienia > Apple (APNS). Następnie wykonaj odpowiednie kroki na podstawie podejścia wybranego wcześniej podczas tworzenia certyfikatu dla centrum powiadomień.

Ważne

Podczas ustawiania trybu aplikacji wybierz pozycję Produkcja 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

  1. W bloku Apple (APNS) wybierz tryb uwierzytelniania certyfikatu.
  2. W bloku Apple (APNS) wybierz ikonę pliku obok pola Przekaż certyfikat. Następnie wybierz wyeksportowany wcześniej plik p12 i przekaż go.
  3. W bloku Apple (APNS) wprowadź hasło certyfikatu w polu Hasło, jeśli jest to wymagane.
  4. W bloku Apple (APNS) wybierz tryb aplikacji piaskownicy.
  5. W bloku Apple (APNS) wybierz przycisk Zapisz.

Opcja 2 — używanie uwierzytelniania opartego na tokenach

  1. W bloku Apple (APNS) wybierz tryb uwierzytelniania tokenu.
  2. W bloku Apple (APNS) wprowadź wartości uzyskane wcześniej dla pól Identyfikator klucza, Identyfikator pakietu, Identyfikator zespołu i Token.
  3. W bloku Apple (APNS) wybierz tryb aplikacji piaskownicy.
  4. W bloku Apple (APNS) wybierz przycisk Zapisz.

Tworzenie aplikacji zaplecza internetowego interfejsu API platformy ASP.NET Core

W tej sekcji utworzysz zaplecze internetowego interfejsu API platformy ASP.NET Core do obsługi instalacji urządzenia i wysyłania powiadomień do aplikacji .NET MAUI.

Tworzenie projektu internetowego interfejsu API

Aby utworzyć projekt internetowego interfejsu API:

  1. W programie Visual Studio utwórz projekt internetowego interfejsu API platformy ASP.NET Core:

    Zrzut ekranu przedstawiający tworzenie nowego projektu internetowego interfejsu API platformy ASP.NET Core w programie Visual Studio.

  2. W oknie dialogowym Konfigurowanie nowego projektu nadaj projektowi nazwę PushNotificationsAPI.

  3. W oknie dialogowym Dodatkowe informacje upewnij się, że pole wyboru Konfiguruj dla protokołu HTTPS i Użyj kontrolerów jest włączone:

    Zrzut ekranu przedstawiający konfigurowanie projektu internetowego interfejsu API platformy ASP.NET Core w programie Visual Studio.

  4. Po utworzeniu projektu naciśnij F5 , aby uruchomić projekt.

    Aplikacja jest obecnie skonfigurowana do używania WeatherForecastController elementu jako launchUrl, który jest ustawiony w pliku Properties\launchSettings.json . Aplikacja zostanie uruchomiona w przeglądarce internetowej i wyświetli niektóre dane JSON.

    Ważne

    Po uruchomieniu projektu ASP.NET Core korzystającego z protokołu HTTPS program Visual Studio wykryje, czy certyfikat dewelopera ASP.NET Core HTTPS jest zainstalowany w magazynie certyfikatów użytkownika lokalnego i będzie oferować jego zainstalowanie i zaufanie, jeśli go brakuje.

  5. Zamknij przeglądarkę internetową.

  6. W Eksplorator rozwiązań rozwiń folder Controllers i usuń WeatherForecastController.cs.

  7. W Eksplorator rozwiązań w katalogu głównym projektu usuń WeatherForecast.cs.

  8. Otwórz okno polecenia i przejdź do katalogu zawierającego plik projektu. Użyj następujących poleceń:

    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ą usługi Azure Notification Hub i wartościami parametry połączenia. Można je znaleźć w następujących lokalizacjach w usłudze Azure Notification Hub:

    Wartość konfiguracji Lokalizacja
    NotificationHub:Name Zobacz Nazwę w podsumowaniu Podstawy w górnej części strony Przegląd .
    NotificationHub:ConnectinString Zobacz DefaultFullSharedAccessSignature* na stronie Zasady dostępu.

    Spowoduje to skonfigurowanie lokalnych wartości konfiguracji przy użyciu narzędzia Secret Manager. Spowoduje to oddzielenie wpisów tajnych usługi Azure Notification Hub z rozwiązania Visual Studio, aby upewnić się, że nie są one w kontroli źródła.

    Napiwek

    W przypadku scenariuszy produkcyjnych rozważ usługę, taką jak Azure KeyVault, aby bezpiecznie przechowywać parametry połączenia.

Uwierzytelnianie klientów przy użyciu klucza interfejsu API

Aby uwierzytelnić klientów przy użyciu klucza interfejsu API:

  1. Otwórz okno polecenia i przejdź do katalogu zawierającego plik projektu. Użyj następujących poleceń:

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

    Zastąp wartość symbolu zastępczego kluczem interfejsu API, który może być dowolną wartością.

  2. W programie Visual Studio dodaj nowy folder o nazwie Authentication do projektu, a następnie dodaj nową klasę o nazwie ApiKeyAuthOptions do folderu Authentication i zastąp jego kod następującym kodem:

    using Microsoft.AspNetCore.Authentication;
    
    namespace PushNotificationsAPI.Authentication;
    
    public class ApiKeyAuthOptions : AuthenticationSchemeOptions
    {
        public const string DefaultScheme = "ApiKey";
        public string Scheme => DefaultScheme;
        public string ApiKey { get; set; }
    }
    
  3. W programie Visual Studio dodaj nową klasę o nazwie ApiKeyAuthHandler do folderu Authentication i zastąp jego kod następującym kodem:

    using Microsoft.AspNetCore.Authentication;
    using Microsoft.Extensions.Options;
    using System.Security.Claims;
    using System.Text.Encodings.Web;
    
    namespace PushNotificationsAPI.Authentication;
    
    public class ApiKeyAuthHandler : AuthenticationHandler<ApiKeyAuthOptions>
    {
        const string ApiKeyIdentifier = "apikey";
    
        public ApiKeyAuthHandler(
            IOptionsMonitor<ApiKeyAuthOptions> options,
            ILoggerFactory logger,
            UrlEncoder encoder)
            : base(options, logger, encoder)
        {
        }
    
        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));
        }
    }
    

    Procedura obsługi uwierzytelniania to typ implementujący zachowanie schematu, który w tym przypadku jest niestandardowym schematem kluczy interfejsu API.

  4. W programie Visual Studio dodaj nową klasę o nazwie AuthenticationBuilderExtensions do folderu Authentication i zastąp jego kod następującym kodem:

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

    Ta metoda rozszerzenia zostanie użyta do uproszczenia kodu konfiguracji oprogramowania pośredniczącego w Program.cs.

  5. W programie Visual Studio otwórz Program.cs i zaktualizuj kod, aby skonfigurować uwierzytelnianie klucza interfejsu API poniżej wywołania builder.Services.AddControllers metody :

    using PushNotificationsAPI.Authentication;
    
    builder.Services.AddControllers();
    
    builder.Services.AddAuthentication(options =>
    {
        options.DefaultAuthenticateScheme = ApiKeyAuthOptions.DefaultScheme;
        options.DefaultChallengeScheme = ApiKeyAuthOptions.DefaultScheme;
    }).AddApiKeyAuth(builder.Configuration.GetSection("Authentication").Bind);
    
  6. W Program.cs zaktualizuj kod poniżej komentarza // Configure the HTTP request pipeline , aby wywołać UseRoutingmetody , UseAuthenticationi MapControllers rozszerzenia:

    // Configure the HTTP request pipeline.
    
    app.UseHttpsRedirection();
    app.UseRouting();
    app.UseAuthentication();
    app.UseAuthorization();
    app.MapControllers();
    
    app.Run();
    

    Metoda UseAuthentication rozszerzenia rejestruje oprogramowanie pośredniczące, które używa wcześniej zarejestrowanego schematu uwierzytelniania. UseAuthentication należy wywołać przed każdym oprogramowaniem pośredniczącym, które zależy od uwierzytelnienia użytkowników.

    Uwaga

    Chociaż klucz interfejsu API nie jest tak bezpieczny jak token, wystarczy na potrzeby tego samouczka i będzie można go łatwo skonfigurować za pośrednictwem oprogramowania pośredniczącego ASP.NET.

Dodawanie i konfigurowanie usług

Aby dodać i skonfigurować usługi w aplikacji zaplecza internetowego interfejsu API:

  1. W programie Visual Studio dodaj pakiet NuGet Microsoft.Azure.NotificationHubs do projektu. Ten pakiet NuGet służy do uzyskiwania dostępu do centrum powiadomień, hermetyzowanego w usłudze.

  2. W programie Visual Studio dodaj nowy folder o nazwie Models do projektu, a następnie dodaj nową klasę o nazwie PushTemplates do folderu Models i zastąp jego kod następującym kodem:

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

    Klasa PushTemplates zawiera tokenizowane ładunki powiadomień dla ogólnych i dyskretnych powiadomień wypychanych. Te ładunki są definiowane poza instalacją, 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 artykułu. W scenariuszach produktów rozważ użycie szablonów niestandardowych.

  3. W programie Visual Studio dodaj nową klasę o nazwie DeviceInstallation do folderu Models i zastąp kod następującym kodem:

    using System.ComponentModel.DataAnnotations;
    
    namespace PushNotificationsAPI.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>();
    }
    
  4. W programie Visual Studio dodaj nową klasę o nazwie NotificationRequest do folderu Models i zastąp kod następującym kodem:

    namespace PushNotificationsAPI.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; }
    }
    
  5. W programie Visual Studio dodaj nową klasę o nazwie NotificationHubOptions do folderu Models i zastąp kod następującym kodem:

    using System.ComponentModel.DataAnnotations;
    
    namespace PushNotificationsAPI.Models;
    
    public class NotificationHubOptions
    {
        [Required]
        public string Name { get; set; }
    
        [Required]
        public string ConnectionString { get; set; }
    }
    
  6. W programie Visual Studio dodaj nowy folder o nazwie Services do projektu, a następnie dodaj nowy interfejs o nazwie INotificationService do folderu Services i zastąp jego kod następującym kodem:

    using PushNotificationsAPI.Models;
    
    namespace PushNotificationsAPI.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);
    }
    
  7. W programie Visual Studio dodaj nową klasę o nazwie NotificationHubService do folderu Services i zastąp jego kod następującym kodem:

    using Microsoft.Extensions.Options;
    using Microsoft.Azure.NotificationHubs;
    using PushNotificationsAPI.Models;
    
    namespace PushNotificationsAPI.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.FcmV1).ToLower(), NotificationPlatform.FcmV1 }
            };
        }
    
        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.SendFcmV1NativeNotificationAsync(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.SendFcmV1NativeNotificationAsync(androidPayload, tags, token),
                _hub.SendAppleNativeNotificationAsync(iOSPayload, tags, token)
            };
    
            return Task.WhenAll(sendTasks);
        }
    }
    

    Wyrażenie tagu dostarczone do SendTemplateNotificationsAsync metody jest ograniczone do 20 tagów, jeśli zawierają tylko jednostki ORS. W przeciwnym razie są one ograniczone do 6 tagów. Aby uzyskać więcej informacji, zobacz Routing i wyrażenia tagów.

  8. W programie Visual Studio otwórz Program.cs i zaktualizuj kod, aby dodać NotificationHubService element jako pojedynczą implementację INotificationService poniżej wywołania builder.Services.AddAuthentication metody :

    using PushNotificationsAPI.Authentication;
    using PushNotificationsAPI.Services;
    using PushNotificationsAPI.Models;
    
    var builder = WebApplication.CreateBuilder(args);
    
    // Add services to the container.
    
    builder.Services.AddControllers();
    
    builder.Services.AddAuthentication(options =>
    {
        options.DefaultAuthenticateScheme = ApiKeyAuthOptions.DefaultScheme;
        options.DefaultChallengeScheme = ApiKeyAuthOptions.DefaultScheme;
    }).AddApiKeyAuth(builder.Configuration.GetSection("Authentication").Bind);
    
    builder.Services.AddSingleton<INotificationService, NotificationHubService>();
    builder.Services.AddOptions<NotificationHubOptions>()
        .Configure(builder.Configuration.GetSection("NotificationHub").Bind)
        .ValidateDataAnnotations();
    
    var app = builder.Build();
    

Tworzenie interfejsu API REST powiadomień

Aby utworzyć interfejs API REST powiadomień:

  1. W programie Visual Studio dodaj nowy kontroler o nazwie NotificationsController do folderu Controllers .

    Napiwek

    Wybierz szablon Kontroler interfejsu API z akcjami odczytu/zapisu.

  2. W pliku NotificationsController.cs dodaj następujące using instrukcje w górnej części pliku:

    using System.ComponentModel.DataAnnotations;
    using System.Net;
    using Microsoft.AspNetCore.Authorization;
    using Microsoft.AspNetCore.Mvc;
    using PushNotificationsAPI.Models;
    using PushNotificationsAPI.Services;
    
  3. W pliku NotificationsController.cs dodaj Authorize atrybut do NotificationsController klasy:

    [Authorize]
    [ApiController]
    [Route("api/[controller]")]
    public class NotificationsController : ControllerBase
    
  4. W pliku NotificationsController.cs zaktualizuj NotificationsContoller konstruktor, aby akceptował zarejestrowane wystąpienie INotificationService jako argument i przypisz go do elementu członkowskiego tylko do odczytu:

    readonly INotificationService _notificationService;
    
    public NotificationsController(INotificationService notificationService)
    {
        _notificationService = notificationService;
    }
    
  5. W pliku NotificationsContoller.cs zastąp wszystkie metody 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)
    {
        // Probably want to ensure deletion even if the connection is broken
        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();
    }
    
  6. W pliku Właściwości/launchSettings.json zmień launchUrl właściwość dla każdego profilu z weatherforecast na api/notifications.

Tworzenie aplikacji interfejsu API

Teraz utworzysz aplikację interfejsu API w usłudze aplikacja systemu Azure, aby hostować usługę zaplecza. Można to zrobić bezpośrednio z poziomu programu Visual Studio lub Visual Studio Code przy użyciu interfejsu wiersza polecenia platformy Azure, programu Azure PowerShell, interfejsu wiersza polecenia dla deweloperów platformy Azure i witryny Azure Portal. Aby uzyskać więcej informacji, zobacz Publikowanie aplikacji internetowej.

Aby utworzyć aplikację interfejsu API w witrynie Azure Portal:

  1. W przeglądarce internetowej zaloguj się do witryny Azure Portal.

  2. W witrynie Azure Portal kliknij przycisk Utwórz zasób , a następnie wyszukaj i wybierz pozycję Aplikacja interfejsu API przed wybraniem przycisku Utwórz .

  3. Na stronie Tworzenie aplikacji interfejsu API zaktualizuj następujące pola przed wybraniem przycisku Utwórz:

    Pole Akcja
    Subskrypcja Wybierz tę samą subskrypcję docelową, w której utworzono centrum powiadomień.
    Grupa zasobów Wybierz tę samą grupę zasobów, w której utworzono centrum powiadomień.
    Nazwisko Podaj globalnie unikatową nazwę.
    Stos środowiska uruchomieniowego Upewnij się, że wybrano najnowszą wersję platformy .NET.
  4. Po aprowizacji aplikacji interfejsu API przejdź do zasobu.

  5. Na stronie Przegląd zanotuj domyślną wartość domeny. Ten adres URL to punkt końcowy zaplecza, który będzie używany z poziomu aplikacji .NET MAUI. Adres URL będzie używać określonej nazwy aplikacji interfejsu API z formatem https://<app_name>.azurewebsites.net.

  6. W witrynie Azure Portal przejdź do bloku Ustawienia > Zmienne środowiskowe , a następnie upewnij się, że wybrano kartę Ustawienia aplikacji. Następnie użyj przycisku Dodaj , aby dodać następujące ustawienia:

    Nazwa/nazwisko Wartość
    Authentication:ApiKey <api_key_value>
    NotificationHub:Name <hub_name_value>
    NotificationHub:ConnectionString <hub_connection_string_value>

    Ważne

    Dla Authentication:ApiKey uproszczenia dodano ustawienie aplikacji. W przypadku scenariuszy produkcyjnych rozważ usługę, taką jak Azure KeyVault, aby bezpiecznie przechowywać parametry połączenia.

    Po wprowadzeniu wszystkich tych ustawień wybierz przycisk Zastosuj , a następnie przycisk Potwierdź .

Publikowanie usługi zaplecza

Aby opublikować usługę zaplecza w usłudze aplikacja systemu Azure:

  1. W programie Visual Studio kliknij prawym przyciskiem myszy projekt i wybierz polecenie Publikuj.
  2. W kreatorze Publikowanie wybierz pozycję Azure, a następnie przycisk Dalej.
  3. W kreatorze Publikowanie wybierz pozycję usługa aplikacja systemu Azure (Windows), a następnie przycisk Dalej.
  4. W kreatorze Publikowanie postępuj zgodnie z przepływem uwierzytelniania, aby połączyć program Visual Studio z subskrypcją platformy Azure i opublikować aplikację.

Program Visual Studio kompiluje, pakuje i publikuje aplikację na platformie Azure, a następnie uruchamia aplikację w domyślnej przeglądarce. Aby uzyskać więcej informacji, zobacz Publikowanie ASP.NET aplikacji internetowej.

Napiwek

Profil publikowania aplikacji można pobrać z bloku Przegląd aplikacji interfejsu API w witrynie Azure Portal, a następnie opublikować aplikację przy użyciu profilu w programie Visual Studio.

Weryfikowanie opublikowanego interfejsu API

Aby sprawdzić, czy aplikacja interfejsu API została poprawnie opublikowana, należy użyć wybranego narzędzia REST, aby wysłać POST żądanie do następującego adresu:

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

Uwaga

Adres podstawowy to https://<app_name>.azurewebsites.net.

Upewnij się, że nagłówki żądań są skonfigurowane tak, aby zawierały klucz apikey i jego wartość, ustaw treść na nieprzetworzoną i użyj następującej zawartości zastępczej JSON:

{}

Powinna zostać odebrana 400 Bad Request odpowiedź z usługi.

Uwaga

Nie można jeszcze przetestować interfejsu API przy użyciu prawidłowych danych żądania, ponieważ będzie to wymagało informacji specyficznych dla platformy z aplikacji .NET MAUI.

Aby uzyskać więcej informacji na temat wywoływania interfejsów API REST, zobacz Use .http files in Visual Studio and Test web APIs with the Http Repl (Używanie plików HTTP w programie Visual Studio i testowanie internetowych interfejsów API za pomocą protokołu Http Repl). W programie Visual Studio Code klient REST może służyć do testowania interfejsów API REST.

Tworzenie aplikacji MAUI platformy .NET

W tej sekcji utworzysz aplikację interfejsu użytkownika aplikacji wieloplatformowej platformy .NET (.NET MAUI), która umożliwia zarejestrowanie się w celu otrzymywania powiadomień wypychanych z centrum powiadomień za pośrednictwem usługi zaplecza i anulowania rejestracji.

Aby utworzyć aplikację .NET MAUI:

  1. W programie Visual Studio utwórz nową aplikację .NET MAUI o nazwie PushNotificationsDemo przy użyciu szablonu projektu .NET MAUI App .

  2. W programie Visual Studio dodaj nowy folder o nazwie Models do projektu .NET MAUI, a następnie dodaj nową klasę o nazwie DeviceInstallation do folderu Models i zastąp jego kod następującym kodem:

    using System.Text.Json.Serialization;
    
    namespace PushNotificationsDemo.Models;
    
    public class DeviceInstallation
    {
        [JsonPropertyName("installationId")]
        public string InstallationId { get; set; }
    
        [JsonPropertyName("platform")]
        public string Platform { get; set; }
    
        [JsonPropertyName("pushChannel")]
        public string PushChannel { get; set; }
    
        [JsonPropertyName("tags")]
        public List<string> Tags { get; set; } = new List<string>();
    }
    
  3. W programie Visual Studio dodaj wyliczenie o nazwie PushDemoAction do folderu Models i zastąp jego kod następującym kodem:

    namespace PushNotificationsDemo.Models;
    
    public enum PushDemoAction
    {
        ActionA,
        ActionB
    }
    
  4. W programie Visual Studio dodaj nowy folder o nazwie Services do projektu .NET MAUI, a następnie dodaj nowy interfejs o nazwie IDeviceInstallationService do folderu Services i zastąp jego kod następującym kodem:

    using PushNotificationsDemo.Models;
    
    namespace PushNotificationsDemo.Services;
    
    public interface IDeviceInstallationService
    {
        string Token { get; set; }
        bool NotificationsSupported { get; }
        string GetDeviceId();
        DeviceInstallation GetDeviceInstallation(params string[] tags);
    }
    

    Ten interfejs zostanie zaimplementowany na każdej platformie później, aby udostępnić DeviceInstallation informacje wymagane przez usługę zaplecza.

  5. W programie Visual Studio dodaj interfejs o nazwie INotificationRegistrationService do folderu Services i zastąp jego kod następującym kodem:

    namespace PushNotificationsDemo.Services;
    
    public interface INotificationRegistrationService
    {
        Task DeregisterDeviceAsync();
        Task RegisterDeviceAsync(params string[] tags);
        Task RefreshRegistrationAsync();
    }
    

    Ten interfejs będzie obsługiwać interakcję między klientem a usługą zaplecza.

  6. W programie Visual Studio dodaj interfejs o nazwie INotificationActionService do folderu Services i zastąp jego kod następującym kodem:

    namespace PushNotificationsDemo.Services;
    
    public interface INotificationActionService
    {
        void TriggerAction(string action);
    }
    

    Ten interfejs będzie używany jako prosty mechanizm umożliwiający scentralizowanie obsługi akcji powiadomień.

  7. W programie Visual Studio dodaj interfejs o nazwie IPushDemoNotificationActionService do folderu Services i zastąp jego kod następującym kodem:

    using PushNotificationsDemo.Models;
    
    namespace PushNotificationsDemo.Services;
    
    public interface IPushDemoNotificationActionService : INotificationActionService
    {
        event EventHandler<PushDemoAction> ActionTriggered;
    }
    

    Typ IPushDemoNotificationActionService jest specyficzny dla tej aplikacji i używa PushDemoAction wyliczenia do identyfikowania akcji wyzwalanej przy użyciu podejścia silnie typizowanego.

  8. W programie Visual Studio dodaj klasę o nazwie NotificationRegistrationService do folderu Services i zastąp jego kod następującym kodem:

    using System.Text;
    using System.Text.Json;
    using PushNotificationsDemo.Models;
    
    namespace PushNotificationsDemo.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;
    
        IDeviceInstallationService DeviceInstallationService =>
            _deviceInstallationService ?? (_deviceInstallationService = Application.Current.Windows[0].Page.Handler.MauiContext.Services.GetService<IDeviceInstallationService>());
    
        public NotificationRegistrationService(string baseApiUri, string apiKey)
        {
            _client = new HttpClient();
            _client.DefaultRequestHeaders.Add("Accept", "application/json");
            _client.DefaultRequestHeaders.Add("apikey", apiKey);
    
            _baseApiUrl = baseApiUri;
        }
    
        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, JsonSerializer.Serialize(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 = JsonSerializer.Deserialize<string[]>(serializedTags);
    
            await RegisterDeviceAsync(tags);
        }
    
        async Task SendAsync<T>(HttpMethod requestType, string requestUri, T obj)
        {
            string serializedContent = null;
    
            await Task.Run(() => serializedContent = JsonSerializer.Serialize(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();
        }
    }
    
  9. W programie Visual Studio dodaj klasę o nazwie PushDemoNotificationActionService do folderu Services i zastąp jego kod następującym kodem:

    using PushNotificationsDemo.Models;
    
    namespace PushNotificationsDemo.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);
        }
    }
    
  10. W programie Visual Studio dodaj klasę o nazwie Config do katalogu głównego projektu i zastąp jego kod następującym kodem:

    namespace PushNotificationsDemo;
    
    public static partial class Config
    {
        public static string ApiKey = "API_KEY";
        public static string BackendServiceEndpoint = "BACKEND_SERVICE_ENDPOINT";
    }
    

    Klasa Config jest używana jako prosty sposób, aby zachować wpisy tajne 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.

    Ważne

    Podczas określania adresu podstawowego w aplikacji .NET MAUI upewnij się, że kończy się na ./

  11. W programie Visual Studio dodaj klasę o nazwie Config.local_secrets do katalogu głównego projektu. Następnie zastąp kod w pliku Config.local_secrets.cs następującym kodem:

    namespace PushNotificationsDemo;
    
    public static partial class Config
    {
        static Config()
        {
            ApiKey = "<your_api_key>";
            BackendServiceEndpoint = "<your_api_app_url>";
        }
    }
    

    Zamień wartości symboli zastępczych na wartości wybrane podczas tworzenia usługi zaplecza. Adres BackendServiceEndpoint URL powinien używać formatu https://<api_app_name>.azurewebsites.net/.

    Napiwek

    Pamiętaj, aby dodać *.local_secrets.* plik do .gitignore pliku, aby uniknąć zatwierdzania tego pliku do kontroli źródła.

Tworzenie interfejsu użytkownika

Aby utworzyć interfejs użytkownika aplikacji:

  1. W programie Visual Studio otwórz plik MainPage.xaml i zastąp element VerticalStackLayout i jego elementami podrzędnymi następującym kodem XAML:

    <VerticalStackLayout Margin="20"
                         Spacing="6">
        <Button x:Name="registerButton"
                Text="Register"
                Clicked="OnRegisterButtonClicked" />
        <Button x:Name="deregisterButton"
                Text="Deregister"
                Clicked="OnDeregisterButtonClicked" />
    </VerticalStackLayout>
    
  2. W programie Visual Studio otwórz MainPage.xaml.cs i dodaj instrukcję using dla PushNotificationsDemo.Services przestrzeni nazw:

    using PushNotificationsDemo.Services;
    
  3. W MainPage.xaml.cs dodaj readonly pole zapasowe, aby zapisać odwołanie do implementacji INotificationRegistrationService :

    readonly INotificationRegistrationService _notificationRegistrationService;
    
  4. W konstruktorze MainPage rozwiąż implementację INotificationRegistrationService i przypisz ją do pola zapasowego _notificationRegistrationService :

    public MainPage(INotificationRegistrationService service)
    {
        InitializeComponent();
    
        _notificationRegistrationService = service;
    }
    
  5. W klasie zaimplementuj MainPage OnRegisterButtonClicked programy obsługi zdarzeń i OnDeregisterButtonClicked , wywołując odpowiednie metody rejestru i wyrejestrowania w INotificationRegistrationService obiekcie:

    void OnRegisterButtonClicked(object sender, EventArgs e)
    {
        _notificationRegistrationService.RegisterDeviceAsync()
            .ContinueWith((task) =>
            {
                ShowAlert(task.IsFaulted ? task.Exception.Message : $"Device registered");
            });
    }
    
    void OnDeregisterButtonClicked(object sender, EventArgs e)
    {
        _notificationRegistrationService.DeregisterDeviceAsync()
            .ContinueWith((task) =>
            {
                ShowAlert(task.IsFaulted ? task.Exception.Message : $"Device deregistered");
            });
    }
    
    void ShowAlert(string message)
    {
        MainThread.BeginInvokeOnMainThread(() =>
        {
            DisplayAlert("Push notifications demo", message, "OK")
                .ContinueWith((task) =>
                {
                    if (task.IsFaulted)
                        throw task.Exception;
                });
        });
    }
    

    Ważne

    W aplikacji rejestracja i anulowanie rejestracji jest wykonywana w odpowiedzi na dane wejściowe użytkownika, aby umożliwić łatwiejsze eksplorowanie i testowanie tej funkcji. W aplikacji produkcyjnej zazwyczaj wykonujesz akcje rejestracji i anulowania rejestracji w odpowiednim punkcie cyklu życia aplikacji bez konieczności jawnego wprowadzania danych przez użytkownika.

  6. W programie Visual Studio otwórz App.xaml.cs i dodaj następujące using instrukcje:

    using PushNotificationsDemo.Models;
    using PushNotificationsDemo.Services;
    
  7. W App.xaml.cs dodaj readonly pole zapasowe, aby zapisać odwołanie do implementacji IPushDemoNotificationActionService :

    readonly IPushDemoNotificationActionService _actionService;
    
  1. W konstruktorze App rozwiąż implementację IPushDemoNotificationActionService i przypisz ją do pola zapasowego _actionService , a następnie zasubskrybuj IPushDemoNotificationActionService.ActionTriggered zdarzenie:

    public App(IPushDemoNotificationActionService service)
    {
        InitializeComponent();
    
        _actionService = service;
        _actionService.ActionTriggered += NotificationActionTriggered;
    
        MainPage = new AppShell();
    }
    
  1. W konstruktorze App rozwiąż implementację IPushDemoNotificationActionService i przypisz ją do pola zapasowego _actionService , a następnie zasubskrybuj IPushDemoNotificationActionService.ActionTriggered zdarzenie:

    public App(IPushDemoNotificationActionService service)
    {
        InitializeComponent();
    
        _actionService = service;
        _actionService.ActionTriggered += NotificationActionTriggered;
    }
    
  1. W klasie zaimplementuj App program obsługi zdarzeń dla IPushDemoNotificationActionService.ActionTriggered zdarzenia:

    void NotificationActionTriggered(object sender, PushDemoAction e)
    {
        ShowActionAlert(e);
    }
    
    void ShowActionAlert(PushDemoAction action)
    {
        MainThread.BeginInvokeOnMainThread(() =>
        {
            Windows[0].Page?.DisplayAlert("Push notifications demo", $"{action} action received.", "OK")
                .ContinueWith((task) =>
                {
                    if (task.IsFaulted)
                        throw task.Exception;
                });
        });
    }
    

    Procedura obsługi zdarzeń dla ActionTriggered zdarzenia demonstruje potwierdzenie i propagację 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.

Konfigurowanie aplikacji systemu Android

Aby skonfigurować aplikację .NET MAUI w systemie Android w celu odbierania i przetwarzania powiadomień wypychanych:

  1. W programie Visual Studio dodaj pakiet NuGet Xamarin.Firebase.Messaging do projektu aplikacji .NET MAUI.

  2. W programie Visual Studio dodaj plik google-services.json do folderu Platformy/Android projektu aplikacji .NET MAUI. Po dodaniu pliku do projektu powinien zostać dodany z akcją kompilacji :GoogleServicesJson

    <ItemGroup Condition="'$(TargetFramework)' == 'net8.0-android'">
      <GoogleServicesJson Include="Platforms\Android\google-services.json" />
    </ItemGroup>
    

    Napiwek

    Pamiętaj, aby dodać google-services.json plik do .gitignore pliku, aby uniknąć zatwierdzania tego pliku do kontroli źródła.

  3. W programie Visual Studio edytuj plik projektu (*.csproj) i ustaw SupportedOSPlatformVersion dla systemu Android wartość 26.0:

    <SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'android'">26.0</SupportedOSPlatformVersion>
    

    Google dokonało zmian w kanałach powiadomień systemu Android w interfejsie API 26. Aby uzyskać więcej informacji, zobacz Kanały powiadomień w developer.android.com.

  4. W folderze Platformy/Android projektu dodaj nową klasę o nazwie DeviceInstallationService i zastąp jej kod następującym kodem:

    using Android.Gms.Common;
    using PushNotificationsDemo.Models;
    using PushNotificationsDemo.Services;
    using static Android.Provider.Settings;
    
    namespace PushNotificationsDemo.Platforms.Android;
    
    public class DeviceInstallationService : IDeviceInstallationService
    {
        public string Token { get; set; }
    
        public bool NotificationsSupported
            => GoogleApiAvailability.Instance.IsGooglePlayServicesAvailable(Platform.AppContext) == ConnectionResult.Success;
    
        public string GetDeviceId()
            => Secure.GetString(Platform.AppContext.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 FCMv1.");
    
            var installation = new DeviceInstallation
            {
                InstallationId = GetDeviceId(),
                Platform = "fcmv1",
                PushChannel = Token
            };
    
            installation.Tags.AddRange(tags);
    
            return installation;
        }
    
        string GetPlayServicesError()
        {
            int resultCode = GoogleApiAvailability.Instance.IsGooglePlayServicesAvailable(Platform.AppContext);
    
            if (resultCode != ConnectionResult.Success)
                return GoogleApiAvailability.Instance.IsUserResolvableError(resultCode) ?
                           GoogleApiAvailability.Instance.GetErrorString(resultCode) :
                           "This device isn't supported.";
    
            return "An error occurred preventing the use of push notifications.";
        }
    }
    

    Ta klasa udostępnia unikatowy identyfikator, używając Secure.AndroidId wartości i ładunku rejestracji centrum powiadomień.

  5. W folderze Platformy/Android projektu dodaj nową klasę o nazwie PushNotificationFirebaseMessagingService i zastąp jej kod następującym kodem:

    using Android.App;
    using Firebase.Messaging;
    using PushNotificationsDemo.Services;
    
    namespace PushNotificationsDemo.Platforms.Android;
    
    [Service(Exported = false)]
    [IntentFilter(new[] { "com.google.firebase.MESSAGING_EVENT" })]
    public class PushNotificationFirebaseMessagingService : FirebaseMessagingService
    {
        IPushDemoNotificationActionService _notificationActionService;
        INotificationRegistrationService _notificationRegistrationService;
        IDeviceInstallationService _deviceInstallationService;
        int _messageId;
    
        IPushDemoNotificationActionService NotificationActionService =>
            _notificationActionService ?? (_notificationActionService = IPlatformApplication.Current.Services.GetService<IPushDemoNotificationActionService>());
    
        INotificationRegistrationService NotificationRegistrationService =>
            _notificationRegistrationService ?? (_notificationRegistrationService = IPlatformApplication.Current.Services.GetService<INotificationRegistrationService>());
    
        IDeviceInstallationService DeviceInstallationService =>
            _deviceInstallationService ?? (_deviceInstallationService = IPlatformApplication.Current.Services.GetService<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)
        {
            base.OnMessageReceived(message);
    
            if (message.Data.TryGetValue("action", out var messageAction))
                NotificationActionService.TriggerAction(messageAction);
        }
    }
    

    Ta klasa ma IntentFilter atrybut zawierający com.google.firebase.MESSAGING_EVENT filtr. Ten filtr umożliwia systemowi Android przekazywanie przychodzących komunikatów do tej klasy na potrzeby przetwarzania.

    Aby uzyskać informacje o formacie komunikatów firebase Cloud Messaging, zobacz About FCM messages on developer.android.com (Informacje o komunikatach FCM w developer.android.com).

  6. W programie Visual Studio otwórz plik MainActivity.cs w folderze Platformy/Android i dodaj następujące using instrukcje:

    using Android.App;
    using Android.Content;
    using Android.Content.PM;
    using Android.OS;
    using PushNotificationsDemo.Services;
    using Firebase.Messaging;
    
  7. MainActivity W klasie ustaw LaunchMode wartość na SingleTop , aby element nie został utworzony ponownie po otwarciuMainActivity:

    [Activity(
        Theme = "@style/Maui.SplashTheme",
        MainLauncher = true,
        LaunchMode = LaunchMode.SingleTop,
        ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation | ConfigChanges.UiMode | ConfigChanges.ScreenLayout | ConfigChanges.SmallestScreenSize | ConfigChanges.Density)]
    
  8. MainActivity W klasie dodaj pola zapasowe do przechowywania odwołań do IPushDemoNotificationActionService implementacji i IDeviceInstallationService :

    IPushDemoNotificationActionService _notificationActionService;
    IDeviceInstallationService _deviceInstallationService;
    
  9. MainActivity W klasie dodaj NotificationActionService i DeviceInstallationService właściwości prywatne, które pobierają konkretne implementacje z kontenera wstrzykiwania zależności aplikacji:

    IPushDemoNotificationActionService NotificationActionService =>
        _notificationActionService ?? (_notificationActionService = IPlatformApplication.Current.Services.GetService<IPushDemoNotificationActionService>());
    
    IDeviceInstallationService DeviceInstallationService =>
        _deviceInstallationService ?? (_deviceInstallationService = IPlatformApplication.Current.Services.GetService<IDeviceInstallationService>());
    
  10. W klasie zaimplementuj MainActivity Android.Gms.Tasks.IOnSuccessListener interfejs w celu pobrania i zapisania tokenu Firebase:

    public class MainActivity : MauiAppCompatActivity, Android.Gms.Tasks.IOnSuccessListener
    {
        public void OnSuccess(Java.Lang.Object result)
        {
            DeviceInstallationService.Token = result.ToString();
        }
    }
    
  11. MainActivity W klasie dodaj metodęProcessNotificationActions, która sprawdzi, czy dana Intent wartość ma dodatkową wartość o nazwie action, a następnie warunkowo wyzwalana action przy użyciu IPushDemoNotificationActionService implementacji:

    void ProcessNotificationsAction(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);
        }
    }
    
  12. MainActivity W klasie zastąpij metodę OnNewIntent , aby wywołać metodę ProcessNotificationActions :

    protected override void OnNewIntent(Intent? intent)
    {
        base.OnNewIntent(intent);
        ProcessNotificationsAction(intent);
    }
    

    LaunchMode Ponieważ dla parametru Activity jest ustawiona wartość SingleTop, element Intent zostanie wysłany do istniejącego Activity wystąpienia za pośrednictwem OnNewIntent przesłonięcia, a nie OnCreate metody. W związku z tym należy obsługiwać intencję przychodzącą zarówno w , jak OnNewIntent i OnCreate.

  13. MainActivity W klasie zastąp metodę OnCreate , aby wywołać metodę ProcessNotificationActions , i pobrać token z bazy firebase, dodając MainActivity jako :IOnSuccessListener

    protected override void OnCreate(Bundle? savedInstanceState)
    {
        base.OnCreate(savedInstanceState);
    
        if (DeviceInstallationService.NotificationsSupported)
            FirebaseMessaging.Instance.GetToken().AddOnSuccessListener(this);
    
        ProcessNotificationsAction(Intent);
    }
    

    Uwaga

    Aplikacja musi zostać ponownie zarejestrowana przy każdym uruchomieniu i zatrzymać ją z sesji debugowania, aby nadal otrzymywać powiadomienia wypychane.

  14. W programie Visual Studio dodaj POST_NOTIFICATIONS uprawnienie do pliku AndroidManifest.xml w folderze Platformy/Android :

    <uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
    

    Aby uzyskać więcej informacji na temat tego uprawnienia, zobacz Uprawnienia środowiska uruchomieniowego powiadomień w developer.android.com.

  15. W programie Visual Studio otwórz MainPage.xaml.cs i dodaj następujący kod do MainPage klasy:

    #if ANDROID
            protected override async void OnAppearing()
            {
                base.OnAppearing();
    
                PermissionStatus status = await Permissions.RequestAsync<Permissions.PostNotifications>();
            }
    #endif
    

    Ten kod jest uruchamiany w systemie Android po MainPage wyświetleniu i żąda od użytkownika udzielenia POST_NOTIFICATIONS uprawnienia. Aby uzyskać więcej informacji na temat uprawnień programu .NET MAUI, zobacz Uprawnienia.

Konfigurowanie aplikacji systemu iOS

Symulator systemu iOS obsługuje powiadomienia zdalne w systemie iOS 16 lub nowszym podczas uruchamiania w systemie macOS 13 lub nowszym na komputerach Mac z procesorami krzemowymi firmy Apple lub T2. Każdy symulator generuje tokeny rejestracji, które są unikatowe dla kombinacji tego symulatora i sprzętu mac, na którym działa.

Ważne

Symulator obsługuje środowisko piaskownicy usługi Apple Push Notification Service.

W poniższych instrukcjach założono, że używasz sprzętu obsługującego odbieranie powiadomień zdalnych w symulatorze systemu iOS. Jeśli tak nie jest, musisz uruchomić aplikację systemu iOS na urządzeniu fizycznym, co będzie wymagało utworzenia profilu aprowizacji dla aplikacji, która obejmuje możliwość powiadomień wypychanych. Następnie należy upewnić się, że aplikacja została skompilowana przy użyciu certyfikatu i profilu aprowizacji. Aby uzyskać więcej informacji na temat tego, jak to zrobić, zobacz Konfigurowanie aplikacji systemu iOS do pracy z usługą Azure Notification Hubs, a następnie postępuj zgodnie z poniższymi instrukcjami.

Aby skonfigurować aplikację .NET MAUI w systemie iOS w celu odbierania i przetwarzania powiadomień wypychanych:

  1. W programie Visual Studio edytuj plik projektu (*.csproj) i ustaw SupportedOSPlatformVersion dla systemu iOS wartość 13.0:

    <SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios'">13.0</SupportedOSPlatformVersion>
    

    Firma Apple dokonała zmian w swojej usłudze wypychania w systemie iOS 13. Aby uzyskać więcej informacji, zobacz Aktualizacje usługi Azure Notification Hubs dla systemu iOS 13.

  2. W programie Visual Studio dodaj plik Entitlements.plist do folderu Platforms/iOS projektu i dodaj następujący kod XML do pliku:

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
    <plist version="1.0">
    <dict>
      <key>aps-environment</key>
      <string>development</string>
    </dict>
    </plist>
    

    Spowoduje to ustawienie uprawnień środowiska usługi APS i określa użycie środowiska deweloperskiego apple Push Notification Service. W aplikacjach produkcyjnych ta wartość uprawnień powinna być ustawiona na productionwartość . Aby uzyskać więcej informacji na temat tego uprawnienia, zobacz Uprawnienia środowiska usługi APS w developer.apple.com.

    Aby uzyskać więcej informacji na temat dodawania pliku uprawnień, zobacz uprawnienia systemu iOS.

  3. W programie Visual Studio dodaj nową klasę o nazwie DeviceInstallationService do folderu Platformy/iOS projektu i dodaj następujący kod do pliku:

    using PushNotificationsDemo.Services;
    using PushNotificationsDemo.Models;
    using UIKit;
    
    namespace PushNotificationsDemo.Platforms.iOS;
    
    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";
        }
    }
    

    Ta klasa udostępnia unikatowy identyfikator, używając UIDevice.IdentifierForVendor wartości i ładunku rejestracji centrum powiadomień.

  4. W programie Visual Studio dodaj nową klasę o nazwie NSDataExtensions do folderu Platformy/iOS projektu i dodaj następujący kod do pliku:

    using Foundation;
    using System.Text;
    
    namespace PushNotificationsDemo.Platforms.iOS;
    
    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();
        }
    }
    

    Metoda ToHexString rozszerzenia będzie zużywana przez kod, który analizuje pobrany token urządzenia.

  5. W programie Visual Studio otwórz plik AppDelegate.cs w folderze Platformy/iOS i dodaj następujące using instrukcje:

    using System.Diagnostics;
    using Foundation;
    using PushNotificationsDemo.Platforms.iOS;
    using PushNotificationsDemo.Services;
    using UIKit;
    using UserNotifications;
    
  6. AppDelegate W klasie dodaj pola zapasowe do przechowywania odwołań do IPushDemoNotificationActionServiceimplementacji , INotificationRegistrationServicei IDeviceInstallationService :

    IPushDemoNotificationActionService _notificationActionService;
    INotificationRegistrationService _notificationRegistrationService;
    IDeviceInstallationService _deviceInstallationService;
    
  7. AppDelegate W klasie dodaj NotificationActionServicewłaściwości , NotificationRegistrationServicei DeviceInstallationService prywatne, które pobierają konkretne implementacje z kontenera wstrzykiwania zależności aplikacji:

    IPushDemoNotificationActionService NotificationActionService =>
        _notificationActionService ?? (_notificationActionService = IPlatformApplication.Current.Services.GetService<IPushDemoNotificationActionService>());
    
    INotificationRegistrationService NotificationRegistrationService =>
        _notificationRegistrationService ?? (_notificationRegistrationService = IPlatformApplication.Current.Services.GetService<INotificationRegistrationService>());
    
    IDeviceInstallationService DeviceInstallationService =>
        _deviceInstallationService ?? (_deviceInstallationService = IPlatformApplication.Current.Services.GetService<IDeviceInstallationService>());
    
  8. AppDelegate W klasie dodaj metodę CompleteRegistrationAsync , aby ustawić IDeviceInstallationService.Token wartość właściwości:

    Task CompleteRegistrationAsync(NSData deviceToken)
    {
        DeviceInstallationService.Token = deviceToken.ToHexString();
        return NotificationRegistrationService.RefreshRegistrationAsync();
    }
    

    Ta metoda odświeża również rejestrację i buforuje token urządzenia, jeśli został on zaktualizowany od czasu jego ostatniego przechowywania.

  9. AppDelegate W klasie dodaj metodę ProcessNotificationActions przetwarzania NSDictionary danych powiadomień i warunkowo wywołując metodę NotificationActionService.TriggerAction:

    void ProcessNotificationActions(NSDictionary userInfo)
    {
        if (userInfo == null)
            return;
    
        try
        {
            // If your app isn't in the foreground, the notification goes to Notification Center.
            // If your app is in the foreground, the notification goes directly to your app and you
            // need to process the notification payload yourself.
            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);
        }
    }
    
  10. AppDelegate W klasie dodaj metodę RegisteredForRemoteNotifications przekazującą deviceToken argument do CompleteRegistrationAsync metody :

    [Export("application:didRegisterForRemoteNotificationsWithDeviceToken:")]
    public void RegisteredForRemoteNotifications(UIApplication application, NSData deviceToken)
    {
        CompleteRegistrationAsync(deviceToken)
            .ContinueWith((task) =>
            {
                if (task.IsFaulted)
                    throw task.Exception;
            });
    }
    

    Ta metoda zostanie wywołana, gdy aplikacja zostanie zarejestrowana w celu odbierania powiadomienia zdalnego i będzie używana do żądania unikatowego tokenu urządzenia, który jest w rzeczywistości adresem aplikacji na urządzeniu.

  11. AppDelegate W klasie dodaj metodę ReceivedRemoteNotification przekazującą userInfo argument do ProcessNotificationActions metody :

    [Export("application:didReceiveRemoteNotification:")]
    public void ReceivedRemoteNotification(UIApplication application, NSDictionary userInfo)
    {
        ProcessNotificationActions(userInfo);
    }
    

    Ta metoda będzie wywoływana, gdy aplikacja otrzymała powiadomienie zdalne i jest używana do przetwarzania powiadomienia.

  12. AppDelegate W klasie dodaj metodę FailedToRegisterForRemoteNotifications , aby rejestrować błędy:

    [Export("application:didFailToRegisterForRemoteNotificationsWithError:")]
    public void FailedToRegisterForRemoteNotifications(UIApplication application, NSError error)
    {
        Debug.WriteLine(error.Description);
    }
    

    Ta metoda zostanie wywołana, gdy aplikacja nie może zarejestrować się w celu odbierania powiadomień zdalnych. Rejestracja może zakończyć się niepowodzeniem, jeśli urządzenie nie jest połączone z siecią, jeśli serwer APNS jest niemożliwy do osiągnięcia lub jeśli aplikacja jest niepoprawnie skonfigurowana.

    Uwaga

    W przypadku scenariuszy produkcyjnych należy zaimplementować odpowiednie rejestrowanie i obsługę błędów w metodzie FailedToRegisterForRemoteNotifications .

  13. AppDelegate W klasie dodaj metodę FinishedLaunching , aby warunkowo zażądać uprawnień do korzystania z powiadomień i zarejestrować się w celu otrzymywania powiadomień zdalnych:

    [Export("application:didFinishLaunchingWithOptions:")]
    public override bool FinishedLaunching(UIApplication application, NSDictionary launchOptions)
    {
        if (DeviceInstallationService.NotificationsSupported)
        {
            UNUserNotificationCenter.Current.RequestAuthorization(
                UNAuthorizationOptions.Alert |
                UNAuthorizationOptions.Badge |
                UNAuthorizationOptions.Sound,
                (approvalGranted, error) =>
                {
                    if (approvalGranted && error == null)
                    {
                        MainThread.BeginInvokeOnMainThread(() =>
                        {
                            UIApplication.SharedApplication.RegisterForRemoteNotifications();
                        });
                    }
                });
        }
    
        using (var userInfo = launchOptions?.ObjectForKey(UIApplication.LaunchOptionsRemoteNotificationKey) as NSDictionary)
        {
            ProcessNotificationActions(userInfo);
        }
    
        return base.FinishedLaunching(application, launchOptions);
    }
    

    Aby uzyskać informacje na temat monitowania o uprawnienie do korzystania z powiadomień, zobacz Monituj o uprawnienie do korzystania z powiadomień w developer.apple.com.

Aby uzyskać informacje o powiadomieniach w systemie iOS, zobacz Powiadomienia użytkowników w developer.apple.com.

Rejestrowanie typów w kontenerze wstrzykiwania zależności aplikacji

  1. W programie Visual Studio otwórz MauiProgram.cs i dodaj instrukcję using dla PushNotificationsDemo.Services przestrzeni nazw:

    using PushNotificationsDemo.Services;
    
  2. MauiProgram W klasie dodaj kod dla RegisterServices metody rozszerzenia, która rejestruje DeviceInstallationService element na każdej platformie, oraz międzyplatformowe PushDemoNotificationActionService i NotificationRegistrationService usługi, a następnie zwraca MauiAppBuilder obiekt:

    public static MauiAppBuilder RegisterServices(this MauiAppBuilder builder)
    {
    #if IOS
        builder.Services.AddSingleton<IDeviceInstallationService, PushNotificationsDemo.Platforms.iOS.DeviceInstallationService>();
    #elif ANDROID
        builder.Services.AddSingleton<IDeviceInstallationService, PushNotificationsDemo.Platforms.Android.DeviceInstallationService>();
    #endif
    
        builder.Services.AddSingleton<IPushDemoNotificationActionService, PushDemoNotificationActionService>();
        builder.Services.AddSingleton<INotificationRegistrationService>(new NotificationRegistrationService(Config.BackendServiceEndpoint, Config.ApiKey));
    
        return builder;
    }
    
  3. MauiProgram W klasie dodaj kod dla RegisterViews metody rozszerzenia, która rejestruje MainPage typ jako pojedynczy i który zwraca MauiAppBuilder obiekt:

    public static MauiAppBuilder RegisterViews(this MauiAppBuilder builder)
    {
        builder.Services.AddSingleton<MainPage>();
        return builder;
    }
    

    Typ MainPage jest zarejestrowany, ponieważ wymaga INotificationRegistrationService zależności, a wszystkie typy wymagające zależności muszą być zarejestrowane w kontenerze wstrzykiwania zależności.

  4. W klasie zmodyfikuj MauiProgram metodę CreateMauiApp , tak aby wywołała RegisterServices metody i RegisterViews rozszerzenia:

    public static MauiApp CreateMauiApp()
    {
        var builder = MauiApp.CreateBuilder();
        builder
            .UseMauiApp<App>()
            .ConfigureFonts(fonts =>
            {
                fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
                fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
            })
            .RegisterServices()
            .RegisterViews();
    
    #if DEBUG
          builder.Logging.AddDebug();
    #endif
          return builder.Build();
    }
    

Aby uzyskać więcej informacji na temat wstrzykiwania zależności w programie .NET MAUI, zobacz Wstrzykiwanie zależności.

Testowanie aplikacji

Aplikację można przetestować, wysyłając powiadomienia wypychane do aplikacji przy użyciu usługi zaplecza lub za pośrednictwem witryny Azure Portal.

Symulator systemu iOS obsługuje powiadomienia zdalne w systemie iOS 16 lub nowszym podczas uruchamiania w systemie macOS 13 lub nowszym na komputerach Mac z procesorami krzemowymi firmy Apple lub T2. Jeśli nie spełniasz tych wymagań sprzętowych, musisz przetestować aplikację systemu iOS na urządzeniu fizycznym. W systemie Android możesz przetestować aplikację na odblokowanym urządzeniu fizycznym dewelopera lub emulatorze.

Systemy Android i iOS wyświetlają powiadomienia wypychane w imieniu aplikacji, gdy są uruchomione w tle. Jeśli aplikacja jest uruchomiona na pierwszym planie po odebraniu powiadomienia, kod aplikacji określa zachowanie. Możesz na przykład zaktualizować interfejs aplikacji, aby odzwierciedlić nowe informacje zawarte w powiadomieniu.

Testowanie przy użyciu usługi zaplecza

Aby wysłać testowe powiadomienie wypychane do aplikacji za pośrednictwem usługi zaplecza opublikowanej w usłudze aplikacja systemu Azure Service:

  1. W programie Visual Studio uruchom aplikację PushNotificationsDemo w systemie Android lub iOS i wybierz przycisk Zarejestruj .

    Uwaga

    Jeśli testujesz w systemie Android, upewnij się, że nie używasz konfiguracji debugowania. Alternatywnie, jeśli aplikacja została wcześniej wdrożona, upewnij się, że została zamknięta, a następnie uruchom ją ponownie z poziomu uruchamiania.

  2. W wybranym narzędziu REST wyślij POST żądanie na następujący adres:

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

    Upewnij się, że nagłówki żądań są skonfigurowane tak, aby zawierały klucz apikey i jego wartość, ustawić treść na nieprzetworzoną i użyć następującej zawartości JSON:

    {
        "text": "Message from REST tooling!",
        "action": "action_a"
    }
    

    Ogólne żądanie powinno być podobne do następującego przykładu:

    POST /api/notifications/requests HTTP/1.1
    Host: https://<app_name>.azurewebsites.net
    apikey: <your_api_key>
    Content-Type: application/json
    
    {
        "text": "Message from REST tooling!",
        "action": "action_a"
    }
    
  3. W wybranym narzędziu REST sprawdź, czy otrzymasz odpowiedź 200 OK .

  4. W aplikacji w systemie Android lub iOS powinien zostać wyświetlony alert z odebraną akcją ActionA.

Aby uzyskać więcej informacji na temat wywoływania interfejsów API REST, zobacz Use .http files in Visual Studio and Test web APIs with the Http Repl (Używanie plików HTTP w programie Visual Studio i testowanie internetowych interfejsów API za pomocą protokołu Http Repl). W programie Visual Studio Code klient REST może służyć do testowania interfejsów API REST.

Testowanie przy użyciu witryny Azure Portal

Usługa Azure Notification Hubs umożliwia sprawdzenie, czy aplikacja może odbierać powiadomienia wypychane.

Aby wysłać testowe powiadomienie wypychane do aplikacji za pośrednictwem witryny Azure Portal:

  1. W programie Visual Studio uruchom aplikację PushNotificationsDemo w systemie Android lub iOS i wybierz przycisk Zarejestruj .

    Uwaga

    Jeśli testujesz w systemie Android, upewnij się, że nie używasz konfiguracji debugowania. Alternatywnie, jeśli aplikacja została wcześniej wdrożona, upewnij się, że została zamknięta, a następnie uruchom ją ponownie z poziomu uruchamiania.

  2. W witrynie Azure Portal przejdź do centrum powiadomień i wybierz przycisk Wyślij test w bloku Przegląd.

  3. W bloku Wysyłanie testowe wybierz wymaganą platformę i zmodyfikuj ładunek.

    W przypadku firmy Apple użyj następującego ładunku:

    {
      "aps": {
        "alert": "Message from Notification Hub!"
      },
      "action": "action_a"
    }
    

    W przypadku systemu Android użyj następującego ładunku:

    {
      "message": {
        "notification": {
          "title": "PushDemo",
          "body": "Message from Notification Hub!"
        },
        "data": {
          "action": "action_a"
        }
      }
    }
    

    Witryna Azure Portal powinna wskazywać, że powiadomienie zostało pomyślnie wysłane.

    Aby uzyskać informacje o formacie komunikatów firebase Cloud Messaging, zobacz About FCM messages on developer.android.com (Informacje o komunikatach FCM w developer.android.com).

  4. W aplikacji w systemie Android lub iOS powinien zostać wyświetlony alert z odebraną akcją ActionA.

Rozwiązywanie problemów

W poniższych sekcjach omówiono typowe problemy występujące podczas próby korzystania z powiadomień wypychanych w aplikacji klienckiej.

Brak odpowiedzi z usługi zaplecza

Podczas testowania lokalnego upewnij się, że usługa zaplecza jest uruchomiona i używa poprawnego portu.

W przypadku testowania 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 narzędziu REST lub w konfiguracji aplikacji .NET MAUI. Adres podstawowy powinien być https://<api_name>.azurewebsites.net lub https://localhost:7020 podczas testowania lokalnego.

Odbieranie kodu stanu 401 z usługi zaplecza

Sprawdź, czy poprawnie ustawiasz apikey nagłówek żądania i czy ta wartość jest zgodna z wartością skonfigurowaną dla usługi zaplecza.

Jeśli ten błąd zostanie wyświetlony podczas testowania lokalnego, upewnij się, że wartość klucza zdefiniowana w aplikacji .NET MAUI odpowiada Authentication:ApiKey wartości wpisów tajnych użytkownika używanych przez usługę zaplecza.

Jeśli testujesz przy użyciu aplikacji interfejsu API platformy Azure, upewnij się, że wartość klucza zdefiniowana w aplikacji .NET MAUI jest zgodna Authentication:ApiKey z wartością ustawienia aplikacji zdefiniowaną w witrynie Azure Portal. Jeśli to ustawienie aplikacji zostało utworzone lub zmienione po wdrożeniu usługi zaplecza, musisz ponownie uruchomić usługę, aby wartość została wdrożona.

Odbieranie kodu stanu 404 z usługi zaplecza

Sprawdź, czy punkt końcowy i metoda żądania HTTP są poprawne:

  • KŁAŚĆ- https://<api_name>.azurewebsites.net/api/notifications/installations
  • USUNĄĆ- https://<api_name>.azurewebsites.net/api/notifications/installations/<installation_id>
  • POST- https://<api_name>.azurewebsites.net/api/notifications/requests

Lub podczas testowania lokalnego:

  • KŁAŚĆ- https://localhost:7020/api/notifications/installations
  • USUNĄĆ- https://localhost:7020/api/notifications/installations/<installation_id>
  • POST- https://localhost:7020/api/notifications/requests

Ważne

Podczas określania adresu podstawowego w aplikacji .NET MAUI upewnij się, że kończy się na ./ Adres podstawowy powinien być https://<api_name>.azurewebsites.net lub https://localhost:7020/ podczas testowania lokalnego.

Nie otrzymuję powiadomień w systemie Android po uruchomieniu lub zatrzymaniu sesji debugowania

Upewnij się, że rejestrujesz się za każdym razem, gdy rozpoczynasz sesję debugowania. Debuger spowoduje wygenerowanie nowego tokenu programu Firebase, dlatego należy zaktualizować instalację centrum powiadomień.

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 StatusCode właściwości w obiekcie HttpResponse.

Przejrzyj poprzednie sugestie dotyczące rozwiązywania problemów, jeśli ma to zastosowanie, na podstawie kodu stanu.

Ustaw punkt przerwania w wierszach, które zwracają określone kody stanu odpowiedniego interfejsu API. Następnie spróbuj wywołać usługę zaplecza podczas lokalnego debugowania.

Zweryfikuj, czy usługa zaplecza działa zgodnie z oczekiwaniami według wybranego narzędzia REST, i użyj ładunku utworzonego przez aplikację .NET MAUI dla wybranej platformy.

Przejrzyj sekcje konfiguracji specyficzne dla platformy, aby upewnić się, że nie pominięto żadnych kroków. Sprawdź, czy odpowiednie wartości są rozpoznawane jako InstallationId zmienne i Token dla wybranej platformy.

Nie można rozpoznać identyfikatora urządzenia w komunikacie o błędzie urządzenia

Przejrzyj sekcje konfiguracji specyficzne dla platformy, aby upewnić się, że nie pominięto żadnych kroków.