Delen via


Zelfstudie: Pushmeldingen verzenden naar .NET MAUI-apps met behulp van Azure Notification Hubs via een back-endservice

Voorbeeld bekijken. Het voorbeeld bekijken.

Pushmeldingen leveren informatie van een back-endsysteem naar een client-app. Apple, Google en andere platforms hebben elk hun eigen PNS (Push Notification Service). Met Azure Notification Hubs kunt u meldingen centraliseren op verschillende platforms, zodat uw back-end-app kan communiceren met één hub, die zorgt voor het distribueren van meldingen naar elke PNS.

Voor Azure Notification Hubs moeten apps zich registreren bij de hub en eventueel sjablonen definiëren en/of zich abonneren op tags:

  • Als u een apparaatinstallatie uitvoert, wordt een PNS-ingang gekoppeld aan een id in de Azure Notification Hub. Zie Registratiebeheer voor meer informatie over registraties.
  • Met sjablonen kunnen apparaten geparameteriseerde berichtsjablonen opgeven. Binnenkomende berichten kunnen per apparaat worden aangepast. Zie Notification Hubs-sjablonen voor meer informatie.
  • Tags kunnen worden gebruikt om u te abonneren op berichtcategorieën zoals nieuws, sport en weer. Zie Routerings- en tagexpressies voor meer informatie.

In deze tutorial gebruikt u Azure Notification Hubs om pushmeldingen te verzenden naar een .NET Multi-platform App UI (.NET MAUI) app die gericht is op Android en iOS. Een ASP.NET Core Web API-back-end wordt gebruikt voor het afhandelen van apparaatregistratie voor de client en voor het initiëren van een pushmelding. Deze bewerkingen worden verwerkt met behulp van het NuGet-pakket Microsoft.Azure.NotificationHubs . Zie Registratiebeheer vanuit een back-end voor meer informatie over de algehele aanpak.

In deze handleiding leert u:

  • Pushmeldingsservices en Azure Notification Hub instellen.
  • Maak een ASP.NET Core WebAPI-back-end-app.
  • Maak een .NET MAUI-app.
  • Configureer de Android-app voor pushmeldingen.
  • Configureer de iOS-app voor pushmeldingen.
  • De app testen.
  • Los eventuele installatie- en configuratieproblemen op.

Vereiste voorwaarden

U hebt het volgende nodig om deze zelfstudie te voltooien:

  • Een Azure-account met een actief abonnement.
  • Een pc of Mac waarop de nieuwste versie van Visual Studio/Visual Studio Code wordt uitgevoerd met de workload voor het ontwikkelen van de gebruikersinterface van de .NET-platform-app en de ASP.NET- en webontwikkelingsworkloads geïnstalleerd.

Voor Android hebt u het volgende nodig:

  • Een door de ontwikkelaar ontgrendeld fysiek apparaat, of een emulator, met API 26+ waarop Google Play Services zijn geïnstalleerd.

Voor iOS hebt u het volgende nodig:

  • Een actief Apple-ontwikkelaarsaccount.
  • Een Mac met Xcode, samen met een geldig ontwikkelaarscertificaat dat is geïnstalleerd in uw sleutelhanger.

Op iOS moet u een van de volgende hebben:

  • Een iOS 16+-simulator die wordt uitgevoerd in macOS 13+ op Mac-computers met Apple silicon- of T2-processors.

    OF

  • Een fysiek iOS-apparaat dat is geregistreerd bij uw ontwikkelaarsaccount (met iOS 13.0+).

  • Uw fysieke apparaat dat is geregistreerd in uw Apple-ontwikkelaarsaccount en is gekoppeld aan uw certificaat.

Belangrijk

De iOS-simulator ondersteunt externe meldingen in iOS 16+ wanneer deze wordt uitgevoerd op macOS 13+ op Mac-computers met Apple silicon- of T2-processors. Als u niet aan deze hardwarevereisten voldoet, hebt u een actief Apple-ontwikkelaarsaccount en een fysiek apparaat nodig.

Als u deze zelfstudie wilt volgen, moet u bekend zijn met:

Hoewel deze zelfstudie is gericht op Visual Studio, is het mogelijk om deze te volgen met Visual Studio Code op een pc of Mac. Er zijn echter enkele verschillen die moeten worden afgestemd. Bijvoorbeeld beschrijvingen van gebruikersinterfaces en werkstromen, sjabloonnamen en omgevingsconfiguratie.

Push notification services en Azure Notification Hub instellen

In deze sectie gaat u Firebase Cloud Messaging en Apple Push Notification Services (APNS) instellen. Vervolgens maakt en configureert u een Azure Notification Hub om met deze services te werken.

Een Firebase-project maken

Een Firebase-project maken:

  1. Meld u in een webbrowser aan bij de Firebase-console.

  2. Selecteer in de Firebase-console de knop Project toevoegen en maak een nieuw Firebase-project en voer PushDemo in als projectnaam.

    Opmerking

    Er wordt een unieke naam voor u gegenereerd. Dit bestaat standaard uit een kleine letter van de naam die u hebt opgegeven plus een gegenereerd getal gescheiden door een streepje. U kunt dit desgewenst wijzigen, mits uw wijzigingen nog steeds wereldwijd uniek zijn.

  3. Nadat uw project is gemaakt, selecteert u het Android-logo om Firebase toe te voegen aan een Android-app:

    Schermopname van het toevoegen van Firebase aan een Android-app in de Firebase Cloud Messaging-console.

  4. Voer op de pagina Firebase toevoegen aan uw Android-app een naam in voor uw pakket, eventueel een app-bijnaam en selecteer de knop App registreren :

    Schermopname van het registreren van uw Android-app bij Firebase.

  5. Selecteer op de pagina Firebase toevoegen aan uw Android-app de knop Downloaden google-services.json en sla het bestand op in een lokale map voordat u de knop Volgende selecteert:

    Schermopname van het downloaden van het JSON-bestand van Google Services.

  6. Selecteer op de pagina Firebase toevoegen aan uw Android-app de knop Volgende .

  7. Selecteer op de pagina Firebase toevoegen aan uw Android-app de knop Doorgaan naar de console .

  8. Selecteer in de Firebase-console het pictogram Projectoverzicht en selecteer vervolgens Project-instellingen:

    Schermopname van het selecteren van de projectinstellingen in de Firebase Cloud Messaging-console.

  9. Selecteer in de projectinstellingen het tabblad Cloud Messaging . U ziet dat Firebase Cloud Messaging API (V1) is ingeschakeld:

    Schermopname waarin wordt bevestigd dat Firebase Cloud Messaging V1 is ingeschakeld.

  10. Selecteer in de projectinstellingen het tabblad Serviceaccounts en selecteer vervolgens de knop Nieuwe persoonlijke sleutel genereren .

  11. Selecteer in het dialoogvenster Nieuwe persoonlijke sleutel genereren de knop Sleutel genereren :

    Schermopname van het genereren van een nieuwe persoonlijke sleutel in de Firebase Cloud Messaging-console.

    Er wordt een JSON-bestand gedownload dat waarden bevat die u in uw Azure Notification Hub invoert.

Uw iOS-app registreren voor pushmeldingen

Als u pushmeldingen wilt verzenden naar een iOS-app, moet u uw app registreren bij Apple en registreren voor pushmeldingen. U kunt dit doen door de stappen uit te voeren in de volgende Documentatie van Azure Notification Hub:

Als u pushmeldingen wilt ontvangen op een fysiek apparaat, moet u ook een inrichtingsprofiel maken.

Belangrijk

Als u achtergrondmeldingen op iOS wilt ontvangen, moet u de achtergrondmodus voor externe meldingen toevoegen aan uw app. Zie De mogelijkheid voor externe meldingen inschakelen op developer.apple.com voor meer informatie.

Een Azure Notification Hub maken

Een Notification Hub maken in Azure Portal:

  1. Meld u in een webbrowser aan bij Azure Portal.
  2. Klik in Azure Portal op de knop Een resource maken en zoek en kies Notification Hub voordat u de knop Maken selecteert.
  3. Voer op de pagina Notification Hub de volgende stappen uit:
    1. Selecteer in het veld Abonnement de naam van het Azure-abonnement dat u wilt gebruiken en selecteer vervolgens een bestaande resourcegroep of maak een nieuwe resourcegroep.

    2. Voer in het veld Naamruimtedetails een unieke naam in voor de nieuwe naamruimte.

    3. Typ in het veld Details van Notification Hub een naam voor de Notification Hub. Dit is vereist omdat een naamruimte een of meer Notification Hubs bevat.

    4. Selecteer in de vervolgkeuzelijst Locatie een waarde die de locatie aangeeft waarin u de Notification Hub wilt maken.

    5. Controleer de optie Beschikbaarheidszones . Als u een regio met beschikbaarheidszones hebt gekozen, is het selectievakje standaard ingeschakeld.

      Opmerking

      Beschikbaarheidszones is een betaalde functie, dus er worden extra kosten aan uw laag toegevoegd.

    6. Kies een optie voor herstel na noodgevallen : geen, gekoppelde herstelregio of flexibele herstelregio. Als u gekoppelde herstelregio kiest, wordt de failoverregio weergegeven. Als u Flexibele herstelregio selecteert, gebruikt u de vervolgkeuzelijst om te kiezen uit een lijst met herstelregio's.

    7. Selecteer de knop Create. De Notification Hub wordt gemaakt.

  4. Blader in Azure Portal naar de zojuist gemaakte Notification Hub en ga vervolgens naar de blade Toegangsbeleid beheren>.
  5. Noteer de verbindingsreeks voor het DefaultFullSharedAccessSignature beleid op de blade Toegangsbeleid. U hebt dit later nodig bij het bouwen van een back-endservice die communiceert met uw Notification Hub.

Zie Een Azure Notification Hub maken in Azure Portal voor meer informatie over het maken van een Notification Hub.

Firebase Cloud Messaging configureren in de Notification Hub

Uw Notification Hub configureren voor communicatie met Firebase Cloud Messaging:

  1. Blader in Azure Portal naar uw Notification Hub en selecteer de blade Instellingen > Google (FCM v1).

  2. Voer op de blade Google (FCM v1) waarden in voor de velden Persoonlijke sleutel, Client-e-mail en Project-id . Deze waarden vindt u in het JSON-bestand met de persoonlijke sleutel dat u hebt gedownload van Firebase Cloud Messaging:

    Azure-veld JSON-sleutel Voorbeeld van JSON-waarde
    Persoonlijke sleutel private_key Deze waarde moet beginnen met -----BEGIN PRIVATE KEY-----\n en eindigen met -----END PRIVATE KEY-----\n.
    E-mail van client client_email firebase-adminsdk-55sfg@pushdemo-d6ab2.iam.gserviceaccount.com
    Project-id project_id pushdemo-d6ab2
  3. Selecteer op de blade Google (FCM v1) de knop Opslaan .

Apple Push Notification Service configureren in de Notification Hub

Blader in Azure Portal naar uw Notification Hub en selecteer de blade Instellingen Apple (APNS) >. Volg vervolgens de juiste stappen op basis van de methode die u eerder hebt gekozen bij het maken van een certificaat voor de Notification Hub.

Belangrijk

Wanneer u de toepassingsmodus instelt, kiest u alleen Productie als u pushmeldingen wilt verzenden naar gebruikers die uw app in de Store hebben gekocht.

Optie 1: een .p12-pushcertificaat gebruiken

  1. Selecteer op de blade Apple (APNS) de modus Certificaatverificatie .
  2. Selecteer op de blade Apple (APNS) het bestandspictogram naast het veld Certificaat uploaden . Selecteer vervolgens het .p12-bestand dat u eerder hebt geëxporteerd en upload het.
  3. Voer op de blade Apple (APNS) het certificaatwachtwoord in het veld Wachtwoord in, indien nodig.
  4. Selecteer op de Apple (APNS) blade de Sandbox-toepassingsmodus.
  5. Selecteer op de blade Apple (APNS) de knop Opslaan .

Optie 2: verificatie op basis van tokens gebruiken

  1. Selecteer op de blade Apple (APNS) de tokenverificatiemodus .
  2. Voer op de blade Apple (APNS) de waarden in die u eerder hebt verkregen voor de velden Sleutel-id, Bundel-id, Team-id en Token .
  3. Selecteer in het paneel Apple (APNS) de modus voor de toepassing Sandbox.
  4. Selecteer op de blade Apple (APNS) de knop Opslaan .

Een ASP.NET Core Web API-back-end-app maken

In deze sectie maakt u een ASP.NET Core Web API-back-end voor het afhandelen van de installatie van apparaten en het verzenden van meldingen naar de .NET MAUI-app.

Een web-API-project maken

Een web-API-project maken:

  1. Maak in Visual Studio een ASP.NET Core Web API-project :

    Schermopname van het maken van een nieuw ASP.NET Core Web API-project in Visual Studio.

  2. Geef in het dialoogvenster Uw nieuwe project configureren de naam Van het project PushNotificationsAPI.

  3. Controleer in het dialoogvenster Aanvullende informatie of de selectievakjes Configureren voor HTTPS en Controllers gebruiken zijn ingeschakeld:

    Schermopname van het configureren van het ASP.NET Core Web API-project in Visual Studio.

  4. Nadat het project is gemaakt, drukt u op F5 om het project uit te voeren.

    De app is momenteel geconfigureerd om WeatherForecastController als launchUrl te gebruiken, wat is ingesteld in het bestand Eigenschappen\launchSettings.js. De app wordt gestart in een webbrowser en geeft enkele JSON-gegevens weer.

    Belangrijk

    Wanneer u een ASP.NET Core-project uitvoert dat https gebruikt, detecteert Visual Studio of het ASP.NET Core HTTPS-ontwikkelingscertificaat is geïnstalleerd in uw lokale certificaatarchief voor gebruikers en biedt visual Studio aan om het te installeren en te vertrouwen als het ontbreekt.

  5. Sluit de webbrowser.

  6. Vouw in Solution Explorer de map Controllers uit en verwijder WeatherForecastController.cs.

  7. Verwijder WeatherForecast.cs in Solution Explorer, in de rootmap van het project.

  8. Open een opdrachtvenster en navigeer naar de map met het projectbestand. Voer vervolgens de volgende opdrachten uit:

    dotnet user-secrets init
    dotnet user-secrets set "NotificationHub:Name" <value>
    dotnet user-secrets set "NotificationHub:ConnectionString" "<value>"
    

    Vervang de tijdelijke aanduidingen door uw eigen Azure Notification Hub-naam en verbindingsreekswaarden. Deze vindt u op de volgende locaties in uw Azure Notification Hub:

    Configuratiewaarde Locatie
    NotificationHub:Name Zie Name in de Essentials samenvatting bovenaan de pagina Overzicht.
    NotificationHub:ConnectionString Zie DefaultFullSharedAccessSignature* op de pagina Toegangsbeleid .

    Hiermee stelt u lokale configuratiewaarden in met behulp van het hulpprogramma Secret Manager. Hierdoor worden uw Azure Notification Hub-geheimen losgekoppeld van de Visual Studio-oplossing om ervoor te zorgen dat ze niet in broncodebeheer terechtkomen.

    Aanbeveling

    Overweeg voor productiescenario's een service zoals Azure KeyVault om de verbindingsreeks veilig op te slaan.

Clients verifiëren met een API-sleutel

Clients verifiëren met een API-sleutel:

  1. Open een opdrachtvenster en navigeer naar de map met het projectbestand. Voer vervolgens de volgende opdrachten uit:

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

    Vervang de tijdelijke aanduidingswaarde door uw API-sleutel. Dit kan elke waarde zijn.

  2. Voeg in Visual Studio een nieuwe map met de naam Authentication toe aan uw project en voeg vervolgens een nieuwe klasse toe met de naam ApiKeyAuthOptionsVerificatiemap en vervang de bijbehorende code door de volgende code:

    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. Voeg in Visual Studio een nieuwe klasse toe met de naam ApiKeyAuthHandler aan de map Verificatie en vervang de bijbehorende code door de volgende code:

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

    Een verificatiehandler is een type dat het gedrag van een schema implementeert, wat in dit geval een aangepast API-sleutelschema is.

  4. Voeg in Visual Studio een nieuwe klasse toe met de naam AuthenticationBuilderExtensions aan de map Verificatie en vervang de bijbehorende code door de volgende code:

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

    Deze extensiemethode wordt gebruikt om de middlewareconfiguratiecode in Program.cs te vereenvoudigen.

  5. Open in Visual Studio Program.cs en werk de code bij om de VERIFICATIE van de API-sleutel onder de aanroep naar de builder.Services.AddControllers methode te configureren:

    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. Werk in Program.cs de code onder de // Configure the HTTP request pipeline opmerking bij om de UseRoutingmethoden en UseAuthenticationMapControllers uitbreidingsmethoden aan te roepen:

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

    De UseAuthentication extensiemethode registreert de middleware die gebruikmaakt van het eerder geregistreerde verificatieschema. UseAuthentication moet worden aangeroepen voordat middleware wordt aangeroepen die afhankelijk is van geauthenticeerde gebruikers.

    Opmerking

    Hoewel een API-sleutel niet zo veilig is als een token, is deze voldoende voor deze zelfstudie en kan deze eenvoudig worden geconfigureerd via de ASP.NET Middleware.

Services toevoegen en configureren

Services toevoegen en configureren in uw web-API-back-end-app:

  1. Voeg in Visual Studio het NuGet-pakket Microsoft.Azure.NotificationHubs toe aan uw project. Dit NuGet-pakket wordt gebruikt voor toegang tot uw Notification Hub, ingekapseld binnen een service.

  2. Voeg in Visual Studio een nieuwe map met de naam Modellen toe aan uw project en voeg vervolgens een nieuwe klasse toe met de naam PushTemplates aan de map Modellen en vervang de bijbehorende code door de volgende code:

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

    De PushTemplates-klasse bevat getokeniseerde melding-payloads voor algemene en stille pushmeldingen. Deze nettoladingen worden buiten de installatie gedefinieerd om experimenten mogelijk te maken zonder bestaande installaties via de service bij te werken. Het verwerken van wijzigingen in installaties op deze manier valt buiten het bereik van dit artikel. Overweeg in productscenario's aangepaste sjablonen te gebruiken.

  3. Voeg in Visual Studio een nieuwe klasse toe met de naam DeviceInstallation aan de map Modellen en vervang de bijbehorende code door de volgende code:

    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. Voeg in Visual Studio een nieuwe klasse toe met de naam NotificationRequest aan de map Modellen en vervang de bijbehorende code door de volgende code:

    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. Voeg in Visual Studio een nieuwe klasse toe met de naam NotificationHubOptions aan de map Modellen en vervang de bijbehorende code door de volgende code:

    using System.ComponentModel.DataAnnotations;
    
    namespace PushNotificationsAPI.Models;
    
    public class NotificationHubOptions
    {
        [Required]
        public string Name { get; set; }
    
        [Required]
        public string ConnectionString { get; set; }
    }
    
  6. Voeg in Visual Studio een nieuwe map met de naam Services toe aan uw project en voeg vervolgens een nieuwe interface toe met de naam INotificationServiceservices en vervang de bijbehorende code door de volgende code:

    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. Voeg in Visual Studio een nieuwe klasse toe met de naam NotificationHubService aan de map Services en vervang de bijbehorende code door de volgende code:

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

    De tagexpressie die aan de SendTemplateNotificationsAsync methode wordt verstrekt, is beperkt tot 20 tags als deze alleen OR's bevatten. Anders zijn ze beperkt tot 6 tags. Zie Routerings- en tagexpressiesvoor meer informatie.

  8. In Visual Studio, open Program.cs en werk de code bij om de NotificationHubService als singleton-implementatie van INotificationService toe te voegen onder de aanroep van de builder.Services.AddAuthentication methode.

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

De REST API voor meldingen maken

De REST API voor meldingen maken:

  1. Voeg in Visual Studio een nieuwe controller toe met de naam NotificationsController aan de map Controllers .

    Aanbeveling

    Kies de API-controller met een sjabloon voor lees-/schrijfacties .

  2. Voeg in het bestand NotificationsController.cs de volgende using instructies toe bovenaan het bestand:

    using System.ComponentModel.DataAnnotations;
    using System.Net;
    using Microsoft.AspNetCore.Authorization;
    using Microsoft.AspNetCore.Mvc;
    using PushNotificationsAPI.Models;
    using PushNotificationsAPI.Services;
    
  3. Voeg in het bestand NotificationsController.cs het Authorize kenmerk toe aan de NotificationsController klasse:

    [Authorize]
    [ApiController]
    [Route("api/[controller]")]
    public class NotificationsController : ControllerBase
    
  4. Werk in het bestand NotificationsController.cs de NotificationsContoller constructor bij om het geregistreerde exemplaar van INotificationService een argument te accepteren en toe te wijzen aan een alleen-lezen lid:

    readonly INotificationService _notificationService;
    
    public NotificationsController(INotificationService notificationService)
    {
        _notificationService = notificationService;
    }
    
  5. Vervang in het bestand NotificationsContoller.cs alle methoden door de volgende code:

    [HttpPut]
    [Route("installations")]
    [ProducesResponseType((int)HttpStatusCode.OK)]
    [ProducesResponseType((int)HttpStatusCode.BadRequest)]
    [ProducesResponseType((int)HttpStatusCode.UnprocessableEntity)]
    public async Task<IActionResult> UpdateInstallation(
        [Required] DeviceInstallation deviceInstallation)
    {
        var success = await _notificationService
            .CreateOrUpdateInstallationAsync(deviceInstallation, HttpContext.RequestAborted);
    
        if (!success)
            return new UnprocessableEntityResult();
    
        return new OkResult();
    }
    
    [HttpDelete()]
    [Route("installations/{installationId}")]
    [ProducesResponseType((int)HttpStatusCode.OK)]
    [ProducesResponseType((int)HttpStatusCode.BadRequest)]
    [ProducesResponseType((int)HttpStatusCode.UnprocessableEntity)]
    public async Task<ActionResult> DeleteInstallation(
        [Required][FromRoute] string installationId)
    {
        // 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. Wijzig de launchUrl eigenschap van elk profiel in het bestand Eigenschappen/launchSettings.json van weatherforecast naar api/notifications.

Een API-app maken

U maakt nu een API-app in Azure App Service om uw back-endservice te hosten. Dit kan rechtstreeks vanuit Visual Studio of Visual Studio Code, met Azure CLI, Azure PowerShell, Azure Developer CLI en via de Azure-portal. Zie Uw web-app publiceren voor meer informatie.

Ga als volgende te werk om een API-app te maken in Azure Portal:

  1. Meld u in een webbrowser aan bij Azure Portal.

  2. Klik in Azure Portal op de knop Een resource maken en zoek en kies api-app voordat u de knop Maken selecteert.

  3. Werk op de pagina API-app maken de volgende velden bij voordat u de knop Maken selecteert:

    Veld Handeling
    Abonnement Kies hetzelfde doelabonnement waarin u de Notification Hub hebt gemaakt.
    Resourcegroep Kies dezelfde resourcegroep waarin u de Notification Hub hebt gemaakt.
    Naam Voer een wereldwijd unieke naam in.
    Runtime stack Zorg ervoor dat de nieuwste versie van .NET is geselecteerd.
  4. Zodra de API-app is ingericht, gaat u naar de resource.

  5. Noteer op de pagina Overzicht de standaarddomeinwaarde. Deze URL is uw backend-eindpunt dat wordt benaderd door uw .NET MAUI-app. De URL gebruikt de naam van de API-app die u hebt opgegeven, met de indeling https://<app_name>.azurewebsites.net.

  6. Blader in Azure Portal naar de blade Omgevingsvariabelen instellingen > en zorg ervoor dat het tabblad App-instellingen is geselecteerd. Gebruik vervolgens de knop Toevoegen om de volgende instellingen toe te voegen:

    Naam Waarde
    Verificatie: ApiKey <api_key_value>
    NotificationHub:Naam <hub_name_value>
    NotificationHub:ConnectionString <waarde_van_hub_verbindingsreeks>

    Belangrijk

    De Authentication:ApiKey toepassingsinstelling is voor het gemak toegevoegd. Overweeg voor productiescenario's een service zoals Azure KeyVault om de verbindingsreeks veilig op te slaan.

    Zodra al deze instellingen zijn ingevoerd, selecteert u de knop Toepassen en vervolgens de knop Bevestigen .

De back-endservice publiceren

Uw back-endservice publiceren naar Azure App Service:

  1. Klik in Visual Studio met de rechtermuisknop op uw project en selecteer Publiceren.
  2. Selecteer Azure in de wizard Publiceren en vervolgens de knop Volgende.
  3. Selecteer Azure App Service (Windows) in de wizard Publiceren en klik vervolgens op de knop Volgende.
  4. Volg in de wizard Publiceren de verificatiestroom om Visual Studio te verbinden met uw Azure-abonnement en de app te publiceren.

Visual Studio bouwt, verpakt en publiceert de app naar Azure en start vervolgens de app in uw standaardbrowser. Zie Een ASP.NET-web-app publiceren voor meer informatie.

Aanbeveling

U kunt een publicatieprofiel voor uw app downloaden via de blade Overzicht van uw API-app in Azure Portal en vervolgens het profiel in Visual Studio gebruiken om uw app te publiceren.

De gepubliceerde API valideren

Als u wilt controleren of de API-app correct is gepubliceerd, moet u de REST-tooling van uw keuze gebruiken om een POST aanvraag naar het volgende adres te verzenden:

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

Opmerking

Het basisadres is https://<app_name>.azurewebsites.net.

Zorg ervoor dat u de aanvraagheaders configureert voor het opnemen van de sleutel apikey en de waarde ervan, stel de hoofdtekst in op onbewerkt en gebruik de volgende tijdelijke aanduiding voor JSON-inhoud:

{}

U zou een 400 Bad Request reactie van de dienst moeten ontvangen.

Opmerking

Het is nog niet mogelijk om de API te testen met geldige aanvraaggegevens, omdat hiervoor platformspecifieke informatie van de .NET MAUI-app vereist is.

Zie HTTP-bestanden gebruiken in Visual Studio en web-API's testen met http Repl voor meer informatie over het aanroepen van REST API's. In Visual Studio Code kan REST Client worden gebruikt om REST API's te testen.

Maak een .NET MAUI-app

In deze sectie bouwt u een .NET Multi-platform App UI (.NET MAUI) app waarmee u zich kunt registreren om pushmeldingen van een Notification Hub te ontvangen via de back-endservice, en kunt u zich ook weer uitschrijven.

Uw .NET MAUI-app maken:

  1. Maak in Visual Studio een nieuwe .NET MAUI-app met de naam PushNotificationsDemo met behulp van de projectsjabloon .NET MAUI App .

  2. Voeg in Visual Studio een nieuwe map met de naam Models toe aan het .NET MAUI-project en voeg vervolgens een nieuwe klasse toe met de naam DeviceInstallation aan de map Modellen en vervang de bijbehorende code door de volgende code:

    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. Voeg in Visual Studio een opsomming toe met de naam PushDemoAction aan de map Modellen en vervang de bijbehorende code door de volgende code:

    namespace PushNotificationsDemo.Models;
    
    public enum PushDemoAction
    {
        ActionA,
        ActionB
    }
    
  4. Voeg in Visual Studio een nieuwe map met de naam Services toe aan het .NET MAUI-project en voeg vervolgens een nieuwe interface toe met de naam IDeviceInstallationService aan de map Services en vervang de bijbehorende code door de volgende code:

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

    Deze interface wordt later op elk platform geïmplementeerd om de DeviceInstallation informatie te verstrekken die vereist is voor de back-endservice.

  5. Voeg in Visual Studio een interface toe met de naam INotificationRegistrationService aan de map Services en vervang de bijbehorende code door de volgende code:

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

    Deze interface verwerkt de interactie tussen de client en de back-endservice.

  6. Voeg in Visual Studio een interface toe met de naam INotificationActionService aan de map Services en vervang de bijbehorende code door de volgende code:

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

    Deze interface wordt gebruikt als een eenvoudig mechanisme om de verwerking van meldingsacties te centraliseren.

  7. Voeg in Visual Studio een interface toe met de naam IPushDemoNotificationActionService aan de map Services en vervang de bijbehorende code door de volgende code:

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

    Het IPushDemoNotificationActionService type is specifiek voor deze app en gebruikt de PushDemoAction opsomming om de actie te identificeren die wordt geactiveerd met behulp van een sterk getypte benadering.

  8. Voeg in Visual Studio een klasse toe met de naam NotificationRegistrationService aan de map Services en vervang de bijbehorende code door de volgende code:

    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. Voeg in Visual Studio een klasse toe met de naam PushDemoNotificationActionService aan de map Services en vervang de bijbehorende code door de volgende code:

    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. Voeg in Visual Studio een klasse toe met de naam Config aan de hoofdmap van het project en vervang de bijbehorende code door de volgende code:

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

    De Config klasse wordt gebruikt als een eenvoudige manier om uw geheimen buiten broncodebeheer te houden. U kunt deze waarden vervangen als onderdeel van een geautomatiseerde build of deze overschrijven met behulp van een lokale gedeeltelijke klasse.

    Belangrijk

    Wanneer u het basisadres opgeeft in de .NET MAUI-app, moet u ervoor zorgen dat het eindigt met een /.

  11. Voeg in Visual Studio een klasse toe met de naam Config.local_secrets aan de hoofdmap van het project. Vervang vervolgens de code in het Config.local_secrets.cs bestand door de volgende code:

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

    Vervang de tijdelijke aanduidingen door de waarden die u hebt gekozen bij het maken van de back-endservice. De BackendServiceEndpoint URL moet de indeling https://<api_app_name>.azurewebsites.net/gebruiken.

    Aanbeveling

    Vergeet niet om *.local_secrets.* toe te voegen aan uw .gitignore bestand om te voorkomen dat dit bestand naar bronbeheer wordt doorgevoerd.

De gebruikersinterface maken

De gebruikersinterface van de app maken:

  1. In Visual Studio, open MainPage.xaml en vervang de VerticalStackLayout en zijn onderliggende elementen door de volgende XAML:

    <VerticalStackLayout Margin="20"
                         Spacing="6">
        <Button x:Name="registerButton"
                Text="Register"
                Clicked="OnRegisterButtonClicked" />
        <Button x:Name="deregisterButton"
                Text="Deregister"
                Clicked="OnDeregisterButtonClicked" />
    </VerticalStackLayout>
    
  2. Open in Visual Studio MainPage.xaml.cs en voeg een using instructie toe voor de PushNotificationsDemo.Services naamruimte:

    using PushNotificationsDemo.Services;
    
  3. Voeg in MainPage.xaml.cs een readonly backingveld toe om een verwijzing naar de INotificationRegistrationService implementatie op te slaan:

    readonly INotificationRegistrationService _notificationRegistrationService;
    
  4. Los de INotificationRegistrationService implementatie in de MainPage constructor op en wijs deze toe aan het _notificationRegistrationService backingveld:

    public MainPage(INotificationRegistrationService service)
    {
        InitializeComponent();
    
        _notificationRegistrationService = service;
    }
    
  5. Implementeer in de MainPage klasse de OnRegisterButtonClicked en OnDeregisterButtonClicked gebeurtenishandlers en roep daarbij de bijbehorende registreer- en deregistreermethoden aan voor het INotificationRegistrationService object.

    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;
                });
        });
    }
    
    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(() =>
        {
            DisplayAlertAsync("Push notifications demo", message, "OK")
                .ContinueWith((task) =>
                {
                    if (task.IsFaulted)
                        throw task.Exception;
                });
        });
    }
    

    Belangrijk

    In de app worden registratie en de-registratie uitgevoerd als reactie op gebruikersinvoer, zodat deze functionaliteit gemakkelijker kan worden verkend en getest. In een productie-app voert u doorgaans de registratie- en afmeldacties uit op het juiste moment in de levenscyclus van de app, zonder expliciete gebruikersinvoer.

  6. Open in Visual Studio App.xaml.cs en voeg de volgende using instructies toe:

    using PushNotificationsDemo.Models;
    using PushNotificationsDemo.Services;
    
  7. Voeg in App.xaml.cs een readonly back-upveld toe om een verwijzing naar de IPushDemoNotificationActionService implementatie op te slaan:

    readonly IPushDemoNotificationActionService _actionService;
    
  1. Los de IPushDemoNotificationActionService implementatie op binnen de App constructor en wijs deze toe aan het _actionService backing field, en meld u aan voor het IPushDemoNotificationActionService.ActionTriggered evenement:

    public App(IPushDemoNotificationActionService service)
    {
        InitializeComponent();
    
        _actionService = service;
        _actionService.ActionTriggered += NotificationActionTriggered;
    
        MainPage = new AppShell();
    }
    
  1. Los in de App constructor de IPushDemoNotificationActionService implementatie op, wijs deze toe aan het _actionService backingveld en abonneer je op de IPushDemoNotificationActionService.ActionTriggered gebeurtenis.

    public App(IPushDemoNotificationActionService service)
    {
        InitializeComponent();
    
        _actionService = service;
        _actionService.ActionTriggered += NotificationActionTriggered;
    }
    
  1. Implementeer in de App klasse de gebeurtenis-handler voor de IPushDemoNotificationActionService.ActionTriggered gebeurtenis:

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

    De eventhandler voor de ActionTriggered gebeurtenis demonstreert het ontvangen en de verwerking van pushmeldingen. Deze worden doorgaans op de achtergrond afgehandeld, bijvoorbeeld door naar een specifieke weergave te navigeren of bepaalde gegevens te vernieuwen in plaats van een waarschuwing weer te geven.

De Android-app configureren

Uw .NET MAUI-app op Android configureren voor het ontvangen en verwerken van pushmeldingen:

  1. Voeg in Visual Studio het Xamarin.Firebase.Messaging NuGet-pakket toe aan uw .NET MAUI-app-project.

  2. Voeg in Visual Studio uw google-services.json bestand toe aan de map Platforms/Android van uw .NET MAUI-app-project. Zodra het bestand is toegevoegd aan uw project, moet het zijn toegevoegd met een buildactie van GoogleServicesJson:

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

    Aanbeveling

    Vergeet niet om google-services.json toe te voegen aan uw .gitignore-bestand om te voorkomen dat dit bestand in de broncontrole wordt gecommit.

  3. Bewerk in Visual Studio het projectbestand (*.csproj) en stel het SupportedOSPlatformVersion voor Android in op 26.0:

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

    Google heeft wijzigingen aangebracht in Android-meldingskanalen in API 26. Zie Meldingskanalen op developer.android.com voor meer informatie.

  4. Voeg in de map Platforms/Android van het project een nieuwe klasse toe met de naam DeviceInstallationService en vervang de bijbehorende code door de volgende code:

    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.";
        }
    }
    

    Deze klasse biedt een unieke ID, door de Secure.AndroidId waarde te gebruiken en de payload van de Notification Hub-registratie.

  5. Voeg in de map Platforms/Android van het project een nieuwe klasse toe met de naam PushNotificationFirebaseMessagingService en vervang de bijbehorende code door de volgende code:

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

    Deze klasse heeft een IntentFilter kenmerk dat het com.google.firebase.MESSAGING_EVENT filter bevat. Met dit filter kan Android binnenkomende berichten doorgeven aan deze klasse voor verwerking.

    Zie Over FCM-berichten op developer.android.com voor informatie over de berichtindeling Firebase Cloud Messaging.

  6. Open in Visual Studio het bestand MainActivity.cs in de map Platforms/Android en voeg de volgende using instructies toe:

    using Android.App;
    using Android.Content;
    using Android.Content.PM;
    using Android.OS;
    using PushNotificationsDemo.Services;
    using Firebase.Messaging;
    
  7. Stel in de MainActivity class de LaunchMode in op SingleTop zodat de MainActivity niet opnieuw wordt gemaakt wanneer deze wordt geopend.

    [Activity(
        Theme = "@style/Maui.SplashTheme",
        MainLauncher = true,
        LaunchMode = LaunchMode.SingleTop,
        ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation | ConfigChanges.UiMode | ConfigChanges.ScreenLayout | ConfigChanges.SmallestScreenSize | ConfigChanges.Density)]
    
  8. Voeg in de MainActivity klasse backingvelden toe om verwijzingen naar de IPushDemoNotificationActionService en IDeviceInstallationService implementaties op te slaan:

    IPushDemoNotificationActionService _notificationActionService;
    IDeviceInstallationService _deviceInstallationService;
    
  9. Voeg in de MainActivity klasse private eigenschappen NotificationActionService en DeviceInstallationService toe die hun concrete implementaties ophalen uit de afhankelijkheidsinjectiecontainer van de app.

    IPushDemoNotificationActionService NotificationActionService =>
        _notificationActionService ?? (_notificationActionService = IPlatformApplication.Current.Services.GetService<IPushDemoNotificationActionService>());
    
    IDeviceInstallationService DeviceInstallationService =>
        _deviceInstallationService ?? (_deviceInstallationService = IPlatformApplication.Current.Services.GetService<IDeviceInstallationService>());
    
  10. Implementeer in de MainActivity klasse de Android.Gms.Tasks.IOnSuccessListener interface om het Firebase-token op te halen en op te slaan:

    public class MainActivity : MauiAppCompatActivity, Android.Gms.Tasks.IOnSuccessListener
    {
        public void OnSuccess(Java.Lang.Object result)
        {
            DeviceInstallationService.Token = result.ToString();
        }
    }
    
  11. Voeg in de MainActivity klasse de ProcessNotificationActions methode toe die controleert of een bepaalde Intent waarde een extra waarde heeft met de naam actionen activeer vervolgens voorwaardelijk die action met behulp van de IPushDemoNotificationActionService implementatie:

    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. Overschrijf in de MainActivity klasse de OnNewIntent methode om de ProcessNotificationActions methode aan te roepen:

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

    Omdat de LaunchMode voor de Activity is ingesteld op SingleTop, wordt er via de OnNewIntent override een Intent naar het bestaande Activity exemplaar verzonden in plaats van de OnCreate methode. Daarom moet u een binnenkomend verzoek in zowel OnNewIntent als OnCreate afhandelen.

  13. Oversschrijf in de MainActivity-klasse de OnCreate-methode om de ProcessNotificationActions-methode aan te roepen en het token op te halen uit Firebase door MainActivity toe te voegen als IOnSuccessListener.

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

    Opmerking

    De app moet telkens opnieuw worden geregistreerd wanneer u deze uitvoert en stopt met een foutopsporingssessie om pushmeldingen te blijven ontvangen.

  14. Voeg in Visual Studio de POST_NOTIFICATIONS machtiging toe aan het AndroidManifest.xml-bestand in de map Platforms/Android :

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

    Zie voor meer informatie over deze machtiging Notification runtime-permissie op developer.android.com.

  15. Open in Visual Studio MainPage.xaml.cs en voeg de volgende code toe aan de MainPage klasse:

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

    Deze code wordt uitgevoerd op Android wanneer deze MainPage wordt weergegeven en vraagt de gebruiker om de POST_NOTIFICATIONS machtiging te verlenen. Zie Machtigingenvoor meer informatie over .NET MAUI-machtigingen.

De iOS-app configureren

De iOS-simulator ondersteunt externe meldingen in iOS 16+ wanneer deze wordt uitgevoerd op macOS 13+ op Mac-computers met Apple silicon- of T2-processors. Elke simulator genereert registratietokens die uniek zijn voor de combinatie van die simulator en de Mac-hardware waarop deze wordt uitgevoerd.

Belangrijk

De simulator ondersteunt de sandbox-omgeving van Apple Push Notification Service.

In de volgende instructies wordt ervan uitgegaan dat u hardware gebruikt die ondersteuning biedt voor het ontvangen van externe meldingen in een iOS-simulator. Als dit niet het geval is, moet u de iOS-app uitvoeren op een fysiek apparaat. Hiervoor moet u een inrichtingsprofiel maken voor uw app met de mogelijkheid voor pushmeldingen. Vervolgens moet u ervoor zorgen dat uw app is gebouwd met behulp van uw certificaat- en inrichtingsprofiel. Zie Uw iOS-app instellen voor gebruik met Azure Notification Hubs en volg de onderstaande instructies voor meer informatie over hoe u dit doet.

Uw .NET MAUI-app op iOS configureren voor het ontvangen en verwerken van pushmeldingen:

  1. Bewerk in Visual Studio het projectbestand (*.csproj) en stel het SupportedOSPlatformVersion voor iOS in op 13.0:

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

    Apple heeft wijzigingen aangebracht in hun pushservice in iOS 13. Zie Azure Notification Hubs-updates voor iOS 13 voor meer informatie.

  2. Voeg in Visual Studio een Bestand Entitlements.plist toe aan de map Platforms/iOS van het project en voeg de volgende XML toe aan het bestand:

    <?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>
    

    Hiermee stelt u het APS-omgevingsrecht in en geeft u op om de ontwikkelomgeving van de Apple Push Notification-service te gebruiken. In productie-apps moet deze rechtwaarde worden ingesteld op production. Zie APS-omgevingsrechten op developer.apple.com voor meer informatie over dit recht.

    Zie iOS-rechten voor meer informatie over het toevoegen van een rechtenbestand.

  3. Voeg in Visual Studio een nieuwe klasse toe met de naam aan DeviceInstallationService de map Platforms/iOS van het project en voeg de volgende code toe aan het bestand:

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

    Deze klasse biedt een unieke ID, met behulp van de UIDevice.IdentifierForVendor waarde en de payload van de Notification Hub-registratie.

  4. Voeg in Visual Studio een nieuwe klasse toe met de naam aan NSDataExtensions de map Platforms/iOS van het project en voeg de volgende code toe aan het bestand:

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

    De ToHexString extensiemethode wordt gebruikt door code die u toevoegt die het opgehaalde apparaattoken parseert.

  5. Open in Visual Studio het bestand AppDelegate.cs in de map Platforms/iOS en voeg de volgende using instructies toe:

    using System.Diagnostics;
    using Foundation;
    using PushNotificationsDemo.Platforms.iOS;
    using PushNotificationsDemo.Services;
    using UIKit;
    using UserNotifications;
    
  6. Voeg in de AppDelegate klasse backingvelden toe om verwijzingen naar de IPushDemoNotificationActionServiceen INotificationRegistrationServiceIDeviceInstallationService implementaties op te slaan:

    IPushDemoNotificationActionService _notificationActionService;
    INotificationRegistrationService _notificationRegistrationService;
    IDeviceInstallationService _deviceInstallationService;
    
  7. Voeg in de AppDelegate klasse de privé-eigenschappen NotificationActionService, NotificationRegistrationService, en DeviceInstallationService toe die hun concrete implementaties ophalen uit de container voor afhankelijkheidsinjectie van de app:

    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. Voeg in de AppDelegate klasse de CompleteRegistrationAsync methode toe om de IDeviceInstallationService.Token eigenschapswaarde in te stellen:

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

    Met deze methode wordt ook de registratie vernieuwd en wordt het apparaattoken in de cache opgeslagen als het apparaattoken is bijgewerkt sinds het voor het laatst is opgeslagen.

  9. Voeg in de AppDelegate klasse de ProcessNotificationActions methode voor het verwerken van de NSDictionary meldingsgegevens en het voorwaardelijk aanroepen NotificationActionService.TriggerActiontoe:

    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. Voeg in de AppDelegate klasse de RegisteredForRemoteNotifications methode toe die het deviceToken argument doorgeeft aan de CompleteRegistrationAsync methode:

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

    Deze methode wordt aangeroepen wanneer de app is geregistreerd voor het ontvangen van externe meldingen en wordt gebruikt om het unieke apparaattoken aan te vragen. Dit is in feite het adres van uw app op het apparaat.

  11. Voeg in de AppDelegate klasse de ReceivedRemoteNotification methode toe die het userInfo argument doorgeeft aan de ProcessNotificationActions methode:

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

    Deze methode wordt aangeroepen wanneer de app een externe melding heeft ontvangen en wordt gebruikt om de melding te verwerken.

  12. Voeg in de AppDelegate klasse de FailedToRegisterForRemoteNotifications methode toe om fouten te registreren:

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

    Deze methode wordt aangeroepen wanneer de app zich niet heeft geregistreerd voor het ontvangen van externe meldingen. De registratie kan mislukken als het apparaat niet is verbonden met het netwerk, als de APNS-server niet bereikbaar is of als de app onjuist is geconfigureerd.

    Opmerking

    Voor productiescenario's wilt u de juiste logboekregistratie en foutafhandeling in de FailedToRegisterForRemoteNotifications methode implementeren.

  13. Voeg in de AppDelegate klasse de FinishedLaunching methode toe om voorwaardelijk toestemming te vragen voor het gebruik van meldingen en registreren voor externe meldingen:

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

    Zie Toestemming vragen om meldingen te gebruiken op developer.apple.com voor meer informatie over het vragen van machtigingen voor het gebruik van meldingen.

Zie Gebruikersmeldingen op developer.apple.com voor informatie over meldingen in iOS.

Typen registreren bij de container voor afhankelijkheidsinjectie van de app

  1. Open in Visual Studio MauiProgram.cs en voeg een using instructie toe voor de PushNotificationsDemo.Services naamruimte:

    using PushNotificationsDemo.Services;
    
  2. Voeg in de MauiProgram klasse code toe voor de RegisterServices extensiemethode waarmee het DeviceInstallationService platform en de platformoverschrijdende PushDemoNotificationActionService services NotificationRegistrationService worden geregistreerd en waarmee een MauiAppBuilder object wordt geretourneerd:

    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. Voeg in de MauiProgram klasse code toe voor de RegisterViews extensiemethode waarmee het MainPage type wordt geregistreerd als een singleton en waarmee een MauiAppBuilder object wordt geretourneerd:

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

    Het MainPage type wordt geregistreerd omdat er een INotificationRegistrationService afhankelijkheid is vereist en alle typen waarvoor een afhankelijkheid is vereist, moeten worden geregistreerd bij de container voor afhankelijkheidsinjectie.

  4. Wijzig in de MauiProgram klasse de CreateMauiApp methode zodat deze de RegisterServices methoden en RegisterViews uitbreidingsmethoden aanroept:

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

Zie Afhankelijkheidsinjectievoor meer informatie over afhankelijkheidsinjectie in .NET MAUI.

De app testen

U kunt uw app testen door pushmeldingen naar de app te verzenden met behulp van de back-endservice of via Azure Portal.

De iOS-simulator ondersteunt externe meldingen in iOS 16+ wanneer deze wordt uitgevoerd op macOS 13+ op Mac-computers met Apple silicon- of T2-processors. Als u niet aan deze hardwarevereisten voldoet, moet u uw iOS-app testen op een fysiek apparaat. Op Android kunt u uw app testen op een door een ontwikkelaar ontgrendeld fysiek apparaat of een emulator.

Android en iOS geven pushmeldingen namens de app weer wanneer deze op de achtergrond wordt uitgevoerd. Als de app op de voorgrond wordt uitgevoerd wanneer de melding wordt ontvangen, bepaalt de code van de app het gedrag. U kunt bijvoorbeeld de interface van uw app bijwerken om nieuwe informatie in de melding weer te geven.

Testen met behulp van de back-endservice

Een testpushmelding verzenden naar uw app via de back-endservice die is gepubliceerd op Azure App Service.

  1. Voer in Visual Studio de pushNotificationsDemo-app uit op Android of iOS en selecteer de knop Registreren .

    Opmerking

    Als u test op Android, controleert u of u niet werkt met de foutopsporingsconfiguratie. Als de app eerder is geïmplementeerd, kunt u er ook voor zorgen dat de app geforceerd is gesloten en vervolgens opnieuw starten vanuit het startprogramma.

  2. Verzend in de REST-tooling van uw keuze een POST aanvraag naar het volgende adres:

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

    Zorg ervoor dat u de aanvraagheaders configureert om de sleutel apikey en de bijbehorende waarde op te nemen, de hoofdtekst in te stellen op onbewerkt en de volgende JSON-inhoud te gebruiken:

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

    De algehele aanvraag moet er ongeveer uitzien als in het volgende voorbeeld:

    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. Valideer in de REST-tooling van uw keuze of u een 200 OK-antwoord ontvangt.

  4. In de app op Android of iOS wordt een waarschuwing weergegeven met de actie ActieA die is ontvangen.

Zie HTTP-bestanden gebruiken in Visual Studio en web-API's testen met http Repl voor meer informatie over het aanroepen van REST API's. In Visual Studio Code kan REST Client worden gebruikt om REST API's te testen.

Testen met behulp van Azure Portal

Met Azure Notification Hubs kunt u controleren of uw app pushmeldingen kan ontvangen.

Een testpushmelding verzenden naar uw app via Azure Portal:

  1. Voer in Visual Studio de pushNotificationsDemo-app uit op Android of iOS en selecteer de knop Registreren .

    Opmerking

    Als u test op Android, controleert u of u niet werkt met de foutopsporingsconfiguratie. Als de app eerder is geïmplementeerd, kunt u er ook voor zorgen dat de app geforceerd is gesloten en vervolgens opnieuw starten vanuit het startprogramma.

  2. Blader in de Azure portal naar uw Notification Hub en selecteer de knop Test verzenden op de pagina Overzicht.

  3. Selecteer in de Test Verzenden blade uw vereiste Platform en wijzig de belasting.

    Gebruik voor Apple de volgende lading:

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

    Gebruik voor Android de volgende payload:

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

    De Azure-portal moet aangeven dat de melding is verzonden.

    Zie Over FCM-berichten op developer.android.com voor informatie over de berichtindeling Firebase Cloud Messaging.

  4. In de app op Android of iOS wordt een waarschuwing weergegeven met de actie ActieA die is ontvangen.

Probleemoplossingsproces

In de volgende secties worden de veelvoorkomende problemen besproken die optreden bij het gebruik van pushmeldingen in een client-app.

Geen reactie van de back-endservice

Wanneer u lokaal test, moet u ervoor zorgen dat de back-endservice wordt uitgevoerd en de juiste poort gebruikt.

Als u test op basis van de Azure API-app, controleert u of de service wordt uitgevoerd en is geïmplementeerd en zonder fouten is gestart.

Zorg ervoor dat u het basisadres correct hebt opgegeven in de REST-hulpprogramma's of in de configuratie van uw .NET MAUI-app. Het basisadres moet zijn https://<api_name>.azurewebsites.net of https://localhost:7020 bij het lokaal testen.

Een 401-statuscode ontvangen van de back-endservice

Controleer of u de apikey aanvraagheader juist instelt en of deze waarde overeenkomt met de waarde die u hebt geconfigureerd voor de back-endservice.

Als u deze fout ontvangt bij het lokaal testen, moet u ervoor zorgen dat de sleutelwaarde die u hebt gedefinieerd in uw .NET MAUI-app overeenkomt met de Authentication:ApiKey waarde van gebruikersgeheimen die wordt gebruikt door de back-endservice.

Als u test met een Azure API-app, moet u ervoor zorgen dat de sleutelwaarde die is gedefinieerd in uw .NET MAUI-app overeenkomt met de Authentication:ApiKey app-instellingswaarde die is gedefinieerd in Azure Portal. Als u deze app-instelling hebt gemaakt of gewijzigd nadat u de back-endservice hebt geïmplementeerd, moet u de service opnieuw starten om de waarde van kracht te laten worden.

Een 404-statuscode ontvangen van de back-endservice

Controleer of het eindpunt en de HTTP-aanvraagmethode juist zijn:

  • PLAATS - https://<api_name>.azurewebsites.net/api/notifications/installations
  • VERWIJDEREN - https://<api_name>.azurewebsites.net/api/notifications/installations/<installation_id>
  • VERZENDEN - https://<api_name>.azurewebsites.net/api/notifications/requests

Of wanneer u lokaal test:

  • PLAATS - https://localhost:7020/api/notifications/installations
  • VERWIJDEREN - https://localhost:7020/api/notifications/installations/<installation_id>
  • VERZENDEN - https://localhost:7020/api/notifications/requests

Belangrijk

Wanneer u het basisadres opgeeft in de .NET MAUI-app, moet u ervoor zorgen dat het eindigt met een /. Het basisadres moet zijn https://<api_name>.azurewebsites.net of https://localhost:7020/ bij het lokaal testen.

Geen meldingen ontvangen op Android na het starten of stoppen van een foutopsporingssessie

Zorg ervoor dat u zich registreert telkens wanneer u een foutopsporingssessie start. Het foutopsporingsprogramma zorgt ervoor dat er een nieuw Firebase-token wordt gegenereerd, zodat de installatie van de Notification Hub moet worden bijgewerkt.

Kan niet registreren en er wordt een notification hub-foutbericht weergegeven

Controleer of het testapparaat netwerkconnectiviteit heeft. Bepaal vervolgens de HTTP-antwoordstatuscode door een breakpoint in te stellen en de StatusCode eigenschap in de HttpResponse te inspecteren.

Bekijk de vorige suggesties voor probleemoplossing, indien van toepassing, op basis van de statuscode.

Stel een onderbrekingspunt in op de regels die specifieke statuscodes retourneren voor de respectieve API. Roep vervolgens de back-endservice aan wanneer u lokaal fouten opspoort.

Controleer of de back-endservice werkt zoals verwacht met behulp van uw gekozen REST-tool en gebruik de payload die is gemaakt door de .NET MAUI-app voor uw gekozen platform.

Bekijk de platformspecifieke configuratiesecties om ervoor te zorgen dat er geen stappen zijn gemist. Controleer of geschikte waarden worden omgezet voor InstallationId en Token variabelen voor het gekozen platform.

Kan geen ID voor het apparaat vinden vanwege een foutmelding van het apparaat.

Bekijk de platformspecifieke configuratiesecties om ervoor te zorgen dat er geen stappen zijn gemist.