Dela via


Handledning: Skicka push-meddelanden till .NET MAUI-appar med hjälp av Azure Notification Hubs via en backend-tjänst

Bläddra bland exempel. Bläddra bland exempel

Push-meddelanden levererar information från ett serverdelssystem till en klientapp. Apple, Google och andra plattformar har var och en sin egen push-meddelandetjänst (PNS). Med Azure Notification Hubs kan du centralisera meddelanden mellan plattformar så att din serverdelsapp kan kommunicera med en enda hubb, som tar hand om distribution av meddelanden till varje PNS.

Azure Notification Hubs kräver att appar registrerar sig med hubben och om du vill kan du definiera mallar och/eller prenumerera på taggar:

  • När du utför en enhetsinstallation länkas en PNS-referens till en identifierare i Azure Notification Hub. Mer information om registreringar finns i Registreringshantering.
  • Med mallar kan enheter ange parameteriserade meddelandemallar. Inkommande meddelanden kan anpassas per enhet. Mer information finns i Notification Hubs-mallar.
  • Taggar kan användas för att prenumerera på meddelandekategorier som nyheter, sport och väder. Mer information finns i Routning och tagguttryck.

I den här självstudien använder du Azure Notification Hubs för att skicka push-meddelanden till en .NET Multi-Platform App UI-app (.NET MAUI) som riktar sig till Android och iOS. En ASP.NET Core Web API-serverdel används för att hantera enhetsregistrering för klienten och för att initiera ett push-meddelande. Dessa åtgärder hanteras med hjälp av Microsoft.Azure.NotificationHubs NuGet-paketet. Mer information om den övergripande metoden finns i Registreringshantering från en backend.

I den här handledningen:

  • Konfigurera push-meddelandetjänster och Azure Notification Hub.
  • Skapa en ASP.NET Core WebAPI-serverdelsapp.
  • Skapa en .NET MAUI-app.
  • Konfigurera Android-appen för push-meddelanden.
  • Konfigurera iOS-appen för push-meddelanden.
  • Testa appen.
  • Felsöka eventuella konfigurationsproblem.

Förutsättningar

För att slutföra den här självstudien behöver du:

  • Ett Azure-konto med en aktiv prenumeration.
  • En PC eller Mac som kör den senaste versionen av Visual Studio/Visual Studio Code med arbetsbelastningen för .NET Multi-platform App UI-utveckling och arbetsbelastningarna för ASP.NET och webbapplikationsutveckling installerade.

För Android måste du ha:

  • En utvecklare har låst upp en fysisk enhet eller en emulator som kör API 26+ med Google Play Services installerat.

För iOS måste du ha:

  • Ett aktivt Apple-utvecklarkonto.
  • En Mac som kör Xcode, tillsammans med ett giltigt utvecklarcertifikat installerat i nyckelringen.

Sedan bör du på iOS antingen ha:

  • En iOS 16+ simulator som körs i macOS 13+ på Mac-datorer med Apple-kisel- eller T2-processorer.

    ELLER

  • En fysisk iOS-enhet som är registrerad på ditt utvecklarkonto (kör iOS 13.0+).

  • Din fysiska enhet som är registrerad på ditt Apple-utvecklarkonto och som är associerad med ditt certifikat.

Viktig

iOS-simulatorn stöder fjärrmeddelanden i iOS 16+ när den körs i macOS 13+ på Mac-datorer med Apple-kisel- eller T2-processorer. Om du inte uppfyller dessa maskinvarukrav behöver du ett aktivt Apple-utvecklarkonto och en fysisk enhet.

Om du vill följa den här handledningen bör du känna till:

Den här självstudien är avsedd för Visual Studio, men den kan följas med hjälp av Visual Studio Code på en PC eller Mac. Det kommer dock att finnas vissa skillnader som behöver förenas. Till exempel beskrivningar av användargränssnitt och arbetsflöden, mallnamn och miljökonfiguration.

Konfigurera push-meddelandetjänster och Azure Notification Hub

I det här avsnittet konfigurerar du Firebase Cloud Messaging och Apple Push Notification Services (APNS). Sedan skapar och konfigurerar du en Azure Notification Hub- så att den fungerar med dessa tjänster.

Skapa ett Firebase-projekt

Så här skapar du ett Firebase-projekt:

  1. Logga in på Firebase-konsolen i en webbläsare.

  2. I Firebase-konsolen väljer du knappen Lägg till projekt och skapar ett nytt Firebase-projekt och anger PushDemo- som Projektnamn.

    Not

    Ett unikt namn genereras åt dig. Som standard består detta av en gemen variant av namnet du angav plus ett genererat tal som avgränsas med ett bindestreck. Du kan ändra detta om du vill, förutsatt att dina redigeringar fortfarande är globalt unika.

  3. När projektet har skapats väljer du Android-logotypen för att lägga till Firebase i en Android-app:

    Skärmbild av att lägga till Firebase i en Android-app i Firebase Cloud Messaging-konsolen.

  4. På sidan Lägg till Firebase i din Android-app anger du ett namn för ditt paket, valfritt ett appnamn och väljer knappen Registrera app:

    Skärmbild av registrering av din Android-app med Firebase.

  5. På sidan Lägg till Firebase i din Android-app väljer du knappen Ladda ned google-services.json och sparar filen i en lokal mapp innan du väljer knappen Nästa:

    Skärmbild av nedladdning av JSON-filen för Google Services.

  6. På sidan Lägg till Firebase i din Android-app väljer du knappen Nästa.

  7. På sidan Lägg till Firebase i din Android-app väljer du knappen Fortsätt till konsolen.

  8. I Firebase-konsolen väljer du ikonen Projektöversikt och väljer sedan Project-inställningar:

    Skärmbild av att välja projektinställningarna i Firebase Cloud Messaging-konsolen.

  9. I Project-inställningarväljer du fliken Cloud Messaging. Du ser att Firebase Cloud Messaging API (V1) är aktiverat:

    Skärmbild som bekräftar att Firebase Cloud Messaging V1 är aktiverat.

  10. I Project-inställningarnaväljer du fliken Tjänstkonton och väljer sedan knappen Generera ny privat nyckel.

  11. I dialogrutan Generera ny privat nyckel väljer du knappen Generera nyckel:

    Skärmbild av hur du genererar en ny privat nyckel i Firebase Cloud Messaging-konsolen.

    En JSON-fil laddas ned, som innehåller värden som du anger i Azure Notification Hub.

Registrera din iOS-app för push-meddelanden

Om du vill skicka push-meddelanden till en iOS-app måste du registrera din app med Apple och registrera dig för push-meddelanden. Detta kan du göra genom att utföra stegen i följande Dokumentation om Azure Notification Hub:

Om du vill ta emot push-meddelanden på en fysisk enhet måste du också skapa en distributionsprofil.

Viktig

Om du vill ta emot bakgrundsmeddelanden i iOS måste du lägga till bakgrundsläget för fjärrmeddelanden i appen. Mer information finns i Aktivera funktionen för fjärrmeddelanden på developer.apple.com.

Skapa en Azure Notification Hub

Så här skapar du en meddelandehubb i Azure-portalen:

  1. Logga in på Azure-portalen i en webbläsare.
  2. I Azure-portalen klickar du på knappen Skapa en resurs och söker sedan efter och väljer Notification Hub innan du väljer knappen Skapa.
  3. Utför följande steg på sidan Notification Hub:
    1. I fältet Prenumeration väljer du namnet på den Azure-prenumeration som du vill använda och väljer sedan en befintlig resursgrupp eller skapar en ny.

    2. I fältet Namnområdesinformation anger du ett unikt namn för det nya namnområdet.

    3. I fältet Notification Hub Details anger du ett namn för meddelandehubben. Detta krävs eftersom ett namnområde innehåller en eller flera meddelandehubbar.

    4. I listrutan Plats väljer du ett värde som anger den plats där du vill skapa meddelandehubben.

    5. Granska alternativet tillgänglighetszoner. Om du väljer en region som har tillgänglighetszoner är kryssrutan markerad som standard.

      Notis

      Tillgänglighetszoner är en betald funktion, så en extra avgift läggs till på din nivå.

    6. Välj ett katastrofåterställningsalternativ: ingen, parerad återställningsregion eller flexibel återställningsregion. Om du väljer parkopplad återställningsregionvisas failoverregionen. Om du väljer flexibel återställningsregionanvänder du listrutan för att välja från en lista över återställningsregioner.

    7. Välj knappen Skapa. Meddelandehubben skapas.

  4. I Azure-portalen bläddrar du till din nyligen skapade meddelandehubb och sedan till bladet Hantera > åtkomstprinciper.
  5. Anteckna anslutningssträngen för policyn DefaultFullSharedAccessSignature i bladet Åtkomstprinciper. Du behöver detta senare när du skapar en serverdelstjänst som kommunicerar med din meddelandehubb.

Mer information om hur du skapar en meddelandehubb finns i Skapa en Azure-meddelandehubb i Azure-portalen.

Konfigurera Firebase Cloud Messaging i meddelandehubben

Så här konfigurerar du meddelandehubben så att den kommunicerar med Firebase Cloud Messaging:

  1. I Azure-portalenbläddrar du till meddelandehubben och väljer bladet Inställningar > Google (FCM v1).

  2. På bladet Google (FCM v1) anger du värden för fälten Private Key, Client Emailoch Project ID. Dessa värden finns i JSON-filen med privat nyckel som du laddade ned från Firebase Cloud Messaging:

    Azure-fält JSON-nyckel JSON-värdeexempel
    Privat nyckel private_key Det här värdet bör börja med -----BEGIN PRIVATE KEY-----\n och sluta med -----END PRIVATE KEY-----\n.
    E-post för klient client_email firebase-adminsdk-55sfg@pushdemo-d6ab2.iam.gserviceaccount.com
    Projekt-ID project_id pushdemo-d6ab2
  3. I bladet Google (FCM v1) väljer du knappen Spara.

Konfigurera Apple Push Notification Service i meddelandehubben

I Azure-portalenbläddrar du till meddelandehubben och väljer bladet Inställningar > Apple (APNS). Följ sedan lämpliga steg baserat på den metod du valde tidigare när du skapade ett certifikat för meddelandehubben.

Viktig

När du anger programlägeväljer du bara Production om du vill skicka push-meddelanden till användare som har köpt din app från butiken.

Alternativ 1 – Använd ett .p12-pushcertifikat

  1. På bladet Apple (APNS) väljer du autentiseringsläget Certifikat.
  2. I bladet Apple (APNS) väljer du fil-ikonen bredvid fältet Ladda upp certifikat. Välj sedan den .p12-fil som du exporterade tidigare och ladda upp den.
  3. På bladet Apple (APNS) anger du certifikatlösenordet i fältet Lösenord om det behövs.
  4. På bladet Apple (APNS) väljer du Sandbox- applikationsläge.
  5. På bladet Apple (APNS) väljer du knappen Spara.

Alternativ 2 – Använda tokenbaserad autentisering

  1. På bladet Apple (APNS) väljer du Token autentiseringsmetod.
  2. På bladet Apple (APNS) anger du de värden som du tidigare skaffade för fälten Key ID, Bundle ID, Team IDoch Token.
  3. På bladet Apple (APNS) väljer du Sandbox- applikationsläge.
  4. På bladet Apple (APNS) väljer du knappen Spara.

Skapa en ASP.NET Core Web API-serverdelsapp

I det här avsnittet skapar du en ASP.NET Core Web API-serverdel för att hantera enhetsinstallation och skicka meddelanden till .NET MAUI-appen.

Skapa ett webb-API-projekt

Så här skapar du ett webb-API-projekt:

  1. Skapa ett ASP.NET Core Web API- projekt i Visual Studio:

    Skärmbild av hur du skapar ett nytt ASP.NET Core Web API-projekt i Visual Studio.

  2. I dialogrutan Konfigurera ditt nya projekt namnger du projektet PushNotificationsAPI.

  3. I dialogrutan Ytterligare information kontrollerar du att kryssrutorna Configure for HTTPS and Use controllers är aktiverade:

    Skärmbild av hur du konfigurerar ASP.NET Core Web API-projektet i Visual Studio.

  4. När projektet har skapats trycker du på F5 för att köra projektet.

    Appen är för närvarande konfigurerad att använda WeatherForecastController som launchUrl, som anges i Properties\launchSettings.jspå-filen. Appen startas i en webbläsare och visar vissa JSON-data.

    Viktig

    När du kör ett ASP.NET Core-projekt som använder HTTPS identifierar Visual Studio om ASP.NET Core HTTPS-utvecklingscertifikatet är installerat i ditt lokala användarcertifikatarkiv och erbjuder att installera det och lita på det om det saknas.

  5. Stäng webbläsaren.

  6. I Solution Explorerexpanderar du mappen Controllers och tar bort WeatherForecastController.cs.

  7. I Solution Exploreri roten av projektet tar du bort WeatherForecast.cs.

  8. Öppna ett kommandofönster och navigera till katalogen som innehåller projektfilen. Kör sedan följande kommandon:

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

    Ersätt platshållarvärdena med ditt eget Azure Notification Hub-namn och anslutningssträngsvärden. Dessa finns på följande platser i Azure Notification Hub:

    Konfigurationsvärde Plats
    NotificationHub:Name Se Namn i Essentials-sammanfattningen överst på Översikt-sidan .
    NotificationHub:ConnectionString Se DefaultFullSharedAccessSignature* på sidan Åtkomstprinciper.

    Detta konfigurerar lokala konfigurationsvärden med hjälp av verktyget Secret Manager. Detta frikopplar dina Azure Notification Hub-hemligheter från Visual Studio-lösningen för att säkerställa att de inte hamnar i källkontrollen.

    Tips

    För produktionsscenarier bör du överväga en tjänst som Azure KeyVault för att lagra anslutningssträngen på ett säkert sätt.

Autentisera klienter med en API-nyckel

Så här autentiserar du klienter med en API-nyckel:

  1. Öppna ett kommandofönster och navigera till katalogen som innehåller projektfilen. Kör sedan följande kommandon:

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

    Ersätt platshållarvärdet med din API-nyckel, vilket kan vara valfritt värde.

  2. I Visual Studio lägger du till en ny mapp med namnet Authentication i projektet och lägger sedan till en ny klass med namnet ApiKeyAuthOptions i mappen Authentication och ersätter koden med följande kod:

    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. I Visual Studio lägger du till en ny klass med namnet ApiKeyAuthHandler i mappen Authentication och ersätter koden med följande kod:

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

    En autentiseringshanterare är en typ som implementerar beteendet för ett schema, vilket i det här fallet är ett anpassat API-nyckelschema.

  4. I Visual Studio lägger du till en ny klass med namnet AuthenticationBuilderExtensions i mappen Authentication och ersätter koden med följande kod:

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

    Den här tilläggsmetoden används för att förenkla konfigurationskoden för mellanprogram i Program.cs.

  5. I Visual Studio öppnar du Program.cs och uppdaterar koden för att konfigurera API-nyckelautentiseringen under anropet till metoden builder.Services.AddControllers:

    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. I Program.csuppdaterar du koden under kommentaren // Configure the HTTP request pipeline för att anropa metoderna UseRouting, UseAuthenticationoch MapControllers tillägg:

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

    Metoden UseAuthentication tillägg registrerar mellanprogrammet som använder det tidigare registrerade autentiseringsschemat. UseAuthentication måste anropas innan mellanprogram som är beroende av att användare autentiseras.

    Not

    Även om en API-nyckel inte är lika säker som en token, kommer den att räcka för den här självstudien och kan enkelt konfigureras via ASP.NET Middleware.

Lägga till och konfigurera tjänster

Så här lägger du till och konfigurerar tjänster i din webb-API-serverdelsapp:

  1. I Visual Studio lägger du till Microsoft.Azure.NotificationHubs NuGet-paketet i projektet. Det här NuGet-paketet används för att komma åt din meddelandehubb, inkapslad i en tjänst.

  2. I Visual Studio lägger du till en ny mapp med namnet Models i projektet och lägger sedan till en ny klass med namnet PushTemplates i mappen Models och ersätter koden med följande kod:

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

    Klassen PushTemplates innehåller tokeniserade meddelandenyttolaster för allmänna och tysta push-meddelanden. Dessa nyttolaster definieras utanför installation för att tillåta experimentering utan att behöva uppdatera befintliga installationer via tjänsten. Att hantera ändringar av installationer på det här sättet ligger utanför omfånget för den här artikeln. I produktscenarier bör du överväga att använda anpassade mallar.

  3. I Visual Studio lägger du till en ny klass med namnet DeviceInstallation i mappen Models och ersätter koden med följande kod:

    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. I Visual Studio lägger du till en ny klass med namnet NotificationRequest i mappen Models och ersätter koden med följande kod:

    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. I Visual Studio lägger du till en ny klass med namnet NotificationHubOptions i mappen Models och ersätter koden med följande kod:

    using System.ComponentModel.DataAnnotations;
    
    namespace PushNotificationsAPI.Models;
    
    public class NotificationHubOptions
    {
        [Required]
        public string Name { get; set; }
    
        [Required]
        public string ConnectionString { get; set; }
    }
    
  6. I Visual Studio lägger du till en ny mapp med namnet Services i projektet och lägger sedan till ett nytt gränssnitt med namnet INotificationService i mappen Services och ersätter koden med följande kod:

    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. I Visual Studio lägger du till en ny klass med namnet NotificationHubService i mappen Services och ersätter koden med följande kod:

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

    Tagguttrycket som tillhandahålls till metoden SendTemplateNotificationsAsync är begränsat till 20 taggar om de bara innehåller ORs. Annars är de begränsade till 6 taggar. Mer information finns i Rutthantering och tagguttryck.

  8. I Visual Studio öppnar du Program.cs och uppdaterar koden för att lägga till NotificationHubService som en singleton-implementering av INotificationService under anropet till metoden 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();
    

Skapa REST-API:t för notifikationer

Så här skapar du REST-API:et för meddelanden:

  1. I Visual Studio lägger du till en ny Controller med namnet NotificationsController i mappen Controllers.

    Tips

    Välj API-styrenheten med mall för läs-/skrivåtgärder.

  2. I filen NotificationsController.cs lägger du till följande using-instruktioner överst i filen:

    using System.ComponentModel.DataAnnotations;
    using System.Net;
    using Microsoft.AspNetCore.Authorization;
    using Microsoft.AspNetCore.Mvc;
    using PushNotificationsAPI.Models;
    using PushNotificationsAPI.Services;
    
  3. I filen NotificationsController.cs lägger du till attributet Authorize i klassen NotificationsController:

    [Authorize]
    [ApiController]
    [Route("api/[controller]")]
    public class NotificationsController : ControllerBase
    
  4. I filen NotificationsController.cs uppdaterar du NotificationsContoller konstruktorn för att acceptera den registrerade instansen av INotificationService som ett argument och tilldelar den till en readonly-medlem:

    readonly INotificationService _notificationService;
    
    public NotificationsController(INotificationService notificationService)
    {
        _notificationService = notificationService;
    }
    
  5. I filen NotificationsContoller.cs ersätter du alla metoder med följande kod:

    [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. I filen Egenskaper/launchSettings.json ändrar du egenskapen launchUrl för varje profil från weatherforecast till api/notifications.

Skapa en API-app

Nu ska du skapa en API-app i Azure App Service- som värd för serverdelstjänsten. Detta kan göras direkt från Visual Studio eller Visual Studio Code, med Azure CLI, Azure PowerShell, Azure Developer CLI och via Azure Portal. Mer information finns i Publicera din webbapp.

Så här skapar du en API-app i Azure-portalen:

  1. Logga in på Azure-portalen i en webbläsare.

  2. I Azure-portalen klickar du på knappen Skapa en resurs och söker sedan efter och väljer API App innan du väljer knappen Skapa.

  3. På sidan Skapa API App uppdaterar du följande fält innan du väljer knappen Skapa:

    Fält Handling
    Abonnemang Välj samma målprenumeration som du skapade meddelandehubben i.
    Resursgrupp Välj samma resursgrupp som du skapade meddelandehubben i.
    Namn Ange ett globalt unikt namn.
    Körningsstack Kontrollera att den senaste versionen av .NET är markerad.
  4. När API App har etablerats, navigerar du till resursen.

  5. Anteckna standarddomänvärdet på sidan Översikt. Den här URL:en är din serverdelsslutpunkt som ska användas från .NET MAUI-appen. URL:en använder det API-appnamn som du angav, med formatet https://<app_name>.azurewebsites.net.

  6. I Azure-portalen bläddrar du till bladet Inställningar > Miljö och kontrollerar sedan att fliken Appinställningar är markerad. Använd sedan knappen Lägg till för att lägga till följande inställningar:

    Namn Värde
    Autentisering:ApiKey <api_key_value>
    NotificationHub:Name <hub_name_value>
    NotificationHub:ConnectionString <hub_connection_string_value>

    Viktig

    Den Authentication:ApiKey programinställningen har lagts till för enkelhetens skull. För produktionsscenarier bör du överväga en tjänst som Azure KeyVault för att lagra anslutningssträngen på ett säkert sätt.

    När alla dessa inställningar har angetts väljer du knappen Använd och sedan knappen Bekräfta.

Publicera serverdelstjänsten

Så här publicerar du serverdelstjänsten till Azure App Service:

  1. Högerklicka på projektet i Visual Studio och välj Publicera.
  2. I Publicera-guiden väljer du Azure och trycker sedan på knappen Nästa.
  3. I guiden Publicera väljer du Azure App Service (Windows) och sedan knappen Nästa.
  4. I guiden Publicera följer du autentiseringsflödet för att ansluta Visual Studio till din Azure-prenumeration och publicera appen.

Visual Studio skapar, paketerar och publicerar appen till Azure och startar sedan appen i din standardwebbläsare. Mer information finns i Publicera en ASP.NET-webbapp.

Tips

Du kan ladda ned en publiceringsprofil för din app från bladet Översikt api-appen i Azure-portalen och sedan använda profilen i Visual Studio för att publicera din app.

Verifiera det publicerade API:et

Om du vill kontrollera att API-appen har publicerats korrekt bör du använda valfri REST-verktyg för att skicka en POST begäran till följande adress:

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

Not

Basadressen är https://<app_name>.azurewebsites.net.

Se till att du konfigurerar begäranderubrikerna så att de innehåller nyckeln apikey och dess värde, ange brödtexten till rå och använd följande platshållar-JSON-innehåll:

{}

Du bör få ett 400 Bad Request-svar från tjänsten.

Not

Det går ännu inte att testa API:et med giltiga begärandedata eftersom detta kräver plattformsspecifik information från .NET MAUI-appen.

Mer information om hur du anropar REST-API:er finns i Använda .http-filer i Visual Studio och Testa webb-API:er med Http Repl-. I Visual Studio Code kan REST-klient användas för att testa REST-API:er.

Skapa en .NET MAUI-app

I det här avsnittet skapar du en .NET Multi-Platform App UI-app (.NET MAUI) som gör att du kan registrera dig för att ta emot push-meddelanden från en meddelandehubb via serverdelstjänsten och avregistrera dig.

Så här skapar du .NET MAUI-appen:

  1. I Visual Studio skapar du en ny .NET MAUI-app med namnet PushNotificationsDemomed hjälp av projektmallen .NET MAUI App.

  2. I Visual Studio lägger du till en ny mapp med namnet Models i .NET MAUI-projektet och lägger sedan till en ny klass med namnet DeviceInstallation i mappen Models och ersätter koden med följande kod:

    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. I Visual Studio lägger du till en uppräkning med namnet PushDemoAction i mappen Models och ersätter koden med följande kod:

    namespace PushNotificationsDemo.Models;
    
    public enum PushDemoAction
    {
        ActionA,
        ActionB
    }
    
  4. I Visual Studio lägger du till en ny mapp med namnet Services till .NET MAUI-projektet och lägger sedan till ett nytt gränssnitt med namnet IDeviceInstallationService till mappen Services och ersätter koden med följande kod:

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

    Det här gränssnittet kommer att implementeras på varje plattform vid ett senare tillfälle för att förse den DeviceInstallation-information som krävs av backendtjänsten.

  5. I Visual Studio lägger du till ett gränssnitt med namnet INotificationRegistrationService i mappen Services och ersätter koden med följande kod:

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

    Det här gränssnittet hanterar interaktionen mellan klienten och serverdelstjänsten.

  6. I Visual Studio lägger du till ett gränssnitt med namnet INotificationActionService i mappen Services och ersätter koden med följande kod:

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

    Det här gränssnittet används som en enkel mekanism för att centralisera hanteringen av meddelandeåtgärder.

  7. I Visual Studio lägger du till ett gränssnitt med namnet IPushDemoNotificationActionService i mappen Services och ersätter koden med följande kod:

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

    Den IPushDemoNotificationActionService typen är specifik för den här appen och använder PushDemoAction uppräkning för att identifiera den åtgärd som utlöses med hjälp av en starkt typad metod.

  8. I Visual Studio lägger du till en klass med namnet NotificationRegistrationService i mappen Services och ersätter koden med följande kod:

    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. I Visual Studio lägger du till en klass med namnet PushDemoNotificationActionService i mappen Services och ersätter koden med följande kod:

    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. I Visual Studio lägger du till en klass med namnet Config i projektets rot och ersätter koden med följande kod:

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

    Klassen Config används som ett enkelt sätt att hålla hemligheterna borta från källkontrollen. Du kan ersätta dessa värden som en del av en automatiserad version eller åsidosätta dem med hjälp av en lokal partiell klass.

    Viktig

    När du anger basadressen i .NET MAUI-appen ska du se till att den slutar med en /.

  11. I Visual Studio lägger du till en klass med namnet Config.local_secrets i projektets rot. Ersätt sedan koden i filen Config.local_secrets.cs med följande kod:

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

    Ersätt platshållarvärdena med de värden du valde när du skapade serverdelstjänsten. URL:en för BackendServiceEndpoint ska använda formatet https://<api_app_name>.azurewebsites.net/.

    Tips

    Kom ihåg att lägga till *.local_secrets.* i din .gitignore-fil för att undvika att infoga filen i versionshantering.

Skapa användargränssnittet

Så här skapar du appens användargränssnitt:

  1. Öppna MainPage.xaml i Visual Studio och ersätt VerticalStackLayout och dess underordnade med följande XAML:

    <VerticalStackLayout Margin="20"
                         Spacing="6">
        <Button x:Name="registerButton"
                Text="Register"
                Clicked="OnRegisterButtonClicked" />
        <Button x:Name="deregisterButton"
                Text="Deregister"
                Clicked="OnDeregisterButtonClicked" />
    </VerticalStackLayout>
    
  2. Öppna MainPage.xaml.cs i Visual Studio och lägg till en using-instruktion för PushNotificationsDemo.Services-namnområdet:

    using PushNotificationsDemo.Services;
    
  3. I MainPage.xaml.cslägger du till ett readonly bakgrundsfält för att lagra en referens till implementeringen av INotificationRegistrationService:

    readonly INotificationRegistrationService _notificationRegistrationService;
    
  4. I MainPage konstruktorn löser du implementeringen av INotificationRegistrationService och tilldelar den till _notificationRegistrationService-bakgrundsfältet:

    public MainPage(INotificationRegistrationService service)
    {
        InitializeComponent();
    
        _notificationRegistrationService = service;
    }
    
  5. I klassen MainPage implementerar du händelsehanterarna OnRegisterButtonClicked och OnDeregisterButtonClicked och anropar motsvarande register- och avregistermetoder för INotificationRegistrationService-objektet:

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

    Viktig

    I appen utförs registrering och avregistrering som svar på användarindata så att den här funktionen kan utforskas och testas enklare. I en produktionsapp utför du vanligtvis registrerings- och avregistreringsåtgärderna under lämplig punkt i appens livscykel, utan att uttryckligen behöva användarindata.

  6. Öppna App.xaml.cs i Visual Studio och lägg till följande using-instruktioner:

    using PushNotificationsDemo.Models;
    using PushNotificationsDemo.Services;
    
  7. I App.xaml.cslägger du till ett readonly-bakgrundsfält för att lagra en referens till IPushDemoNotificationActionService-implementeringen:

    readonly IPushDemoNotificationActionService _actionService;
    
  1. I konstruktor för App ska du lösa implementeringen av IPushDemoNotificationActionService, tilldela den till det bakomliggande fältet _actionService och prenumerera på händelsen IPushDemoNotificationActionService.ActionTriggered.

    public App(IPushDemoNotificationActionService service)
    {
        InitializeComponent();
    
        _actionService = service;
        _actionService.ActionTriggered += NotificationActionTriggered;
    
        MainPage = new AppShell();
    }
    
  1. I App konstruktorn löser du implementeringen av IPushDemoNotificationActionService och tilldelar den till _actionService-säkerhetskopieringsfältet och prenumererar på händelsen IPushDemoNotificationActionService.ActionTriggered:

    public App(IPushDemoNotificationActionService service)
    {
        InitializeComponent();
    
        _actionService = service;
        _actionService.ActionTriggered += NotificationActionTriggered;
    }
    
  1. I klassen App implementerar du händelsehanteraren för den IPushDemoNotificationActionService.ActionTriggered händelsen:

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

    Händelsehanteraren för den ActionTriggered händelsen visar mottagandet och spridningen av push-meddelandeåtgärder. Dessa skulle vanligtvis hanteras tyst, till exempel navigera till en viss vy eller uppdatera vissa data i stället för att visa en avisering.

Konfigurera Android-appen

Så här konfigurerar du .NET MAUI-appen på Android för att ta emot och bearbeta push-meddelanden:

  1. I Visual Studio lägger du till Xamarin.Firebase.Messaging- NuGet-paketet i ditt .NET MAUI-appprojekt.

  2. I Visual Studio lägger du till din google-services.json-fil i mappen Platforms/Android i ditt .NET MAUI-appprojekt. När filen har lagts till i projektet bör den ha lagts till med en byggåtgärd av GoogleServicesJson:

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

    Tips

    Kom ihåg att lägga till google-services.json i din .gitignore-fil för att undvika att spara filen i versionskontroll.

  3. I Visual Studio redigerar du projektfilen (*.csproj) och anger SupportedOSPlatformVersion för Android till 26.0:

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

    Google har gjort ändringar i Android-meddelandekanaler i API 26. Mer information finns i Meddelandekanaler på developer.android.com.

  4. I mappen Platforms/Android i projektet lägger du till en ny klass med namnet DeviceInstallationService och ersätter koden med följande kod:

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

    Den här klassen tilldelar ett unikt ID med värdet Secure.AndroidId och hanterar nyttolasten för registreringen av meddelandehubben.

  5. I mappen Platforms/Android i projektet lägger du till en ny klass med namnet PushNotificationFirebaseMessagingService och ersätter koden med följande kod:

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

    Den här klassen har ett IntentFilter attribut som innehåller com.google.firebase.MESSAGING_EVENT-filtret. Det här filtret gör att Android kan skicka inkommande meddelanden till den här klassen för bearbetning.

    Information om meddelandeformatet Firebase Cloud Messaging finns i Om FCM-meddelanden på developer.android.com.

  6. I Visual Studio öppnar du filen MainActivity.cs i mappen Platforms/Android och lägger till följande using-instruktioner:

    using Android.App;
    using Android.Content;
    using Android.Content.PM;
    using Android.OS;
    using PushNotificationsDemo.Services;
    using Firebase.Messaging;
    
  7. I klassen MainActivity anger du LaunchMode till SingleTop så att MainActivity inte skapas igen när den öppnas:

    [Activity(
        Theme = "@style/Maui.SplashTheme",
        MainLauncher = true,
        LaunchMode = LaunchMode.SingleTop,
        ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation | ConfigChanges.UiMode | ConfigChanges.ScreenLayout | ConfigChanges.SmallestScreenSize | ConfigChanges.Density)]
    
  8. I klassen MainActivity lägger du till bakgrundsfält för att lagra referenser till implementeringarna IPushDemoNotificationActionService och IDeviceInstallationService:

    IPushDemoNotificationActionService _notificationActionService;
    IDeviceInstallationService _deviceInstallationService;
    
  9. I klassen MainActivity lägger du till NotificationActionService och DeviceInstallationService privata egenskaper som hämtar deras konkreta implementeringar från appens container för beroendeinmatning:

    IPushDemoNotificationActionService NotificationActionService =>
        _notificationActionService ?? (_notificationActionService = IPlatformApplication.Current.Services.GetService<IPushDemoNotificationActionService>());
    
    IDeviceInstallationService DeviceInstallationService =>
        _deviceInstallationService ?? (_deviceInstallationService = IPlatformApplication.Current.Services.GetService<IDeviceInstallationService>());
    
  10. I klassen MainActivity implementerar du Android.Gms.Tasks.IOnSuccessListener-gränssnittet för att hämta och lagra Firebase-token:

    public class MainActivity : MauiAppCompatActivity, Android.Gms.Tasks.IOnSuccessListener
    {
        public void OnSuccess(Java.Lang.Object result)
        {
            DeviceInstallationService.Token = result.ToString();
        }
    }
    
  11. I klassen MainActivity lägger du till metoden ProcessNotificationActions som kontrollerar om en viss Intent har ett extra värde med namnet actionoch sedan villkorligt utlöser den action med hjälp av IPushDemoNotificationActionService implementering:

    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. I klassen MainActivity åsidosätter du metoden OnNewIntent för att anropa metoden ProcessNotificationActions:

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

    Eftersom LaunchMode för Activity är inställd på SingleTopskickas en Intent till den befintliga Activity-instansen via OnNewIntent överskridande, snarare än metoden OnCreate. Därför måste du hantera en inkommande intent i både OnNewIntent och OnCreate.

  13. I klassen MainActivity åsidosätter du metoden OnCreate för att anropa metoden ProcessNotificationActions och för att hämta token från Firebase lägger du till MainActivity som IOnSuccessListener:

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

    Not

    Appen måste registreras igen varje gång du kör den och stoppa den från en felsökningssession för att fortsätta ta emot push-meddelanden.

  14. I Visual Studio lägger du till behörigheten POST_NOTIFICATIONS i filen AndroidManifest.xml i mappen Platforms/Android:

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

    Mer information om den här behörigheten finns i Meddelandekörningsbehörighet på developer.android.com.

  15. Öppna MainPage.xaml.cs i Visual Studio och lägg till följande kod i klassen MainPage:

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

    Den här koden körs på Android när MainPage visas och begär att användaren beviljar POST_NOTIFICATIONS behörighet. Mer information om .NET MAUI-behörigheter finns i Behörigheter.

Konfigurera iOS-appen

iOS-simulatorn stöder fjärrmeddelanden i iOS 16+ när den körs i macOS 13+ på Mac-datorer med Apple-kisel- eller T2-processorer. Varje simulator genererar registreringstoken som är unika för kombinationen av simulatorn och den Mac-maskinvara som den körs på.

Viktig

Simulatorn stöder sandbox-miljön för Apple Push Notification Service.

Följande instruktioner förutsätter att du använder maskinvara som har stöd för att ta emot fjärrmeddelanden i en iOS-simulator. Om så inte är fallet måste du köra iOS-appen på en fysisk enhet, vilket kräver att du skapar en etableringsprofil för din app som innehåller funktionen Push-meddelanden. Sedan måste du se till att din app byggs med hjälp av ditt certifikat och din provisioningprofil. Mer information om hur du gör detta finns i Konfigurera din iOS-app så att den fungerar med Azure Notification Hubsoch följ sedan anvisningarna nedan.

Så här konfigurerar du .NET MAUI-appen på iOS för att ta emot och bearbeta push-meddelanden:

  1. I Visual Studio redigerar du projektfilen (*.csproj) och anger SupportedOSPlatformVersion för iOS till 13.0:

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

    Apple gjorde ändringar i sin push-tjänst i iOS 13. Mer information finns i Azure Notification Hubs-uppdateringar för iOS 13.

  2. I Visual Studio lägger du till en Entitlements.plist--fil i mappen Platforms/iOS i projektet och lägger till följande XML i filen:

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

    Detta anger berättigande för APS-miljön och anger att du ska använda utvecklingsmiljön för Apple Push Notification Service. I produktionsappar ska det här berättigandevärdet anges till production. Mer information om den här behörigheten finns i APS-miljörättigheter på developer.apple.com.

    Mer information om hur du lägger till en rättighetsfil finns i iOS-berättiganden.

  3. I Visual Studio lägger du till en ny klass med namnet DeviceInstallationService i mappen Platforms/iOS i projektet och lägger till följande kod i filen:

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

    Den här klassen tillhandahåller ett unikt ID med värdet UIDevice.IdentifierForVendor och nyttolast för registreringen av meddelandehubben.

  4. I Visual Studio lägger du till en ny klass med namnet NSDataExtensions i mappen Platforms/iOS i projektet och lägger till följande kod i filen:

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

    Utökningsmetoden ToHexString kommer att användas av den kod som du lägger till för att parsa den hämtade enhetstoken.

  5. I Visual Studio öppnar du filen AppDelegate.cs i mappen Platforms/iOS och lägger till följande using-instruktioner:

    using System.Diagnostics;
    using Foundation;
    using PushNotificationsDemo.Platforms.iOS;
    using PushNotificationsDemo.Services;
    using UIKit;
    using UserNotifications;
    
  6. I klassen AppDelegate lägger du till bakgrundsfält för att lagra referenser till implementeringarna IPushDemoNotificationActionService, INotificationRegistrationServiceoch IDeviceInstallationService:

    IPushDemoNotificationActionService _notificationActionService;
    INotificationRegistrationService _notificationRegistrationService;
    IDeviceInstallationService _deviceInstallationService;
    
  7. I klassen AppDelegate lägger du till NotificationActionService, NotificationRegistrationServiceoch DeviceInstallationService privata egenskaper som hämtar sina konkreta implementeringar från appens container för beroendeinmatning:

    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. I klassen AppDelegate lägger du till metoden CompleteRegistrationAsync för att ange egenskapsvärdet IDeviceInstallationService.Token:

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

    Den här metoden uppdaterar också registreringen och cachelagrar enhetstoken om den har uppdaterats sedan den senast lagrades.

  9. I klassen AppDelegate lägger du till ProcessNotificationActions-metoden för bearbetning av NSDictionary-meddelandedata och anropar villkorligt 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. I klassen AppDelegate lägger du till metoden RegisteredForRemoteNotifications som skickar argumentet deviceToken till metoden CompleteRegistrationAsync:

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

    Den här metoden anropas när appen är registrerad för att ta emot fjärrmeddelanden och används för att begära den unika enhetstoken, som i praktiken är adressen till din app på enheten.

  11. I klassen AppDelegate lägger du till metoden ReceivedRemoteNotification som skickar argumentet userInfo till metoden ProcessNotificationActions:

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

    Den här metoden anropas när appen har tagit emot ett fjärrmeddelande och används för att bearbeta meddelandet.

  12. I klassen AppDelegate lägger du till metoden FailedToRegisterForRemoteNotifications för att logga eventuella fel:

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

    Den här metoden anropas när appen inte har registrerats för att ta emot fjärrmeddelanden. Registreringen kan misslyckas om enheten inte är ansluten till nätverket, om APNS-servern inte kan nås eller om appen är felaktigt konfigurerad.

    Obs

    För produktionsscenarier vill du implementera korrekt loggning och felhantering i metoden FailedToRegisterForRemoteNotifications.

  13. I klassen AppDelegate lägger du till metoden FinishedLaunching för att villkorligt begära behörighet att använda meddelanden och registrera dig för fjärrmeddelanden:

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

    Information om hur du ber om behörighet att använda meddelanden finns i Fråga om behörighet att använda meddelanden på developer.apple.com.

Information om meddelanden i iOS finns i användaraviseringar på developer.apple.com.

Registrera typer med appens beroendeinjektionscontainer

  1. Öppna MauiProgram.cs i Visual Studio och lägg till en using-instruktion för PushNotificationsDemo.Services-namnområdet:

    using PushNotificationsDemo.Services;
    
  2. I klassen MauiProgram lägger du till kod för RegisterServices-tilläggsmetoden som registrerar DeviceInstallationService på varje plattform samt plattformsoberoende PushDemoNotificationActionService- och NotificationRegistrationService-tjänster och som returnerar ett MauiAppBuilder-objekt:

    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. I klassen MauiProgram lägger du till kod för RegisterViews-tilläggsmetoden som registrerar MainPage typ som en singleton och som returnerar ett MauiAppBuilder-objekt:

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

    Den MainPage typen registreras eftersom den kräver ett INotificationRegistrationService beroende och alla typer som kräver ett beroende måste registreras med containern för beroendeinmatning.

  4. I klassen MauiProgram ändrar du metoden CreateMauiApp så att den anropar RegisterServices- och RegisterViews-tilläggsmetoderna:

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

Mer information om beroendeinmatning i .NET MAUI finns i Beroendeinmatning.

Testa appen

Du kan testa din app genom att skicka push-meddelanden till appen med hjälp av serverdelstjänsten eller via Azure-portalen.

iOS-simulatorn stöder fjärrmeddelanden i iOS 16+ när den körs i macOS 13+ på Mac-datorer med Apple-kisel- eller T2-processorer. Om du inte uppfyller dessa maskinvarukrav måste du testa din iOS-app på en fysisk enhet. På Android kan du testa din app på en utvecklarupplåst fysisk enhet eller en emulator.

Android och iOS visar push-meddelanden för appens räkning när den körs i bakgrunden. Om appen körs i förgrunden när meddelandet tas emot avgör appens kod beteendet. Du kan till exempel uppdatera appens gränssnitt så att det återspeglar ny information som finns i meddelandet.

Testa med backend-tjänsten

Så här skickar du ett push-testmeddelande till din app via serverdelstjänsten som publiceras till Azure App Service:

  1. I Visual Studio kör du appen PushNotificationsDemo på Android eller iOS och väljer knappen Registrera.

    Not

    Om du testar på Android kontrollerar du att du inte kör med hjälp av felsökningskonfigurationen. Om appen tidigare har distribuerats kan du också se till att den har tvingats stängas och sedan starta den igen från startprogrammet.

  2. I valfri REST-verktyg skickar du en POST begäran till följande adress:

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

    Se till att du konfigurerar begärandehuvudena så att de innehåller nyckeln apikey och dess värde, ange brödtexten till rå och använd följande JSON-innehåll:

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

    Den övergripande begäran bör likna följande exempel:

    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. I det REST-verktyg du väljer, kontrollera att du får ett 200 OK svar.

  4. I appen på Android eller iOS ska en avisering visas som säger att åtgärden ActionA har tagits emot.

Mer information om hur du anropar REST-API:er finns i Använda .http-filer i Visual Studio och Testa webb-API:er med Http Repl-. I Visual Studio Code kan REST-klient användas för att testa REST-API:er.

Testa genom hjälp av Azure-portalen

Med Azure Notification Hubs kan du kontrollera att din app kan ta emot push-meddelanden.

Så här skickar du ett push-testmeddelande till din app via Azure-portalen:

  1. I Visual Studio kör du appen PushNotificationsDemo på Android eller iOS och väljer knappen Registrera.

    Obs

    Om du testar på Android kontrollerar du att du inte kör med hjälp av felsökningskonfigurationen. Alternativt, om appen tidigare har distribuerats, se till att den har tvingats stängas och starta sedan den igen från startskärmen.

  2. I Azure-portalenbläddrar du till meddelandehubben och väljer knappen Testa skicka på bladet Översikt.

  3. I panelen Test Send väljer du din Plattform och ändrar nyttolasten.

    För Apple använder du följande nyttolast:

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

    För Android använder du följande nyttolast:

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

    Azure-portalen bör ange att meddelandet har skickats.

    Information om meddelandeformatet Firebase Cloud Messaging finns i Om FCM-meddelanden på developer.android.com.

  4. I appen på Android eller iOS ska en avisering visas med ActionA-åtgärdsom tagits emot.

Felsökning

I följande avsnitt beskrivs de vanliga problem som uppstår vid försök att använda push-meddelanden i en klientapp.

Inget svar från bakgrundstjänsten

När du testar lokalt kontrollerar du att serverdelstjänsten körs och använder rätt port.

Om du testar mot Azure API-appen kontrollerar du att tjänsten körs och har distribuerats och har startats utan fel.

Kontrollera att du har angett basadressen korrekt i REST-verktygen eller i konfigurationen av .NET MAUI-appen. Basadressen ska vara https://<api_name>.azurewebsites.net eller https://localhost:7020 när du testar lokalt.

Ta emot en 401-statuskod från serverdelstjänsten

Kontrollera att du ställer in apikey begärandehuvudet korrekt och att det här värdet matchar det som du har konfigurerat för serverdelstjänsten.

Om du får det här felet när du testar lokalt kontrollerar du att nyckelvärdet som du definierade i .NET MAUI-appen matchar värdet Authentication:ApiKey användarhemligheter som används av serverdelstjänsten.

Om du testar med en Azure API-app kontrollerar du att nyckelvärdet som definierats i .NET MAUI-appen matchar det Authentication:ApiKey appinställningsvärde som definierats i Azure-portalen. Om du har skapat eller ändrat den här appinställningen efter att du har distribuerat serverdelstjänsten måste du starta om tjänsten för att värdet ska börja gälla.

Ta emot en 404-statuskod från serverdelstjänsten

Kontrollera att metoden för slutpunkts- och HTTP-begäran är korrekt:

  • PUT - https://<api_name>.azurewebsites.net/api/notifications/installations
  • TA BORT – https://<api_name>.azurewebsites.net/api/notifications/installations/<installation_id>
  • POST - https://<api_name>.azurewebsites.net/api/notifications/requests

Eller när du testar lokalt:

  • PUT - https://localhost:7020/api/notifications/installations
  • TA BORT – https://localhost:7020/api/notifications/installations/<installation_id>
  • POST - https://localhost:7020/api/notifications/requests

Viktig

När du anger basadressen i .NET MAUI-appen ska du se till att den slutar med en /. Basadressen ska vara https://<api_name>.azurewebsites.net eller https://localhost:7020/ när du testar lokalt.

Får inte meddelanden på Android efter att ha startat eller stoppat en felsökningssession

Kontrollera att du registrerar dig varje gång du startar en felsökningssession. Felsökningsprogrammet gör att en ny Firebase-token genereras och därför måste installationen av meddelandehubben uppdateras.

Det går inte att registrera och felmeddelandet för meddelandehubben visas

Kontrollera att testenheten har nätverksanslutning. Bestäm sedan statuskoden för HTTP-svar genom att ange en brytpunkt för att inspektera egenskapen StatusCode i HttpResponse.

Granska de tidigare felsökningsförslagen, i förekommande fall, baserat på statuskoden.

Ange en brytpunkt på de rader som returnerar specifika statuskoder för respektive API. Försök sedan att anropa serverdelstjänsten när du felsöker lokalt.

Verifiera att serverdelstjänsten fungerar som förväntat med valfritt REST-verktyg och använd den nyttolast som skapats av .NET MAUI-appen för den valda plattformen.

Granska de plattformsspecifika konfigurationsavsnitten för att se till att inga steg har missats. Kontrollera att lämpliga värden löses för InstallationId och Token variabler för den valda plattformen.

Det går inte att identifiera ett ID för enhetsfelmeddelandet.

Granska de plattformsspecifika konfigurationsavsnitten för att se till att inga steg har missats.