Udostępnij za pośrednictwem


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

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

Powiadomienia push 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:

  • Instalacja urządzenia łączy uchwyt PNS z identyfikatorem 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ń push do wieloplatformowej aplikacji .NET MAUI na systemy Android i iOS. Zaplecze ASP.NET Core Web API służy do obsługi rejestracji urządzeń klienta i inicjowania powiadomień push. 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 ty:

  • 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 dla powiadomień push.
  • Skonfiguruj aplikację iOS dla powiadomień push.
  • Testowanie aplikacji.
  • Rozwiąż wszelkie problemy z ustawieniami 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 programistę urządzenie fizyczne lub emulator z zainstalowanym API 26 lub nowszym oraz usługami Google Play.

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

  • Aktywne konto dewelopera firmy Apple.
  • Komputer Mac z zainstalowanym Xcode oraz ważnym certyfikatem dewelopera zainstalowanym w Keychain.

Następnie w systemie iOS powinieneś 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.

Zarejestruj swoją aplikację iOS do powiadomień push

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

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

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 naliczana do twojego planu.

    6. Wybierz opcję Odzyskiwania po awarii: brak, sparowany region odzyskiwania lub elastyczny region odzyskiwania. Jeśli wybierzesz sparowany region odzyskiwania, zostanie wyświetlony region awaryjny. 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 portalu Azure przejdź do nowo utworzonego centrum powiadomień, a następnie do sekcji Zarządzanie zasadami dostępu.
  5. W bloku Polityki dostępu zanotuj ciąg połączenia dla polityki DefaultFullSharedAccessSignature. 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 portalu Azure przejdź do swojego centrum powiadomień i wybierz panel Ustawienia > Google (FCM v1).

  2. W panelu Google (FCM v1) wprowadź wartości dla pól Prywatny klucz, Adres e-mail klienta oraz ID projektu. Te wartości można znaleźć w pliku JSON klucza prywatnego pobranym z usługi Firebase Cloud Messaging:

    Pole 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 panelu Google (FCM v1) wybierz przycisk Zapisz.

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

W witrynie Azure portal przejdź do swojego centrum powiadomień i wybierz panel 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 push .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 prześlij 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 panelu 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ź wcześniej zdobyte wartości dla pól Identyfikator klucza, Identyfikator pakietu, Identyfikator zespołu i Token.
  3. W panelu Apple (APNS) wybierz tryb aplikacji Sandbox.
  4. W bloku Apple (APNS) wybierz przycisk Zapisz.

Utwórz aplikację back-endową Web 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 jako launchUrl, co jest ustawione 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 parametrów 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 Essentials na górze strony Przegląd.
    NotificationHub:ConnectionString Zobacz DefaultFullSharedAccessSignature* na stronie Zasady Dostępu.

    Spowoduje to skonfigurowanie lokalnych wartości konfiguracji przy użyciu narzędzia Secret Manager. Spowoduje to odseparowanie tajnych danych usługi Azure Notification Hub od rozwiązania Visual Studio, aby mieć pewność, że nie trafiły do systemu kontroli wersji.

    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 przyjąć dowolną wartość.

  2. W programie Visual Studio dodaj nowy folder o nazwie Authentication do projektu, a następnie dodaj nową klasę o nazwie do ApiKeyAuthOptions 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ć metody rozszerzeń: UseRouting, UseAuthentication i MapControllers.

    // 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 API nie jest tak bezpieczny jak token, wystarczy na potrzeby tego samouczka i będzie można go łatwo skonfigurować za pomocą ASP.NET Middleware.

Dodawanie i konfigurowanie usług

Aby dodać i skonfigurować usługi w aplikacji backendu interfejsu API sieci:

  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ń, osadzonego 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 cichych 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 tagów dostarczone do metody SendTemplateNotificationsAsync jest ograniczone do 20 tagów, jeśli zawiera tylko operatory OR. 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 jako implementację singletonu INotificationService, poniżej wywołania metody builder.Services.AddAuthentication.

    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 Kontrolera API z akcjami odczytu i 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 konstruktor NotificationsContoller, aby przyjmował jako argument zarejestrowane wystąpienie INotificationService i przypisz je do pola 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.

Utwórz aplikację API

Teraz utworzysz aplikację interfejsu API w usłudze Azure App Service, 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ę API w Azure Portal:

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

  2. W portalu Azure kliknij przycisk Utwórz zasób, a następnie wyszukaj i wybierz Aplikację API przed kliknięciem 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 API przejdź do zasobu.

  5. Na stronie Przegląd zanotuj domyślną wartość domeny. Ten URL to punkt końcowy zaplecza, który będzie wykorzystywany przez aplikację .NET MAUI. Adres URL będzie używać nazwy aplikacji API, którą określiłeś, w formacie 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:

    Nazwisko Wartość
    Authentication:ApiKey <api_key_value>
    NotificationHub:Name <hub_name_value>
    NotificationHub:ConnectionString <hub_connection_string_value>

    Ważne

    Dodano ustawienie aplikacji Authentication:ApiKey dla uproszczenia. 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ć swoją usługę zaplecza w usłudze Azure App Service:

  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 Publikuj wybierz pozycję Azure App Service (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 dla aplikacji API można pobrać z karty Przegląd w portalu Azure, a następnie użyć tego profilu w programie Visual Studio do opublikowania aplikacji.

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:

{}

Powinieneś otrzymać 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.

Stwórz aplikację .NET MAUI

W tej sekcji utworzysz aplikację .NET MAUI, która umożliwia rejestrację do otrzymywania powiadomień push z centrum powiadomień za pośrednictwem usługi backend oraz wyrejestrowanie się.

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 wyliczenia PushDemoAction do identyfikowania akcji, która jest wyzwalana za pomocą 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 na przechowywanie tajemnic 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.* do swojego pliku .gitignore, aby uniknąć zatwierdzania tego pliku do systemu kontroli wersji.

Tworzenie interfejsu użytkownika

Aby utworzyć interfejs użytkownika aplikacji:

  1. W programie Visual Studio otwórz plik VerticalStackLayout:

    <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 MainPage zaimplementuj OnRegisterButtonClicked i OnDeregisterButtonClicked procedury obsługi zdarzeń, wywołując odpowiednie metody rejestrowania i wyrejestrowywania w obiekcie INotificationRegistrationService.

    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 pomocniczego _actionService, a następnie subskrybuj zdarzenie IPushDemoNotificationActionService.ActionTriggered.

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

    public App(IPushDemoNotificationActionService service)
    {
        InitializeComponent();
    
        _actionService = service;
        _actionService.ActionTriggered += NotificationActionTriggered;
    }
    
  1. W klasie App zaimplementuj procedurę obsługi zdarzenia IPushDemoNotificationActionService.ActionTriggered.

    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;
                });
        });
    }
    

    Obsługa zdarzenia dla zdarzenia ActionTriggered demonstruje odbieranie 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 do odbierania i przetwarzania powiadomień push:

  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 on zostać dodany z akcją kompilacji typu GoogleServicesJson.

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

    Napiwek

    Pamiętaj, aby dodać google-services.json do pliku .gitignore, aby uniknąć zatwierdzania tego pliku do systemu kontroli wersji.

  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 zapewnia unikatowy identyfikator, korzystając z wartości Secure.AndroidId i ładunku rejestracyjnego 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 Informacje o komunikatach FCM na 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. W klasie MainActivity ustaw LaunchMode na SingleTop, aby MainActivity nie został utworzony ponownie po otwarciu:

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

    IPushDemoNotificationActionService _notificationActionService;
    IDeviceInstallationService _deviceInstallationService;
    
  9. W klasie MainActivity dodaj NotificationActionService i DeviceInstallationService właściwości prywatne, które pobierają swoje konkretne implementacje z kontenera iniekcji 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 MainActivityAndroid.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. W klasie MainActivity dodaj metodę ProcessNotificationActions, która sprawdzi, czy dane Intent ma dodatkową wartość o nazwie action, a następnie warunkowo uruchom action przy użyciu implementacji IPushDemoNotificationActionService:

    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);
    }
    

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

  13. W klasie MainActivity zastąp metodę OnCreate, aby wywołać metodę ProcessNotificationActions i pobrać token z 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 być ponownie zarejestrowana za każdym razem, gdy jest uruchamiana, oraz zatrzymana podczas sesji debugowania, aby nadal otrzymywać powiadomienia push.

  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 działa na Androidzie, kiedy pojawi się MainPage, i prosi użytkownika o udzielenie uprawnień POST_NOTIFICATIONS. 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 testowe (sandbox) 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 funkcjonalność powiadomień push. Następnie należy upewnić się, że aplikacja została skompilowana przy użyciu certyfikatu i profilu provisioningowego. 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ń push:

  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 powiadomień push 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>
    

    Ustawienie uprawnień środowiska usługi APS i wskazuje na użycie środowiska deweloperskiego Apple Push Notification Service. W aplikacjach produkcyjnych to uprawnienie powinno być ustawione na production. Aby uzyskać więcej informacji na temat tego uprawnienia, zobacz APS Environment Entitlement na 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 wartości UIDevice.IdentifierForVendor i danych rejestracji centrum powiadamiania.

  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 rozszerzenia ToHexString będzie wykorzystywana przez kod, jaki dodasz, aby analizować 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. W klasie AppDelegate dodaj pola zapasowe do przechowywania odwołań do implementacji IPushDemoNotificationActionService, INotificationRegistrationService i IDeviceInstallationService.

    IPushDemoNotificationActionService _notificationActionService;
    INotificationRegistrationService _notificationRegistrationService;
    IDeviceInstallationService _deviceInstallationService;
    
  7. W klasie AppDelegate dodaj prywatne właściwości NotificationActionService, NotificationRegistrationService i DeviceInstallationService, które pobierają swoje 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. W klasie AppDelegate dodaj metodę CompleteRegistrationAsync, aby ustawić wartość właściwości IDeviceInstallationService.Token:

    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. W klasie AppDelegate, dodaj metodę ProcessNotificationActions do przetwarzania danych powiadomień NSDictionary i warunkowego wywołania 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 proszenia o zgodę na korzystanie z powiadomień, zobacz Prośba o zgodę na korzystanie z powiadomień na 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. W klasie MauiProgram dodaj kod dla metody rozszerzenia RegisterServices, która rejestruje DeviceInstallationService na każdej platformie, oraz usługi międzyplatformowe PushDemoNotificationActionService i NotificationRegistrationService, i zwraca obiekt typu MauiAppBuilder:

    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. W klasie MauiProgram dodaj kod dla metody rozszerzenia RegisterViews, która rejestruje typ MainPage jako singleton i zwraca obiekt MauiAppBuilder.

    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 MauiProgram zmodyfikuj metodę CreateMauiApp, tak aby wywołała metody rozszerzenia RegisterServices i RegisterViews.

    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

Możesz przetestować swoją aplikację, wysyłając powiadomienia push do aplikacji przy użyciu zaplecza usług lub za pośrednictwem portalu Azure.

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 push w imieniu aplikacji, gdy jest uruchomiona 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 push do aplikacji za pośrednictwem usługi backendowej opublikowanej w usłudze Azure App 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 żądania są skonfigurowane tak, aby zawierały klucz apikey i jego wartość, ustaw ciało żądania jako surowe i użyj następującego kodu 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 push.

Aby wysłać testowe powiadomienie push do aplikacji za pośrednictwem portalu Azure:

  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 portalu Azure przejdź do centrum powiadomień i wybierz przycisk Testowe Wysyłanie na ostrzu 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 danych:

    {
      "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 Informacje o komunikatach FCM na stronie 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 napotykane podczas korzystania z powiadomień push 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 została wdrożona i działa 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 pojawia się podczas testowania lokalnego, upewnij się, że wartość klucza, którą zdefiniowałeś w aplikacji .NET MAUI, odpowiada wartości tajnych danych użytkownika określonych jako Authentication:ApiKey i 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:

  • Umieść - https://<api_name>.azurewebsites.net/api/notifications/installations
  • Usuń - 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: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, aby sprawdzić właściwość StatusCode w 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 dla zmiennych InstallationId i Token odpowiednie wartości są ustawiane na wybraną platformę.

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.