Delen via


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

Voorbeeld downloaden Het voorbeeld downloaden

In deze zelfstudie gebruikt u Azure Notification Hubs- om pushmeldingen te verzenden naar een Xamarin.Forms-toepassing 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 met behulp van de nieuwste en beste installatie- benadering. De service verzendt ook pushmeldingen op een platformoverschrijdende manier.

Deze bewerkingen worden verwerkt met behulp van de Notification Hubs SDK voor back-endbewerkingen. Meer informatie over de algemene benadering vindt u in de Registreren vanuit de back-end van uw app documentatie.

In deze zelfstudie doorloopt u de volgende stappen:

Voorwaarden

Als u wilt volgen, hebt u het volgende nodig:

  • Een Azure-abonnement waar u resources kunt maken en beheren.
  • Een Mac met Visual Studio voor Mac geïnstalleerd of een pc met Visual Studio 2019.
  • Visual Studio 2019- gebruikers moeten ook Mobile-ontwikkeling hebben met .NET en ASP.NET en webontwikkeling workloads geïnstalleerd.
  • De mogelijkheid om de app uit te voeren op Android- (fysieke of emulatorapparaten) of iOS- (alleen fysieke apparaten).

Voor Android hebt u het volgende nodig:

  • Een ontwikkelaar ontgrendeld fysiek apparaat of een emulator (met API 26 en hoger waarop Google Play Services is geïnstalleerd).

Voor iOS hebt u het volgende nodig:

Notitie

De iOS-simulator biedt geen ondersteuning voor externe meldingen en daarom is een fysiek apparaat vereist bij het verkennen van dit voorbeeld in iOS. U hoeft de app echter niet uit te voeren op zowel Android- als iOS- om deze zelfstudie te voltooien.

U kunt de stappen in dit voorbeeld van de eerste principes volgen zonder eerdere ervaring. U hebt echter wel baat bij het kennen van de volgende aspecten.

Belangrijk

De opgegeven stappen zijn specifiek voor Visual Studio voor Mac. Het is mogelijk om Visual Studio 2019- te volgen, maar er kunnen enkele verschillen zijn om af te stemmen. Bijvoorbeeld beschrijvingen van gebruikersinterface en werkstromen, sjabloonnamen, omgevingsconfiguratie, enzovoort.

Push Notification Services en Azure Notification Hub instellen

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

Een Firebase-project maken en Firebase Cloud Messaging voor Android inschakelen

  1. Meld u aan bij de Firebase-console. Maak een nieuw Firebase-project dat PushDemo- invoert als projectnaam.

    Notitie

    Er wordt een unieke naam voor u gegenereerd. Dit bestaat standaard uit een variant in kleine letters van de naam die u hebt opgegeven plus een gegenereerd getal gescheiden door een streepje. U kunt dit wijzigen als u wilt dat deze nog steeds wereldwijd uniek is.

  2. Nadat u uw project hebt gemaakt, selecteert u Firebase toevoegen aan uw Android-app.

    Firebase toevoegen aan uw Android-app

  3. Voer op de pagina Firebase toevoegen aan uw Android-app de volgende stappen uit.

    1. Voer voor de Android-pakketnaameen naam in voor uw pakket. Bijvoorbeeld: com.<organization_identifier>.<package_name>.

      Geef de pakketnaam op

    2. Selecteer App-registreren.

    3. Selecteer google-services.jsondownloaden. Sla het bestand vervolgens op in een lokale map voor later gebruik en selecteer Volgende.

      google-services.json downloaden

    4. Selecteer Volgende.

    5. Selecteer Console doorgaan

      Notitie

      Als de knop Doorgaan naar de console niet is ingeschakeld, kiest u deze stap overslaanvanwege de de installatie controleren.

  4. Selecteer in de Firebase-console het tandwiel voor uw project. Selecteer vervolgens projectinstellingen.

    Projectinstellingen selecteren

    Notitie

    Als u het google-services.json bestand nog niet hebt gedownload, kunt u het downloaden op deze pagina.

  5. Ga naar het tabblad Cloud Messaging bovenaan. Kopieer en sla de Server-sleutel op voor later gebruik. U gebruikt deze waarde om uw Notification Hub te configureren.

    serversleutel kopiëren

Uw iOS-app registreren voor pushmeldingen

Als u pushmeldingen wilt verzenden naar een iOS-app, registreert u uw toepassing bij Apple en registreert u zich ook voor pushmeldingen.

  1. Als u uw app nog niet hebt geregistreerd, bladert u naar de iOS-inrichtingsportal in het Apple Developer Center. Meld u aan bij de portal met uw Apple ID, navigeer naar certificaten, id's & profielenen selecteer vervolgens id's. Klik op + om een nieuwe app te registreren.

    pagina app-id's van de iOS-inrichtingsportal

  2. Selecteer in het scherm Een nieuwe id registreren het keuzerondje app-id's. Selecteer vervolgens Doorgaan.

    iOS-inrichtingsportal nieuwe id-pagina registreren

  3. Werk de volgende drie waarden voor uw nieuwe app bij en selecteer vervolgens Doorgaan:

    • Beschrijving: typ een beschrijvende naam voor uw app.

    • bundel-id: voer een bundel-id in van het formulier com.<organization_identifier>.<product_name> zoals vermeld in de app-distributiehandleiding. In de volgende schermopname wordt de mobcat-waarde gebruikt als organisatie-id en wordt de PushDemo--waarde gebruikt als productnaam.

      de app-id-pagina voor de iOS-inrichtingsportal registreren

    • pushmeldingen: controleer de optie Pushmeldingen in de sectie Capabilities.

      formulier voor het registreren van een nieuwe app-id

      Met deze actie wordt uw app-id gegenereerd en worden de gegevens bevestigd. Selecteer Doorgaanen selecteer registreren om de nieuwe app-id te bevestigen.

      nieuwe app-id bevestigen

      Nadat u registreren hebt geselecteerd, ziet u de nieuwe app-id als regelitem op de pagina Certificaten, Id's & Profielen.

  4. Zoek op de pagina Certificaten, id's & profielen onder id'shet regelitem app-id dat u hebt gemaakt. Selecteer vervolgens de rij om de Uw app-id-configuratie scherm bewerken weer te geven.

Een certificaat maken voor Notification Hubs

Een certificaat is vereist om de Notification Hub in staat te stellen om te werken met APNS- (Apple Push Notification Services) en kan op twee manieren worden verstrekt:

  1. Een p12-pushcertificaat maken dat rechtstreeks naar Notification Hub kan worden geüpload (de oorspronkelijke benadering)

  2. Een p8-certificaat maken dat kan worden gebruikt voor verificatie op basis van tokens (de nieuwere en aanbevolen benadering)

De nieuwere benadering heeft een aantal voordelen, zoals beschreven in verificatie op basis van token (HTTP/2) voor APNS-. Er zijn minder stappen vereist, maar worden ook verplicht voor specifieke scenario's. Er zijn echter stappen gegeven voor beide benaderingen, omdat beide voor de doeleinden van deze zelfstudie werken.

OPTIE 1: Een p12-pushcertificaat maken dat rechtstreeks naar Notification Hub kan worden geüpload
  1. Voer op uw Mac het hulpprogramma Sleutelhangertoegang uit. Het kan worden geopend vanuit de Utilities map of de Andere map op launchpad.

  2. Selecteer sleutelhangertoegang, vouw certificaatassistentuit en selecteer vervolgens Een certificaat aanvragen bij een certificeringsinstantie.

    Sleutelhangertoegang gebruiken om een nieuw certificaat aan te vragen

    Notitie

    Sleutelhangertoegang selecteert standaard het eerste item in de lijst. Dit kan een probleem zijn als u zich in de categorie Certificaten bevindt en Apple Worldwide Developer Relations Certification Authority niet het eerste item in de lijst is. Zorg ervoor dat u een niet-sleutelitem hebt of dat de Apple Worldwide Developer Relations-certificeringsinstantie sleutel is geselecteerd voordat u de CSR (Certificaatondertekeningsaanvraag) genereert.

  3. Selecteer uw e-mailadres van de gebruiker, voer uw algemene naam waarde in, zorg ervoor dat u opgeslagen op schijfopgeeft en selecteer vervolgens Doorgaan. Laat CA-e-mailadres leeg omdat dit niet vereist is.

    verwachte certificaatgegevens

  4. Voer een naam in voor het CSR-bestand (Certificate Signing Request) in Opslaan als, selecteer de locatie in Waaren selecteer vervolgens Opslaan.

    Kies een bestandsnaam voor het certificaat

    Met deze actie wordt het CSR-bestand opgeslagen op de geselecteerde locatie. De standaardlocatie is Desktop. Onthoud de locatie die voor het bestand is gekozen.

  5. Ga terug naar de pagina Certificaten, id's & profielen pagina in de iOS-inrichtingsportal, schuif omlaag naar de ingeschakelde optie Pushmeldingen en selecteer configureren om het certificaat te maken.

    pagina App-id bewerken

  6. Het venster Apple Push Notification Service TLS/SSL-certificaten wordt weergegeven. Selecteer de knop Certificaat maken onder de sectie Development TLS/SSL Certificate.

    knop Certificaat voor app-id maken

    Het scherm Een nieuw certificaat maken wordt weergegeven.

    Notitie

    In deze zelfstudie wordt gebruikgemaakt van een ontwikkelingscertificaat. Hetzelfde proces wordt gebruikt bij het registreren van een productiecertificaat. Zorg ervoor dat u hetzelfde certificaattype gebruikt bij het verzenden van meldingen.

  7. Selecteer Bestandkiezen, blader naar de locatie waar u het CSR-bestandhebt opgeslagen en dubbelklik vervolgens op de naam van het certificaat om het te laden. Selecteer vervolgens Doorgaan.

  8. Nadat de portal het certificaat heeft gemaakt, selecteert u de knop Downloaden. Sla het certificaat op en onthoud de locatie waarop het is opgeslagen.

    pagina voor het downloaden van certificaten gegenereerd

    Het certificaat wordt gedownload en opgeslagen op uw computer in de map Downloads.

    Certificaatbestand zoeken in de map Downloads

    Notitie

    Standaard heeft het gedownloade ontwikkelingscertificaat de naam aps_development.cer.

  9. Dubbelklik op het gedownloade pushcertificaat aps_development.cer. Met deze actie wordt het nieuwe certificaat in de sleutelhanger geïnstalleerd, zoals wordt weergegeven in de volgende afbeelding:

    lijst met toegangscertificaten voor sleutelhanger met nieuw certificaat

    Notitie

    Hoewel de naam in uw certificaat mogelijk anders is, wordt de naam voorafgegaan door Apple Development iOS Push Services en de juiste bundel-id eraan te koppelen.

  10. Klik in Sleutelhangertoegang Control + klik op op het nieuwe pushcertificaat dat u hebt gemaakt in de categorie Certificaten. Selecteer Exporteren, geef het bestand een naam, selecteer de p12-indeling en selecteer vervolgens Opslaan.

    certificaat exporteren als p12-indeling

    U kunt ervoor kiezen om het certificaat te beveiligen met een wachtwoord, maar een wachtwoord is optioneel. Klik op OK als u het maken van een wachtwoord wilt omzeilen. Noteer de bestandsnaam en locatie van het geëxporteerde p12-certificaat. Ze worden gebruikt om verificatie met APNs in te schakelen.

    Notitie

    De naam en locatie van uw p12-bestand kunnen afwijken van wat in deze zelfstudie wordt weergegeven.

OPTIE 2: Een p8-certificaat maken dat kan worden gebruikt voor verificatie op basis van tokens
  1. Noteer de volgende details:

    • voorvoegsel voor app-id's (team-id)
    • bundel-id
  2. Klik in certificaten, id's & profielenop sleutels.

    Notitie

    Als u al een sleutel hebt geconfigureerd voor APNS-, kunt u het p8-certificaat dat u hebt gedownload, opnieuw gebruiken nadat het is gemaakt. Zo ja, dan kunt u stappen 3 tot en met 5negeren.

  3. Klik op de knop + (of de knop Een sleutel maken) om een nieuwe sleutel te maken.

  4. Geef een geschikte sleutelnaam waarde op, schakel vervolgens de APNS-optie (Apple Push Notifications Service) in en klik vervolgens op Doorgaan, gevolgd door registreren op het volgende scherm.

  5. Klik op Download en verplaats het bestand p8 (voorafgegaan door AuthKey_) naar een beveiligde lokale map en klik vervolgens op Gereed.

    Notitie

    Zorg ervoor dat u het p8-bestand op een veilige plaats bewaart (en een back-up opslaat). Nadat u de sleutel hebt gedownload, kan deze niet opnieuw worden gedownload omdat de serverkopie wordt verwijderd.

  6. Klik in Sleutelsop de sleutel die u hebt gemaakt (of een bestaande sleutel als u ervoor hebt gekozen om die te gebruiken).

  7. Noteer de sleutel-id waarde.

  8. Open uw p8-certificaat in een geschikte toepassing van uw keuze, zoals Visual Studio Code. Noteer de sleutelwaarde (tussen -----BEGIN PRIVATE KEY----- en -----END PRIVATE KEY-----).

    -----BEGIN PRIVATE KEY-----
    <key_value>
    ----------

    Notitie

    Dit is de tokenwaarde die later wordt gebruikt om Notification Hub-te configureren.

Aan het einde van deze stappen moet u de volgende informatie hebben voor later gebruik in Uw Notification Hub configureren met APNS-informatie:

  • team-id (zie stap 1)
  • bundel-id (zie stap 1)
  • sleutel-id (zie stap 7)
  • tokenwaarde (p8-sleutelwaarde verkregen in stap 8)

Een inrichtingsprofiel voor de app maken

  1. Ga terug naar de iOS-inrichtingsportal, selecteer Certificaten, Id's & Profielen, selecteer Profielen in het menu links en selecteer + om een nieuw profiel te maken. Het scherm Een nieuw inrichtingsprofiel registreren wordt weergegeven.

  2. Selecteer onder Development als het inrichtingsprofieltype en selecteer vervolgens Doorgaan.

    lijst met inrichtingsprofielen

  3. Selecteer vervolgens de app-id die u hebt gemaakt in de vervolgkeuzelijst App-id en selecteer Doorgaan.

    Selecteer de app-id

  4. Selecteer in het venster Certificaten selecteren het ontwikkelingscertificaat dat u gebruikt voor het ondertekenen van programmacode en selecteer Doorgaan.

    Notitie

    Dit certificaat is niet het pushcertificaat dat u hebt gemaakt in de vorige stap. Dit is uw ontwikkelingscertificaat. Als er geen bestaat, moet u deze maken omdat dit een vereiste is voor deze zelfstudie. Ontwikkelaarscertificaten kunnen worden gemaakt in de Apple Developer Portal, via Xcode- of in Visual Studio-.

  5. Ga terug naar de pagina Certificaten, Id's & Profielen, selecteer Profielen in het linkermenu en selecteer vervolgens + om een nieuw profiel te maken. Het scherm Een nieuw inrichtingsprofiel registreren wordt weergegeven.

  6. Selecteer in het venster Certificaten selecteren het ontwikkelingscertificaat dat u hebt gemaakt. Selecteer vervolgens Doorgaan.

  7. Selecteer vervolgens de apparaten die u wilt gebruiken voor testen en selecteer Doorgaan.

  8. Kies ten slotte een naam voor het profiel in Inrichtingsprofielnaamen selecteer genereren.

    Een inrichtingsprofielnaam kiezen

  9. Wanneer het nieuwe inrichtingsprofiel wordt gemaakt, selecteert u downloaden. Onthoud de locatie waarop deze is opgeslagen.

  10. Blader naar de locatie van het inrichtingsprofiel en dubbelklik erop om het te installeren op uw ontwikkelcomputer.

Een Notification Hub maken

In deze sectie maakt u een Notification Hub en configureert u verificatie met APNS-. U kunt een p12-pushcertificaat of verificatie op basis van tokens gebruiken. Als u een Notification Hub wilt gebruiken die u al hebt gemaakt, kunt u doorgaan naar stap 5.

  1. Meld u aan bij Azure.

  2. Klik op Een resource maken, zoek en kies Notification Hub-en klik vervolgens op Maken.

  3. Werk de volgende velden bij en klik vervolgens op maken:

    BASIC DETAILS

    -abonnement: Kies het doelabonnement abonnement in de vervolgkeuzelijst
    resourcegroep: een nieuwe resourcegroep maken (of kies een bestaande resourcegroep)

    NAAMRUIMTEDETAILS

    Notification Hub-naamruimte: voer een wereldwijd unieke naam in voor de Notification Hub-naamruimte

    Notitie

    Zorg ervoor dat de optie Nieuwe maken is geselecteerd voor dit veld.

    NOTIFICATION HUB DETAILS

    Notification Hub: voer een naam in voor de Notification Hub-
    Locatie: Kies een geschikte locatie in de vervolgkeuzelijst
    prijscategorie: De standaardoptie Gratis behouden

    Notitie

    Tenzij u het maximum aantal hubs in de gratis laag hebt bereikt.

  4. Zodra de Notification Hub is ingericht, gaat u naar die resource.

  5. Navigeer naar uw nieuwe Notification Hub-.

  6. Selecteer toegangsbeleid in de lijst (onder BEHEREN).

  7. Noteer de beleidsnaam waarden, samen met de bijbehorende verbindingsreeks waarden.

Uw Notification Hub configureren met APNS-gegevens

Selecteer onder Notification ServicesApple volg vervolgens de juiste stappen op basis van de methode die u eerder hebt gekozen in de sectie Een certificaat voor Notification Hubs maken.

Notitie

Gebruik de Production- alleen voor toepassingsmodus als u pushmeldingen wilt verzenden naar gebruikers die uw app in de Store hebben gekocht.

OPTIE 1: Een .p12-pushcertificaat gebruiken

  1. Selecteer Certificaat.

  2. Selecteer het bestandspictogram.

  3. Selecteer het .p12-bestand dat u eerder hebt geëxporteerd en selecteer vervolgens Open.

  4. Geef indien nodig het juiste wachtwoord op.

  5. Selecteer Sandbox- modus.

  6. Selecteer opslaan.

OPTIE 2: Verificatie op basis van tokens gebruiken

  1. Selecteer token.

  2. Voer de volgende waarden in die u eerder hebt verkregen:

    • sleutel-id
    • bundel-id
    • team-id
    • token
  3. Kies Sandbox-.

  4. Selecteer opslaan.

Uw Notification Hub configureren met FCM-gegevens

  1. Selecteer Google- (GCM/FCM) in de sectie Instellingen in het linkermenu.
  2. Voer de -serversleutel in die u hebt genoteerd in de Google Firebase Console.
  3. Selecteer opslaan op de werkbalk.

Een ASP.NET Core Web API-back-endtoepassing maken

In deze sectie maakt u de ASP.NET Core Web-API back-end voor het afhandelen van apparaatregistratie en het verzenden van meldingen naar de mobiele Xamarin.Forms-app.

Een webproject maken

  1. Selecteer in Visual StudioFile>New Solution.

  2. Selecteer .NET Core>App>ASP.NET Core>API>Volgende.

  3. Selecteer in het dialoogvenster Uw nieuwe ASP.NET Core Web-API configurerenTarget Framework van .NET Core 3.1-.

  4. Voer PushDemoApi- in voor de projectnaam en selecteer maken.

  5. Start de foutopsporing (Command + Enter) om de sjabloon-app te testen.

    Notitie

    De sjabloon-app is geconfigureerd voor het gebruik van de WeatherForecastController- als de launchUrl-. Dit is ingesteld in Eigenschappen>launchSettings.json.

    Als u wordt gevraagd om een Ongeldig ontwikkelingscertificaat gevonden bericht:

    1. Klik op Ja om akkoord te gaan met het uitvoeren van het hulpprogramma dotnet dev-certs https om dit op te lossen. Het hulpprogramma dotnet dev-certs https vraagt u vervolgens om een wachtwoord in te voeren voor het certificaat en het wachtwoord voor uw sleutelhanger.

    2. Klik op Ja wanneer u wordt gevraagd om het nieuwe certificaat te installeren en te vertrouwenen voer vervolgens het wachtwoord voor de sleutelhanger in.

  6. Vouw de map Controllers uit en verwijder WeatherForecastController.cs.

  7. Verwijder WeatherForecast.cs.

  8. Lokale configuratiewaarden instellen met behulp van het hulpprogramma Secret Manager. Door de geheimen van de oplossing los te koppelen, zorgt u ervoor dat ze niet in broncodebeheer terechtkomen. Open Terminal ga vervolgens naar de map van het projectbestand en voer de volgende opdrachten uit:

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

    Vervang de waarden van de tijdelijke aanduiding door de naam en de verbindingsreekswaarden van uw eigen Notification Hub. U hebt deze in de een notification hub sectie gemaakt. Anders kunt u ze opzoeken in Azure.

    NotificationHub:Name:
    Zie Name in de samenvatting van Essentials bovenaan Overview.

    NotificationHub:ConnectionString-:
    Zie DefaultFullSharedAccessSignature- in toegangsbeleid

    Notitie

    Voor productiescenario's kunt u opties bekijken, zoals Azure KeyVault- om de verbindingsreeks veilig op te slaan. Ter vereenvoudiging worden de geheimen toegevoegd aan de Azure App Service toepassingsinstellingen.

Clients verifiëren met behulp van een API-sleutel (optioneel)

API-sleutels zijn niet zo veilig als tokens, maar zijn voldoende voor de doeleinden van deze zelfstudie. Een API-sleutel kan eenvoudig worden geconfigureerd via de ASP.NET Middleware-.

  1. Voeg de API-sleutel toe aan de lokale configuratiewaarden.

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

    Notitie

    Vervang de waarde van de tijdelijke aanduiding door uw eigen waarde en noteer deze.

  2. Control + Klik op in het project PushDemoApi, kies nieuwe map in het menu toevoegen en klik vervolgens op toevoegen met Authentication als de mapnaam.

  3. Control + klik op in de map Authentication en kies New File... in het menu Toevoegen.

  4. Selecteer >Lege klasse, voer ApiKeyAuthOptions.cs in voor de naamen klik vervolgens op Nieuwe de volgende implementatie toe te voegen.

    using Microsoft.AspNetCore.Authentication;
    
    namespace PushDemoApi.Authentication
    {
        public class ApiKeyAuthOptions : AuthenticationSchemeOptions
        {
            public const string DefaultScheme = "ApiKey";
            public string Scheme => DefaultScheme;
            public string ApiKey { get; set; }
        }
    }
    
  5. Voeg nog een Lege klasse toe aan de map Authentication met de naam ApiKeyAuthHandler.csen voeg vervolgens de volgende implementatie toe.

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Security.Claims;
    using System.Text.Encodings.Web;
    using System.Threading.Tasks;
    using Microsoft.AspNetCore.Authentication;
    using Microsoft.Extensions.Logging;
    using Microsoft.Extensions.Options;
    
    namespace PushDemoApi.Authentication
    {
        public class ApiKeyAuthHandler : AuthenticationHandler<ApiKeyAuthOptions>
        {
            const string ApiKeyIdentifier = "apikey";
    
            public ApiKeyAuthHandler(
                IOptionsMonitor<ApiKeyAuthOptions> options,
                ILoggerFactory logger,
                UrlEncoder encoder,
                ISystemClock clock)
                : base(options, logger, encoder, clock) {}
    
            protected override Task<AuthenticateResult> HandleAuthenticateAsync()
            {
                string key = string.Empty;
    
                if (Request.Headers[ApiKeyIdentifier].Any())
                {
                    key = Request.Headers[ApiKeyIdentifier].FirstOrDefault();
                }
                else if (Request.Query.ContainsKey(ApiKeyIdentifier))
                {
                    if (Request.Query.TryGetValue(ApiKeyIdentifier, out var queryKey))
                        key = queryKey;
                }
    
                if (string.IsNullOrWhiteSpace(key))
                    return Task.FromResult(AuthenticateResult.Fail("No api key provided"));
    
                if (!string.Equals(key, Options.ApiKey, StringComparison.Ordinal))
                    return Task.FromResult(AuthenticateResult.Fail("Invalid api key."));
    
                var identities = new List<ClaimsIdentity> {
                    new ClaimsIdentity("ApiKeyIdentity")
                };
    
                var ticket = new AuthenticationTicket(
                    new ClaimsPrincipal(identities), Options.Scheme);
    
                return Task.FromResult(AuthenticateResult.Success(ticket));
            }
        }
    }
    

    Notitie

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

  6. Voeg nog een Lege klasse toe aan de map Authentication met de naam ApiKeyAuthenticationBuilderExtensions.csen voeg vervolgens de volgende implementatie toe.

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

    Notitie

    Deze extensiemethode vereenvoudigt de middleware-configuratiecode in Startup.cs waardoor deze beter leesbaar en over het algemeen gemakkelijker te volgen is.

  7. Werk in Startup.csde methode ConfigureServices bij om de API-sleutelverificatie te configureren onder de aanroep van de -services. Methode AddControllers.

    using PushDemoApi.Authentication;
    using PushDemoApi.Models;
    using PushDemoApi.Services;
    
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddControllers();
    
        services.AddAuthentication(options =>
        {
            options.DefaultAuthenticateScheme = ApiKeyAuthOptions.DefaultScheme;
            options.DefaultChallengeScheme = ApiKeyAuthOptions.DefaultScheme;
        }).AddApiKeyAuth(Configuration.GetSection("Authentication").Bind);
    }
    
  8. Werk nog steeds in Startup.csde methode Configureren bij om de UseAuthentication- en UseAuthorization extensiemethoden aan te roepen op de IApplicationBuilder-van de app. Zorg ervoor dat deze methoden worden aangeroepen na UseRouting- en vóór app. UseEndpoints.

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
    
        app.UseHttpsRedirection();
    
        app.UseRouting();
    
        app.UseAuthentication();
    
        app.UseAuthorization();
    
        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllers();
        });
    }
    

    Notitie

    Het aanroepen van UseAuthentication registreert de middleware die gebruikmaakt van de eerder geregistreerde verificatieschema's (van ConfigureServices). Dit moet worden aangeroepen voordat middleware wordt aangeroepen die afhankelijk is van gebruikers die worden geverifieerd.

Afhankelijkheden toevoegen en services configureren

ASP.NET Core ondersteunt het afhankelijkheidsinjectiepatroon (DI) softwareontwerppatroon. Dit is een techniek voor het bereiken van Inversion of Control (IoC) tussen klassen en hun afhankelijkheden.

Het gebruik van de Notification Hub en de Notification Hubs SDK voor back-endbewerkingen wordt ingekapseld in een service. De service wordt geregistreerd en beschikbaar gesteld via een geschikte abstractie.

  1. Control + Klik op in de map Afhankelijkheden en kies vervolgens NuGet-pakketten beheren....

  2. Zoek Microsoft.Azure.NotificationHubs en controleer of deze is ingeschakeld.

  3. Klik op Pakketten toevoegenen klik vervolgens op Accepteren wanneer u wordt gevraagd de licentievoorwaarden te accepteren.

  4. Control + Klik op in het project PushDemoApi, kies nieuwe map in het menu toevoegen en klik vervolgens op toevoegen met modellen als de mapnaam.

  5. Control + Klik op in de map Modellen en kies vervolgens Nieuw bestand... in het menu Toevoegen.

  6. Selecteer >Lege klasse, voer PushTemplates.cs in voor de Naamen klik vervolgens op Nieuwe de volgende implementatie toe te voegen.

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

    Notitie

    Deze klasse bevat de nettoladingen voor tokenized meldingen voor de algemene en stille meldingen die vereist zijn voor dit scenario. De nettoladingen worden buiten de Installation gedefinieerd om experimenten toe te staan zonder dat bestaande installaties via de service hoeven te worden bijgewerkt. Het afhandelen van wijzigingen in installaties op deze manier valt buiten het bereik van deze zelfstudie. Overweeg voor productie aangepaste sjablonen.

  7. Voeg nog een Lege klasse toe aan de map Modellen met de naam DeviceInstallation.csen voeg vervolgens de volgende implementatie toe.

    using System.Collections.Generic;
    using System.ComponentModel.DataAnnotations;
    
    namespace PushDemoApi.Models
    {
        public class DeviceInstallation
        {
            [Required]
            public string InstallationId { get; set; }
    
            [Required]
            public string Platform { get; set; }
    
            [Required]
            public string PushChannel { get; set; }
    
            public IList<string> Tags { get; set; } = Array.Empty<string>();
        }
    }
    
  8. Voeg nog een Empty Class toe aan de map Models met de naam NotificationRequest.csen voeg vervolgens de volgende implementatie toe.

    using System;
    
    namespace PushDemoApi.Models
    {
        public class NotificationRequest
        {
            public string Text { get; set; }
            public string Action { get; set; }
            public string[] Tags { get; set; } = Array.Empty<string>();
            public bool Silent { get; set; }
        }
    }
    
  9. Voeg nog een Lege klasse toe aan de map Models met de naam NotificationHubOptions.csen voeg vervolgens de volgende implementatie toe.

    using System.ComponentModel.DataAnnotations;
    
    namespace PushDemoApi.Models
    {
        public class NotificationHubOptions
        {
            [Required]
            public string Name { get; set; }
    
            [Required]
            public string ConnectionString { get; set; }
        }
    }
    
  10. Voeg een nieuwe map toe aan het project PushDemoApi met de naam Services.

  11. Voeg een Empty Interface toe aan de map Services met de naam INotificationService.csen voeg vervolgens de volgende implementatie toe.

    using System.Threading;
    using System.Threading.Tasks;
    using PushDemoApi.Models;
    
    namespace PushDemoApi.Services
    {
        public interface INotificationService
        {
            Task<bool> CreateOrUpdateInstallationAsync(DeviceInstallation deviceInstallation, CancellationToken token);
            Task<bool> DeleteInstallationByIdAsync(string installationId, CancellationToken token);
            Task<bool> RequestNotificationAsync(NotificationRequest notificationRequest, CancellationToken token);
        }
    }
    
  12. Voeg een Lege klasse toe aan de map Services met de naam NotificationHubsService.csen voeg vervolgens de volgende code toe om de INotificationService-interface te implementeren:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading;
    using System.Threading.Tasks;
    using Microsoft.Azure.NotificationHubs;
    using Microsoft.Extensions.Logging;
    using Microsoft.Extensions.Options;
    using PushDemoApi.Models;
    
    namespace PushDemoApi.Services
    {
        public class NotificationHubService : INotificationService
        {
            readonly NotificationHubClient _hub;
            readonly Dictionary<string, NotificationPlatform> _installationPlatform;
            readonly ILogger<NotificationHubService> _logger;
    
            public NotificationHubService(IOptions<NotificationHubOptions> options, ILogger<NotificationHubService> logger)
            {
                _logger = logger;
                _hub = NotificationHubClient.CreateClientFromConnectionString(
                    options.Value.ConnectionString,
                    options.Value.Name);
    
                _installationPlatform = new Dictionary<string, NotificationPlatform>
                {
                    { nameof(NotificationPlatform.Apns).ToLower(), NotificationPlatform.Apns },
                    { nameof(NotificationPlatform.Fcm).ToLower(), NotificationPlatform.Fcm }
                };
            }
    
            public async Task<bool> CreateOrUpdateInstallationAsync(DeviceInstallation deviceInstallation, CancellationToken token)
            {
                if (string.IsNullOrWhiteSpace(deviceInstallation?.InstallationId) ||
                    string.IsNullOrWhiteSpace(deviceInstallation?.Platform) ||
                    string.IsNullOrWhiteSpace(deviceInstallation?.PushChannel))
                    return false;
    
                var installation = new Installation()
                {
                    InstallationId = deviceInstallation.InstallationId,
                    PushChannel = deviceInstallation.PushChannel,
                    Tags = deviceInstallation.Tags
                };
    
                if (_installationPlatform.TryGetValue(deviceInstallation.Platform, out var platform))
                    installation.Platform = platform;
                else
                    return false;
    
                try
                {
                    await _hub.CreateOrUpdateInstallationAsync(installation, token);
                }
                catch
                {
                    return false;
                }
    
                return true;
            }
    
            public async Task<bool> DeleteInstallationByIdAsync(string installationId, CancellationToken token)
            {
                if (string.IsNullOrWhiteSpace(installationId))
                    return false;
    
                try
                {
                    await _hub.DeleteInstallationAsync(installationId, token);
                }
                catch
                {
                    return false;
                }
    
                return true;
            }
    
            public async Task<bool> RequestNotificationAsync(NotificationRequest notificationRequest, CancellationToken token)
            {
                if ((notificationRequest.Silent &&
                    string.IsNullOrWhiteSpace(notificationRequest?.Action)) ||
                    (!notificationRequest.Silent &&
                    (string.IsNullOrWhiteSpace(notificationRequest?.Text)) ||
                    string.IsNullOrWhiteSpace(notificationRequest?.Action)))
                    return false;
    
                var androidPushTemplate = notificationRequest.Silent ?
                    PushTemplates.Silent.Android :
                    PushTemplates.Generic.Android;
    
                var iOSPushTemplate = notificationRequest.Silent ?
                    PushTemplates.Silent.iOS :
                    PushTemplates.Generic.iOS;
    
                var androidPayload = PrepareNotificationPayload(
                    androidPushTemplate,
                    notificationRequest.Text,
                    notificationRequest.Action);
    
                var iOSPayload = PrepareNotificationPayload(
                    iOSPushTemplate,
                    notificationRequest.Text,
                    notificationRequest.Action);
    
                try
                {
                    if (notificationRequest.Tags.Length == 0)
                    {
                        // This will broadcast to all users registered in the notification hub
                        await SendPlatformNotificationsAsync(androidPayload, iOSPayload, token);
                    }
                    else if (notificationRequest.Tags.Length <= 20)
                    {
                        await SendPlatformNotificationsAsync(androidPayload, iOSPayload, notificationRequest.Tags, token);
                    }
                    else
                    {
                        var notificationTasks = notificationRequest.Tags
                            .Select((value, index) => (value, index))
                            .GroupBy(g => g.index / 20, i => i.value)
                            .Select(tags => SendPlatformNotificationsAsync(androidPayload, iOSPayload, tags, token));
    
                        await Task.WhenAll(notificationTasks);
                    }
    
                    return true;
                }
                catch (Exception e)
                {
                    _logger.LogError(e, "Unexpected error sending notification");
                    return false;
                }
            }
    
            string PrepareNotificationPayload(string template, string text, string action) => template
                .Replace("$(alertMessage)", text, StringComparison.InvariantCulture)
                .Replace("$(alertAction)", action, StringComparison.InvariantCulture);
    
            Task SendPlatformNotificationsAsync(string androidPayload, string iOSPayload, CancellationToken token)
            {
                var sendTasks = new Task[]
                {
                    _hub.SendFcmNativeNotificationAsync(androidPayload, token),
                    _hub.SendAppleNativeNotificationAsync(iOSPayload, token)
                };
    
                return Task.WhenAll(sendTasks);
            }
    
            Task SendPlatformNotificationsAsync(string androidPayload, string iOSPayload, IEnumerable<string> tags, CancellationToken token)
            {
                var sendTasks = new Task[]
                {
                    _hub.SendFcmNativeNotificationAsync(androidPayload, tags, token),
                    _hub.SendAppleNativeNotificationAsync(iOSPayload, tags, token)
                };
    
                return Task.WhenAll(sendTasks);
            }
        }
    }
    

    Notitie

    De tagexpressie die is verstrekt aan SendTemplateNotificationAsync is beperkt tot 20 tags. Het is beperkt tot 6 voor de meeste operators, maar de expressie bevat in dit geval alleen OR's (||). Als er meer dan 20 tags in de aanvraag staan, moeten ze worden gesplitst in meerdere aanvragen. Zie de Routerings- en tagexpressies documentatie voor meer informatie.

  13. Werk in Startup.csde methode ConfigureServices bij om de NotificationHubsService- toe te voegen als een singleton-implementatie van INotificationService.

    
    using PushDemoApi.Models;
    using PushDemoApi.Services;
    
    public void ConfigureServices(IServiceCollection services)
    {
        ...
    
        services.AddSingleton<INotificationService, NotificationHubService>();
    
        services.AddOptions<NotificationHubOptions>()
            .Configure(Configuration.GetSection("NotificationHub").Bind)
            .ValidateDataAnnotations();
    }
    

De API voor meldingen maken

  1. Control + Klik op in de map Controllers en kies vervolgens Nieuw bestand... in het menu Toevoegen.

  2. Selecteer ASP.NET Core>Web API Controller Class, voer NotificationsController in voor de Nameen klik vervolgens op New.

    Notitie

    Als u Visual Studio 2019-volgt, kiest u de API-controller met lees-/schrijfacties sjabloon.

  3. Voeg de volgende naamruimten toe aan het begin van het bestand.

    using System.ComponentModel.DataAnnotations;
    using System.Net;
    using System.Threading;
    using System.Threading.Tasks;
    using Microsoft.AspNetCore.Authorization;
    using Microsoft.AspNetCore.Mvc;
    using PushDemoApi.Models;
    using PushDemoApi.Services;
    
  4. Werk de sjablooncontroller bij zodat deze is afgeleid van ControllerBase- en is ingericht met het kenmerk ApiController.

    [ApiController]
    [Route("api/[controller]")]
    public class NotificationsController : ControllerBase
    {
        // Templated methods here
    }
    

    Notitie

    De Controller basisklasse biedt ondersteuning voor weergaven, maar dit is in dit geval niet nodig en dus kan ControllerBase- worden gebruikt. Als u Visual Studio 2019volgt, kunt u deze stap overslaan.

  5. Als u ervoor hebt gekozen om de sectie Clients verifiëren te voltooien met behulp van een API-sleutel, moet u ook de NotificationsController voorzien van het kenmerk Autoriseren.

    [Authorize]
    
  6. Werk de constructor bij om het geregistreerde exemplaar van INotificationService als argument te accepteren en toe te wijzen aan een alleen-lezen lid.

    readonly INotificationService _notificationService;
    
    public NotificationsController(INotificationService notificationService)
    {
        _notificationService = notificationService;
    }
    
  7. Wijzig in launchSettings.json (in de map Eigenschappen) de launchUrl- van weatherforecast in API/notifications zodat deze overeenkomt met de URL die is opgegeven in het kenmerk RegistrationsControllerRoute.

  8. Start de foutopsporing (Command + Enter) om te controleren of de app werkt met de nieuwe NotificationsController- en retourneert een 401 Niet-geautoriseerde status.

    Notitie

    Visual Studio start de app mogelijk niet automatisch in de browser. U gebruikt Postman- om de API vanaf dit punt te testen.

  9. Stel op een nieuw tabblad Postman de aanvraag in op GET-. Voer het onderstaande adres in en vervang de tijdelijke aanduiding <applicationUrl> door de https applicationUrl gevonden in Properties>launchSettings.json.

    <applicationUrl>/api/notifications
    

    Notitie

    De applicationUrl- moet 'https://localhost:5001' zijn voor het standaardprofiel. Als u IIS- gebruikt (standaard in Visual Studio 2019- in Windows), moet u in plaats daarvan de applicationUrl- gebruiken die is opgegeven in het iisSettings item. U ontvangt een 404-antwoord als het adres onjuist is.

  10. Als u ervoor hebt gekozen om de Clients verifiëren met behulp van een sectie API-sleutel te voltooien, moet u de aanvraagheaders zo configureren dat deze uw apikey waarde bevatten.

    Sleutel Waarde
    apikey <your_api_key>
  11. Klik op de knop Verzenden.

    Notitie

    U ontvangt een 200 OK status met een aantal JSON- inhoud.

    Als u een SSL-certificaatverificatie ontvangt waarschuwing, kunt u de verificatie van het SSL-certificaat Postman uitschakelen in de Instellingen.

  12. Vervang de sjabloonklassemethoden in NotificationsController.cs 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)
    {
        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();
    }
    

De API-app maken

U maakt nu een API-app in Azure App Service- voor het hosten van de back-endservice.

  1. Meld u aan bij de Azure Portal.

  2. Klik op Een resource maken, zoek en kies API-appen klik vervolgens op Maken.

  3. Werk de volgende velden bij en klik vervolgens op maken.

    app-naam:
    Voer een wereldwijd unieke naam in voor de API-app

    -abonnement:
    Kies hetzelfde doel Abonnement u de Notification Hub hebt gemaakt.

    resourcegroep:
    Kies dezelfde resourcegroep u de Notification Hub hebt gemaakt.

    App Service-plan/-locatie:
    Een nieuw App Service-plan maken

    Notitie

    Wijzig van de standaardoptie in een abonnement met SSL--ondersteuning. Anders moet u de juiste stappen uitvoeren bij het werken met de mobiele app om te voorkomen dat http- aanvragen worden geblokkeerd.

    Application Insights:
    Behoud de voorgestelde optie (er wordt een nieuwe resource gemaakt met die naam) of kies een bestaande resource.

  4. Zodra de API-app is ingericht, gaat u naar die resource.

  5. Noteer de eigenschap URL in de samenvatting van de Essentials boven aan de Overzichts-. Deze URL is uw back-endeindpunt dat verderop in deze zelfstudie wordt gebruikt.

    Notitie

    De URL gebruikt de naam van de API-app die u eerder hebt opgegeven, met de indeling https://<app_name>.azurewebsites.net.

  6. Selecteer Configuratie- in de lijst (onder Instellingen).

  7. Klik voor elk van de onderstaande instellingen op Nieuwe toepassingsinstelling om de naam en een waardein te voeren en klik vervolgens op OK-.

    Naam Waarde
    Authentication:ApiKey <api_key_value>
    NotificationHub:Name <hub_name_value>
    NotificationHub:ConnectionString <hub_connection_string_value>

    Notitie

    Dit zijn dezelfde instellingen die u eerder hebt gedefinieerd in de gebruikersinstellingen. U moet deze kunnen kopiëren. De instelling Authentication:ApiKey is alleen vereist als u ervoor kiest om de Clients te verifiëren met behulp van een sectie API-sleutel. Voor productiescenario's kunt u opties bekijken, zoals Azure KeyVault-. Deze zijn toegevoegd als toepassingsinstellingen voor eenvoud in dit geval.

  8. Zodra alle toepassingsinstellingen zijn toegevoegd, klikt u op Opslaanen Doorgaan.

De back-endservice publiceren

Vervolgens implementeert u de app in de API-app om deze toegankelijk te maken vanaf alle apparaten.

Notitie

De volgende stappen zijn specifiek voor Visual Studio voor Mac. Als u Visual Studio 2019- in Windows volgt, is de publicatiestroom anders. Zie Publiceren naar Azure App Service in Windows.

  1. Wijzig de configuratie van Debug in Release als u dit nog niet hebt gedaan.

  2. Control + Klik op het project PushDemoApi en kies vervolgens Publiceren naar Azure... in het menu Publiceren.

  3. Volg de verificatiestroom als u hierom wordt gevraagd. Gebruik het account dat u in de vorige hebt gebruikt om de sectie API-app te maken.

  4. Selecteer de Azure App Service API-app die u eerder hebt gemaakt in de lijst als publicatiedoel en klik vervolgens op Publiceren.

Nadat u de wizard hebt voltooid, wordt de app gepubliceerd naar Azure en wordt de app vervolgens geopend. Noteer de URL als u dit nog niet hebt gedaan. Deze URL is uw back-endeindpunt dat verderop in deze zelfstudie wordt gebruikt.

De gepubliceerde API valideren

  1. In Postman een nieuw tabblad openen, stelt u de aanvraag in op PUT- en voert u het onderstaande adres in. Vervang de tijdelijke aanduiding door het basisadres dat u in de vorige de back-endservice sectie publiceert.

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

    Notitie

    Het basisadres moet de indeling hebben https://<app_name>.azurewebsites.net/

  2. Als u ervoor hebt gekozen om de Clients verifiëren met behulp van een sectie API-sleutel te voltooien, moet u de aanvraagheaders zo configureren dat deze uw apikey waarde bevatten.

    Sleutel Waarde
    apikey <your_api_key>
  3. Kies de onbewerkte optie voor de Hoofdtekst, kies vervolgens JSON- in de lijst met indelingsopties en neem vervolgens een tijdelijke aanduiding op JSON- inhoud:

    {}
    
  4. Klik op verzenden.

    Notitie

    U ontvangt een 422 UnprocessableEntity status van de service.

  5. Voer stap 1-4 opnieuw uit, maar deze keer geeft u het eindpunt voor aanvragen op om te valideren dat u een 400 Ongeldige aanvraag ontvangt antwoord.

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

Notitie

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

Een platformoverschrijdende Xamarin.Forms-toepassing maken

In deze sectie bouwt u een Xamarin.Forms mobiele toepassing die pushmeldingen implementeert op een platformoverschrijdende manier.

Hiermee kunt u zich registreren en de registratie van een Notification Hub ongedaan maken via de back-endservice die u hebt gemaakt.

Er wordt een waarschuwing weergegeven wanneer een actie wordt opgegeven en de app zich op de voorgrond bevindt. Anders worden meldingen weergegeven in het meldingencentrum.

Notitie

Normaal gesproken voert u de registratie-acties (en deregistratie) uit tijdens het juiste punt in de levenscyclus van de toepassing (of als onderdeel van uw first-run-ervaring) zonder expliciete invoer voor gebruikersregistratie/registratie. In dit voorbeeld is echter expliciete gebruikersinvoer vereist om deze functionaliteit gemakkelijker te kunnen verkennen en testen.

De Xamarin.Forms-oplossing maken

  1. Maak in Visual Studioeen nieuwe Xamarin.Forms-oplossing met behulp van Blank Forms App als sjabloon en voer PushDemo- in voor de Projectnaam.

    Notitie

    Controleer in het dialoogvenster Lege formulieren-app configureren of de organisatie-id overeenkomt met de waarde die u eerder hebt gebruikt en dat zowel Android- als iOS- doelen zijn gecontroleerd.

  2. Control + Klik op in de oplossing PushDemo en kies vervolgens NuGet-pakketten bijwerken.

  3. Control + Klik op in de oplossing PushDemo en kies vervolgens NuGet-pakketten beheren..

  4. Zoek Newtonsoft.Json- en controleer of deze is ingeschakeld.

  5. Klik op Pakketten toevoegenen klik vervolgens op Accepteren wanneer u wordt gevraagd de licentievoorwaarden te accepteren.

  6. Bouw en voer de app uit op elk doelplatform (Command + Enter) om te testen of de sjabloon-app wordt uitgevoerd op uw apparaat(en).

De platformoverschrijdende onderdelen implementeren

  1. Control + Klik op in het project PushDemo, kies nieuwe map in het menu toevoegen en klik vervolgens op toevoegen met modellen als mapnaam.

  2. Control + Klik op in de map Modellen en kies vervolgens Nieuw bestand... in het menu Toevoegen.

  3. Selecteer >Lege klasse, voer DeviceInstallation.csin en voeg vervolgens de volgende implementatie toe.

    using System.Collections.Generic;
    using Newtonsoft.Json;
    
    namespace PushDemo.Models
    {
        public class DeviceInstallation
        {
            [JsonProperty("installationId")]
            public string InstallationId { get; set; }
    
            [JsonProperty("platform")]
            public string Platform { get; set; }
    
            [JsonProperty("pushChannel")]
            public string PushChannel { get; set; }
    
            [JsonProperty("tags")]
            public List<string> Tags { get; set; } = new List<string>();
        }
    }
    
  4. Voeg een Lege opsomming toe aan de map Models met de naam PushDemoAction.cs met de volgende implementatie.

    namespace PushDemo.Models
    {
        public enum PushDemoAction
        {
            ActionA,
            ActionB
        }
    }
    
  5. Voeg een nieuwe map toe aan het project PushDemo met de naam Services voeg vervolgens een Lege klasse toe aan die map met de naam ServiceContainer.cs met de volgende implementatie.

    using System;
    using System.Collections.Generic;
    
    namespace PushDemo.Services
    {
       public static class ServiceContainer
       {
           static readonly Dictionary<Type, Lazy<object>> services
               = new Dictionary<Type, Lazy<object>>();
    
           public static void Register<T>(Func<T> function)
               => services[typeof(T)] = new Lazy<object>(() => function());
    
           public static T Resolve<T>()
               => (T)Resolve(typeof(T));
    
           public static object Resolve(Type type)
           {
               {
                   if (services.TryGetValue(type, out var service))
                       return service.Value;
    
                   throw new KeyNotFoundException($"Service not found for type '{type}'");
               }
           }
       }
    }
    

    Notitie

    Dit is een ingekorte versie van de ServiceContainer klasse uit de XamCAT opslagplaats. Deze wordt gebruikt als een lichtgewicht IoC-container (Inversion of Control).

  6. Voeg een Empty Interface- toe aan de map Services met de naam IDeviceInstallationService.csen voeg vervolgens de volgende code toe.

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

    Notitie

    Deze interface wordt later door elk doel geïmplementeerd en opgestart om de platformspecifieke functionaliteit te bieden en DeviceInstallation informatie die vereist is voor de back-endservice.

  7. Voeg nog een Empty Interface toe aan de map Services met de naam INotificationRegistrationService.csen voeg vervolgens de volgende code toe.

    using System.Threading.Tasks;
    
    namespace PushDemo.Services
    {
        public interface INotificationRegistrationService
        {
            Task DeregisterDeviceAsync();
            Task RegisterDeviceAsync(params string[] tags);
            Task RefreshRegistrationAsync();
        }
    }
    

    Notitie

    Hiermee wordt de interactie tussen de client en de back-endservice afgehandeld.

  8. Voeg nog een Lege interface toe aan de map Services met de naam INotificationActionService.csen voeg vervolgens de volgende code toe.

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

    Notitie

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

  9. Voeg een Empty Interface toe aan de map Services met de naam IPushDemoNotificationActionService.cs die is afgeleid van de INotificationActionService, met de volgende implementatie.

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

    Notitie

    Dit type is specifiek voor de PushDemo-toepassing en gebruikt de opsomming PushDemoAction om de actie te identificeren die op een sterk getypte manier wordt geactiveerd.

  10. Voeg een Lege klasse toe aan de map Services met de naam NotificationRegistrationService.cs het implementeren van de INotificationRegistrationService met de volgende code.

    using System;
    using System.Net.Http;
    using System.Text;
    using System.Threading.Tasks;
    using Newtonsoft.Json;
    using PushDemo.Models;
    using Xamarin.Essentials;
    
    namespace PushDemo.Services
    {
        public class NotificationRegistrationService : INotificationRegistrationService
        {
            const string RequestUrl = "api/notifications/installations";
            const string CachedDeviceTokenKey = "cached_device_token";
            const string CachedTagsKey = "cached_tags";
    
            string _baseApiUrl;
            HttpClient _client;
            IDeviceInstallationService _deviceInstallationService;
    
            public NotificationRegistrationService(string baseApiUri, string apiKey)
            {
                _client = new HttpClient();
                _client.DefaultRequestHeaders.Add("Accept", "application/json");
                _client.DefaultRequestHeaders.Add("apikey", apiKey);
    
                _baseApiUrl = baseApiUri;
            }
    
            IDeviceInstallationService DeviceInstallationService
                => _deviceInstallationService ??
                    (_deviceInstallationService = ServiceContainer.Resolve<IDeviceInstallationService>());
    
            public async Task DeregisterDeviceAsync()
            {
                var cachedToken = await SecureStorage.GetAsync(CachedDeviceTokenKey)
                    .ConfigureAwait(false);
    
                if (cachedToken == null)
                    return;
    
                var deviceId = DeviceInstallationService?.GetDeviceId();
    
                if (string.IsNullOrWhiteSpace(deviceId))
                    throw new Exception("Unable to resolve an ID for the device.");
    
                await SendAsync(HttpMethod.Delete, $"{RequestUrl}/{deviceId}")
                    .ConfigureAwait(false);
    
                SecureStorage.Remove(CachedDeviceTokenKey);
                SecureStorage.Remove(CachedTagsKey);
            }
    
            public async Task RegisterDeviceAsync(params string[] tags)
            {
                var deviceInstallation = DeviceInstallationService?.GetDeviceInstallation(tags);
    
                await SendAsync<DeviceInstallation>(HttpMethod.Put, RequestUrl, deviceInstallation)
                    .ConfigureAwait(false);
    
                await SecureStorage.SetAsync(CachedDeviceTokenKey, deviceInstallation.PushChannel)
                    .ConfigureAwait(false);
    
                await SecureStorage.SetAsync(CachedTagsKey, JsonConvert.SerializeObject(tags));
            }
    
            public async Task RefreshRegistrationAsync()
            {
                var cachedToken = await SecureStorage.GetAsync(CachedDeviceTokenKey)
                    .ConfigureAwait(false);
    
                var serializedTags = await SecureStorage.GetAsync(CachedTagsKey)
                    .ConfigureAwait(false);
    
                if (string.IsNullOrWhiteSpace(cachedToken) ||
                    string.IsNullOrWhiteSpace(serializedTags) ||
                    string.IsNullOrWhiteSpace(DeviceInstallationService.Token) ||
                    cachedToken == DeviceInstallationService.Token)
                    return;
    
                var tags = JsonConvert.DeserializeObject<string[]>(serializedTags);
    
                await RegisterDeviceAsync(tags);
            }
    
            async Task SendAsync<T>(HttpMethod requestType, string requestUri, T obj)
            {
                string serializedContent = null;
    
                await Task.Run(() => serializedContent = JsonConvert.SerializeObject(obj))
                    .ConfigureAwait(false);
    
                await SendAsync(requestType, requestUri, serializedContent);
            }
    
            async Task SendAsync(
                HttpMethod requestType,
                string requestUri,
                string jsonRequest = null)
            {
                var request = new HttpRequestMessage(requestType, new Uri($"{_baseApiUrl}{requestUri}"));
    
                if (jsonRequest != null)
                    request.Content = new StringContent(jsonRequest, Encoding.UTF8, "application/json");
    
                var response = await _client.SendAsync(request).ConfigureAwait(false);
    
                response.EnsureSuccessStatusCode();
            }
        }
    }
    

    Notitie

    Het argument apiKey is alleen vereist als u ervoor hebt gekozen om de clients te verifiëren met behulp van een sectie API-sleutel.

  11. Voeg een Empty Class toe aan de map Services met de naam PushDemoNotificationActionService.cs het implementeren van de IPushDemoNotificationActionService met de volgende code.

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using PushDemo.Models;
    
    namespace PushDemo.Services
    {
        public class PushDemoNotificationActionService : IPushDemoNotificationActionService
        {
            readonly Dictionary<string, PushDemoAction> _actionMappings = new Dictionary<string, PushDemoAction>
            {
                { "action_a", PushDemoAction.ActionA },
                { "action_b", PushDemoAction.ActionB }
            };
    
            public event EventHandler<PushDemoAction> ActionTriggered = delegate { };
    
            public void TriggerAction(string action)
            {
                if (!_actionMappings.TryGetValue(action, out var pushDemoAction))
                    return;
    
                List<Exception> exceptions = new List<Exception>();
    
                foreach (var handler in ActionTriggered?.GetInvocationList())
                {
                    try
                    {
                        handler.DynamicInvoke(this, pushDemoAction);
                    }
                    catch (Exception ex)
                    {
                        exceptions.Add(ex);
                    }
                }
    
                if (exceptions.Any())
                    throw new AggregateException(exceptions);
            }
        }
    }
    
  12. Voeg een Lege klasse toe aan het project PushDemo met de naam Config.cs met de volgende implementatie.

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

    Notitie

    Dit wordt gebruikt als een eenvoudige manier om 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. U doet dit in de volgende stap.

    Het veld ApiKey is alleen vereist als u ervoor kiest om de clients te verifiëren met behulp van een sectie API-sleutel.

  13. Voeg deze keer nog een Lege klasse toe aan het project PushDemoConfig.local_secrets.cs met de volgende implementatie.

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

    Notitie

    Vervang de waarden van de tijdelijke aanduiding door uw eigen waarden. U moet deze noteren toen u de back-endservice maakte. De API-app--URL moet https://<api_app_name>.azurewebsites.net/zijn. Vergeet niet om *.local_secrets.* toe te voegen aan uw Gitignore-bestand om te voorkomen dat dit bestand wordt doorgevoerd.

    Het veld ApiKey is alleen vereist als u ervoor kiest om de clients te verifiëren met behulp van een sectie API-sleutel.

  14. Voeg een Lege klasse toe aan het project PushDemoBootstrap.cs met de volgende implementatie.

    using System;
    using PushDemo.Services;
    
    namespace PushDemo
    {
        public static class Bootstrap
        {
            public static void Begin(Func<IDeviceInstallationService> deviceInstallationService)
            {
                ServiceContainer.Register(deviceInstallationService);
    
                ServiceContainer.Register<IPushDemoNotificationActionService>(()
                    => new PushDemoNotificationActionService());
    
                ServiceContainer.Register<INotificationRegistrationService>(()
                    => new NotificationRegistrationService(
                        Config.BackendServiceEndpoint,
                        Config.ApiKey));
            }
        }
    }
    

    Notitie

    De methode Begin wordt door elk platform aangeroepen wanneer de app wordt gestart bij het doorgeven van een platformspecifieke implementatie van IDeviceInstallationService.

    Het argument NotificationRegistrationServiceapiKey constructor is alleen vereist als u ervoor kiest om de clients te verifiëren met behulp van een sectie API-sleutel.

De platformoverschrijdende gebruikersinterface implementeren

  1. Open in het project PushDemoMainPage.xaml en vervang het besturingselement StackLayout door het volgende.

    <StackLayout VerticalOptions="EndAndExpand"  
                 HorizontalOptions="FillAndExpand"
                 Padding="20,40">
        <Button x:Name="RegisterButton"
                Text="Register"
                Clicked="RegisterButtonClicked" />
        <Button x:Name="DeregisterButton"
                Text="Deregister"
                Clicked="DeregisterButtonClicked" />
    </StackLayout>
    
  2. Voeg nu in MainPage.xaml.cseen alleen-lezen back-upveld toe om een verwijzing op te slaan naar de INotificationRegistrationService-implementatie.

    readonly INotificationRegistrationService _notificationRegistrationService;
    
  3. Los in de MainPage constructor de INotificationRegistrationService-implementatie op met behulp van de ServiceContainer- en wijs deze toe aan het notificationRegistrationService backingveld.

    public MainPage()
    {
        InitializeComponent();
    
        _notificationRegistrationService =
            ServiceContainer.Resolve<INotificationRegistrationService>();
    }
    
  4. Implementeer de gebeurtenis-handlers voor de knoppen RegisterButton en DeregisterButtonOp gebeurtenissen geklikt die de bijbehorende Registeren/Deregister methoden aanroepen.

    void RegisterButtonClicked(object sender, EventArgs e)
        => _notificationRegistrationService.RegisterDeviceAsync().ContinueWith((task)
            => { ShowAlert(task.IsFaulted ?
                    task.Exception.Message :
                    $"Device registered"); });
    
    void DeregisterButtonClicked(object sender, EventArgs e)
        => _notificationRegistrationService.DeregisterDeviceAsync().ContinueWith((task)
            => { ShowAlert(task.IsFaulted ?
                    task.Exception.Message :
                    $"Device deregistered"); });
    
    void ShowAlert(string message)
        => MainThread.BeginInvokeOnMainThread(()
            => DisplayAlert("PushDemo", message, "OK").ContinueWith((task)
                => { if (task.IsFaulted) throw task.Exception; }));
    
  5. Controleer nu in App.xaml.csof naar de volgende naamruimten wordt verwezen.

    using PushDemo.Models;
    using PushDemo.Services;
    using Xamarin.Essentials;
    using Xamarin.Forms;
    
  6. Implementeer de gebeurtenis-handler voor de IPushDemoNotificationActionServiceActionTriggered gebeurtenis.

    void NotificationActionTriggered(object sender, PushDemoAction e)
        => ShowActionAlert(e);
    
    void ShowActionAlert(PushDemoAction action)
        => MainThread.BeginInvokeOnMainThread(()
            => MainPage?.DisplayAlert("PushDemo", $"{action} action received", "OK")
                .ContinueWith((task) => { if (task.IsFaulted) throw task.Exception; }));
    
  7. Los in de App constructor de IPushNotificationActionService-implementatie op met behulp van de ServiceContainer- en abonneer u op de IPushDemoNotificationActionServiceActionTriggered gebeurtenis.

    public App()
    {
        InitializeComponent();
    
        ServiceContainer.Resolve<IPushDemoNotificationActionService>()
            .ActionTriggered += NotificationActionTriggered;
    
        MainPage = new MainPage();
    }
    

    Notitie

    Dit is simpelweg om de ontvangst en doorgifte van pushmeldingsacties te demonstreren. Normaal gesproken worden deze 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 via de hoofdpagina Pagina, MainPage- in dit geval.

Het systeemeigen Android-project configureren voor pushmeldingen

Pakketnaam en machtigingen valideren

  1. Open in PushDemo.Androidde ProjectoptiesAndroid-toepassing in de sectie Build.

  2. Controleer of de pakketnaam overeenkomt met de waarde die u hebt gebruikt in de Firebase ConsolePushDemo project. De pakketnaam had de indeling com.<organization>.pushdemo.

  3. Stel de Minimale Android-versie in op Android 8.0- (API-niveau 26) en de Android-versie op het meest recente API-niveau.

    Notitie

    Alleen apparaten met API-niveau 26 en hoger worden ondersteund voor de doeleinden van deze zelfstudie, maar u kunt deze uitbreiden om apparaten met oudere versies te ondersteunen.

  4. Zorg ervoor dat de INTERNET-- en READ_PHONE_STATE-machtigingen zijn ingeschakeld onder Vereiste machtigingen.

  5. Klik op OK-

De Xamarin Google Play Services-basis en Xamarin.Firebase.Messaging-pakketten toevoegen

  1. Klik in PushDemo.Android-Control + klik op in de map Pakketten en kies vervolgens NuGet-pakketten beheren....

  2. Zoek naar Xamarin.GooglePlayServices.Base (niet Basement) en controleer of deze is ingeschakeld.

  3. Zoek Xamarin.Firebase.Messaging- en controleer of deze is ingeschakeld.

  4. Klik op Pakketten toevoegenen klik vervolgens op Accepteren wanneer u wordt gevraagd de licentievoorwaarden te accepteren.

Het JSON-bestand van Google Services toevoegen

  1. Control + Klik op in het PushDemo.Android project en kies vervolgens Bestaand bestand... in het menu toevoegen.

  2. Kies het google-services.json bestand dat u eerder hebt gedownload bij het instellen van het project PushDemo in de Firebase-console klik vervolgens op openen.

  3. Wanneer u hierom wordt gevraagd, kiest u ervoor om het bestand te kopiëren naar de map.

  4. Control + Klik op in het google-services.json-bestand vanuit het PushDemo.Android project en zorg ervoor dat GoogleServicesJson- is ingesteld als de buildactie.

Pushmeldingen voor Android verwerken

  1. Control + Klik op in het PushDemo.Android project, kies nieuwe map in het menu toevoegen en klik vervolgens op toevoegen met Services als mapnaam.

  2. Control + Klik op in de map Services en kies vervolgens Nieuw bestand... in het menu Toevoegen.

  3. Selecteer Algemeen>Lege klasse, voer DeviceInstallationService.cs in voor de Naamen klik vervolgens op Nieuwe de volgende implementatie toe te voegen.

    using System;
    using Android.App;
    using Android.Gms.Common;
    using PushDemo.Models;
    using PushDemo.Services;
    using static Android.Provider.Settings;
    
    namespace PushDemo.Droid.Services
    {
        public class DeviceInstallationService : IDeviceInstallationService
        {
            public string Token { get; set; }
    
            public bool NotificationsSupported
                => GoogleApiAvailability.Instance
                    .IsGooglePlayServicesAvailable(Application.Context) == ConnectionResult.Success;
    
            public string GetDeviceId()
                => Secure.GetString(Application.Context.ContentResolver, Secure.AndroidId);
    
            public DeviceInstallation GetDeviceInstallation(params string[] tags)
            {
                if (!NotificationsSupported)
                    throw new Exception(GetPlayServicesError());
    
                if (string.IsNullOrWhiteSpace(Token))
                    throw new Exception("Unable to resolve token for FCM");
    
                var installation = new DeviceInstallation
                {
                    InstallationId = GetDeviceId(),
                    Platform = "fcm",
                    PushChannel = Token
                };
    
                installation.Tags.AddRange(tags);
    
                return installation;
            }
    
            string GetPlayServicesError()
            {
                int resultCode = GoogleApiAvailability.Instance.IsGooglePlayServicesAvailable(Application.Context);
    
                if (resultCode != ConnectionResult.Success)
                    return GoogleApiAvailability.Instance.IsUserResolvableError(resultCode) ?
                               GoogleApiAvailability.Instance.GetErrorString(resultCode) :
                               "This device is not supported";
    
                return "An error occurred preventing the use of push notifications";
            }
        }
    }
    

    Notitie

    Deze klasse biedt een unieke id (met behulp van Secure.AndroidId) als onderdeel van de nettolading van de Notification Hub-registratie.

  4. Voeg nog een Lege klasse toe aan de map Services met de naam PushNotificationFirebaseMessagingService.csen voeg vervolgens de volgende implementatie toe.

    using Android.App;
    using Android.Content;
    using Firebase.Messaging;
    using PushDemo.Services;
    
    namespace PushDemo.Droid.Services
    {
        [Service]
        [IntentFilter(new[] { "com.google.firebase.MESSAGING_EVENT" })]
        public class PushNotificationFirebaseMessagingService : FirebaseMessagingService
        {
            IPushDemoNotificationActionService _notificationActionService;
            INotificationRegistrationService _notificationRegistrationService;
            IDeviceInstallationService _deviceInstallationService;
    
            IPushDemoNotificationActionService NotificationActionService
                => _notificationActionService ??
                    (_notificationActionService =
                    ServiceContainer.Resolve<IPushDemoNotificationActionService>());
    
            INotificationRegistrationService NotificationRegistrationService
                => _notificationRegistrationService ??
                    (_notificationRegistrationService =
                    ServiceContainer.Resolve<INotificationRegistrationService>());
    
            IDeviceInstallationService DeviceInstallationService
                => _deviceInstallationService ??
                    (_deviceInstallationService =
                    ServiceContainer.Resolve<IDeviceInstallationService>());
    
            public override void OnNewToken(string token)
            {
                DeviceInstallationService.Token = token;
    
                NotificationRegistrationService.RefreshRegistrationAsync()
                    .ContinueWith((task) => { if (task.IsFaulted) throw task.Exception; });
            }
    
            public override void OnMessageReceived(RemoteMessage message)
            {
                if(message.Data.TryGetValue("action", out var messageAction))
                    NotificationActionService.TriggerAction(messageAction);
            }
        }
    }
    
  5. Controleer in MainActivity.csof de volgende naamruimten zijn toegevoegd aan het begin van het bestand.

    using System;
    using Android.App;
    using Android.Content;
    using Android.Content.PM;
    using Android.OS;
    using Android.Runtime;
    using Firebase.Iid;
    using PushDemo.Droid.Services;
    using PushDemo.Services;
    
  6. Stel in MainActivity.csde LaunchMode- in op SingleTop-, zodat MainActivity- niet opnieuw wordt gemaakt wanneer deze wordt geopend.

    [Activity(
        Label = "PushDemo",
        LaunchMode = LaunchMode.SingleTop,
        Icon = "@mipmap/icon",
        Theme = "@style/MainTheme",
        MainLauncher = true,
        ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
    
  7. Voeg privé-eigenschappen en bijbehorende back-upvelden toe om een verwijzing naar de IPushNotificationActionService en IDeviceInstallationService implementaties op te slaan.

    IPushDemoNotificationActionService _notificationActionService;
    IDeviceInstallationService _deviceInstallationService;
    
    IPushDemoNotificationActionService NotificationActionService
        => _notificationActionService ??
            (_notificationActionService =
            ServiceContainer.Resolve<IPushDemoNotificationActionService>());
    
    IDeviceInstallationService DeviceInstallationService
        => _deviceInstallationService ??
            (_deviceInstallationService =
            ServiceContainer.Resolve<IDeviceInstallationService>());
    
  8. Implementeer de IOnSuccessListener interface om het Firebase token op te halen en op te slaan.

    public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity, Android.Gms.Tasks.IOnSuccessListener
    {
        ...
    
        public void OnSuccess(Java.Lang.Object result)
            => DeviceInstallationService.Token =
                result.Class.GetMethod("getToken").Invoke(result).ToString();
    }
    
  9. Voeg een nieuwe methode toe met de naam ProcessNotificationActions waarmee wordt gecontroleerd of een bepaalde intent een extra waarde heeft met de naam actie. Activeer die actie voorwaardelijk met behulp van de IPushDemoNotificationActionService implementatie.

    void ProcessNotificationActions(Intent intent)
    {
        try
        {
            if (intent?.HasExtra("action") == true)
            {
                var action = intent.GetStringExtra("action");
    
                if (!string.IsNullOrEmpty(action))
                    NotificationActionService.TriggerAction(action);
            }
        }
        catch (Exception ex)
        {
            System.Diagnostics.Debug.WriteLine(ex.Message);
        }
    }
    
  10. Overschrijf de methode OnNewIntent om methode ProcessNotificationActions aan te roepen.

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

    Notitie

    Aangezien de LaunchMode- voor de -activiteit is ingesteld op SingleTop-, wordt er een intent verzonden naar de bestaande Activiteit instantie via de Methode OnNewIntent in plaats van de methode OnCreate. Daarom moet u een binnenkomende intentie afhandelen in zowel OnCreate als OnNewIntent methoden.

  11. Werk de methode OnCreate bij om Bootstrap.Begin aan te roepen direct na de aanroep om base.OnCreate de platformspecifieke implementatie van IDeviceInstallationServicedoor te geven.

    Bootstrap.Begin(() => new DeviceInstallationService());
    
  12. Roep in dezelfde methode GetInstanceId- voorwaardelijk aan op het exemplaar van FirebaseApp, direct na de aanroep naar Bootstrap.Begin, en voeg MainActivity toe als de IOnSuccessListener.

    if (DeviceInstallationService.NotificationsSupported)
    {
        FirebaseInstanceId.GetInstance(Firebase.FirebaseApp.Instance)
            .GetInstanceId()
            .AddOnSuccessListener(this);
    }
    
  13. Nog steeds in OnCreateroept u ProcessNotificationActions aan direct na de aanroep om LoadApplication door te geven in de huidige Intentie.

    ...
    
    LoadApplication(new App());
    
    ProcessNotificationActions(Intent);
    

Notitie

U moet de app telkens wanneer u deze uitvoert opnieuw registreren en stoppen met een foutopsporingssessie om pushmeldingen te blijven ontvangen.

Het systeemeigen iOS-project configureren voor pushmeldingen

Info.plist en Entitlements.plist configureren

  1. Zorg ervoor dat u zich hebt aangemeld bij uw Apple Developer-account in Voorkeuren voor Visual Studio>Voorkeuren...>>Apple Developer Accounts en het juiste Certificate en Provisioning Profile is gedownload. U moet deze assets hebben gemaakt als onderdeel van de vorige stappen.

  2. Open in PushDemo.iOS-Info.plist en zorg ervoor dat de BundleIdentifier- overeenkomt met de waarde die is gebruikt voor het respectieve inrichtingsprofiel in de Apple Developer Portal. De BundleIdentifier- had de indeling com.<organization>.PushDemo.

  3. Stel in hetzelfde bestand minimale systeemversie in op 13.0.

    Notitie

    Alleen apparaten met iOS 13.0 en hoger worden ondersteund voor de doeleinden van deze zelfstudie, maar u kunt deze uitbreiden om apparaten met oudere versies te ondersteunen.

  4. Open de projectopties voor PushDemo.iOS- (dubbelklik op het project).

  5. Controleer in Projectoptiesonder Build > iOS Bundle Signingof uw Ontwikkelaarsaccount is geselecteerd onder Team. Controleer vervolgens of 'Automatisch ondertekenen beheren' is geselecteerd en uw handtekeningcertificaat en inrichtingsprofiel automatisch worden geselecteerd.

    Notitie

    Als uw handtekeningcertificaat en inrichtings profiel niet automatisch zijn geselecteerd, kiest u handmatige inrichtingen klikt u vervolgens op opties voor bundelondertekening. Zorg ervoor dat uw Team is geselecteerd voor handtekeningidentiteit en uw PushDemo specifiek inrichtingsprofiel is geselecteerd voor inrichtingsprofiel voor zowel Foutopsporing als -configuraties vrijgeven, zodat iPhone- in beide gevallen is geselecteerd voor de Platform-.

  6. Open in PushDemo.iOS-Rechten.plist en zorg ervoor dat Pushmeldingen inschakelen is ingeschakeld wanneer deze wordt weergegeven op het tabblad Rechten. Controleer vervolgens of de instelling APS-omgeving is ingesteld op ontwikkeling wanneer deze wordt weergegeven op het tabblad Bron.

Pushmeldingen voor iOS verwerken

  1. ControlKlik op in het project PushDemo.iOS, kies Nieuwe map in het menu toevoegen en klik vervolgens op toevoegen met Services als mapnaam.

  2. Control + Klik op in de map Services en kies vervolgens Nieuw bestand... in het menu Toevoegen.

  3. Selecteer Algemeen>Lege klasse, voer DeviceInstallationService.cs in voor de Naamen klik vervolgens op Nieuwe de volgende implementatie toe te voegen.

    using System;
    using PushDemo.Models;
    using PushDemo.Services;
    using UIKit;
    
    namespace PushDemo.iOS.Services
    {
        public class DeviceInstallationService : IDeviceInstallationService
        {
            const int SupportedVersionMajor = 13;
            const int SupportedVersionMinor = 0;
    
            public string Token { get; set; }
    
            public bool NotificationsSupported
                => UIDevice.CurrentDevice.CheckSystemVersion(SupportedVersionMajor, SupportedVersionMinor);
    
            public string GetDeviceId()
                => UIDevice.CurrentDevice.IdentifierForVendor.ToString();
    
            public DeviceInstallation GetDeviceInstallation(params string[] tags)
            {
                if (!NotificationsSupported)
                    throw new Exception(GetNotificationsSupportError());
    
                if (string.IsNullOrWhiteSpace(Token))
                    throw new Exception("Unable to resolve token for APNS");
    
                var installation = new DeviceInstallation
                {
                    InstallationId = GetDeviceId(),
                    Platform = "apns",
                    PushChannel = Token
                };
    
                installation.Tags.AddRange(tags);
    
                return installation;
            }
    
            string GetNotificationsSupportError()
            {
                if (!NotificationsSupported)
                    return $"This app only supports notifications on iOS {SupportedVersionMajor}.{SupportedVersionMinor} and above. You are running {UIDevice.CurrentDevice.SystemVersion}.";
    
                if (Token == null)
                    return $"This app can support notifications but you must enable this in your settings.";
    
    
                return "An error occurred preventing the use of push notifications";
            }
        }
    }
    

    Notitie

    Deze klasse biedt een unieke id (met behulp van de UIDevice.IdentifierForVendor waarde) en de nettolading van de Notification Hub-registratie.

  4. Voeg een nieuwe map toe aan het project PushDemo.iOS met de naam Extensions voeg vervolgens een Lege klasse toe aan die map met de naam NSDataExtensions.cs met de volgende implementatie.

    using System.Text;
    using Foundation;
    
    namespace PushDemo.iOS.Extensions
    {
        internal static class NSDataExtensions
        {
            internal static string ToHexString(this NSData data)
            {
                var bytes = data.ToArray();
    
                if (bytes == null)
                    return null;
    
                StringBuilder sb = new StringBuilder(bytes.Length * 2);
    
                foreach (byte b in bytes)
                    sb.AppendFormat("{0:x2}", b);
    
                return sb.ToString().ToUpperInvariant();
            }
        }
    }
    
  5. Controleer in AppDelegate.csof de volgende naamruimten zijn toegevoegd aan het begin van het bestand.

    using System;
    using System.Diagnostics;
    using System.Threading.Tasks;
    using Foundation;
    using PushDemo.iOS.Extensions;
    using PushDemo.iOS.Services;
    using PushDemo.Services;
    using UIKit;
    using UserNotifications;
    using Xamarin.Essentials;
    
  6. Voeg privé-eigenschappen en de bijbehorende back-upvelden toe om een verwijzing op te slaan naar de IPushDemoNotificationActionService, INotificationRegistrationServiceen IDeviceInstallationService-implementaties.

    IPushDemoNotificationActionService _notificationActionService;
    INotificationRegistrationService _notificationRegistrationService;
    IDeviceInstallationService _deviceInstallationService;
    
    IPushDemoNotificationActionService NotificationActionService
        => _notificationActionService ??
            (_notificationActionService =
            ServiceContainer.Resolve<IPushDemoNotificationActionService>());
    
    INotificationRegistrationService NotificationRegistrationService
        => _notificationRegistrationService ??
            (_notificationRegistrationService =
            ServiceContainer.Resolve<INotificationRegistrationService>());
    
    IDeviceInstallationService DeviceInstallationService
        => _deviceInstallationService ??
            (_deviceInstallationService =
            ServiceContainer.Resolve<IDeviceInstallationService>());
    
  7. Voeg de RegisterForRemoteNotifications methode toe om instellingen voor gebruikersmeldingen te registreren en vervolgens voor externe meldingen met APNS-.

    void RegisterForRemoteNotifications()
    {
        MainThread.BeginInvokeOnMainThread(() =>
        {
            var pushSettings = UIUserNotificationSettings.GetSettingsForTypes(
                UIUserNotificationType.Alert |
                UIUserNotificationType.Badge |
                UIUserNotificationType.Sound,
                new NSSet());
    
            UIApplication.SharedApplication.RegisterUserNotificationSettings(pushSettings);
            UIApplication.SharedApplication.RegisterForRemoteNotifications();
        });
    }
    
  8. Voeg de methode CompleteRegistrationAsync toe om de eigenschapswaarde IDeviceInstallationService.Token in te stellen. Vernieuw de registratie en sla het apparaattoken in de cache op als het is bijgewerkt sinds het laatst is opgeslagen.

    Task CompleteRegistrationAsync(NSData deviceToken)
    {
        DeviceInstallationService.Token = deviceToken.ToHexString();
        return NotificationRegistrationService.RefreshRegistrationAsync();
    }
    
  9. Voeg de methode ProcessNotificationActions toe voor het verwerken van de NSDictionary meldingsgegevens en het voorwaardelijk aanroepen van NotificationActionService.TriggerAction.

    void ProcessNotificationActions(NSDictionary userInfo)
    {
        if (userInfo == null)
            return;
    
        try
        {
            var actionValue = userInfo.ObjectForKey(new NSString("action")) as NSString;
    
            if (!string.IsNullOrWhiteSpace(actionValue?.Description))
                NotificationActionService.TriggerAction(actionValue.Description);
        }
        catch (Exception ex)
        {
            Debug.WriteLine(ex.Message);
        }
    }
    
  10. Overschrijf de methode RegisteredForRemoteNotifications het argument deviceToken door te geven aan de methode CompleteRegistrationAsync.

    public override void RegisteredForRemoteNotifications(
        UIApplication application,
        NSData deviceToken)
        => CompleteRegistrationAsync(deviceToken).ContinueWith((task)
            => { if (task.IsFaulted) throw task.Exception; });
    
  11. Overschrijf de methode ReceivedRemoteNotification door het argument userInfo door te geven aan de methode ProcessNotificationActions.

    public override void ReceivedRemoteNotification(
        UIApplication application,
        NSDictionary userInfo)
        => ProcessNotificationActions(userInfo);
    
  12. Overschrijf de FailedToRegisterForRemoteNotifications methode om de fout te registreren.

    public override void FailedToRegisterForRemoteNotifications(
        UIApplication application,
        NSError error)
        => Debug.WriteLine(error.Description);
    

    Notitie

    Dit is een tijdelijke aanduiding. U wilt de juiste logboekregistratie en foutafhandeling implementeren voor productiescenario's.

  13. Werk de methode FinishedLaunching bij om Bootstrap.Begin aan te roepen direct na de aanroep om Forms.Init door te geven aan de platformspecifieke implementatie van IDeviceInstallationService.

    Bootstrap.Begin(() => new DeviceInstallationService());
    
  14. In dezelfde methode vraagt u autorisatie voorwaardelijk aan en registreert u zich onmiddellijk na Bootstrap.Beginvoor externe meldingen.

    if (DeviceInstallationService.NotificationsSupported)
    {
        UNUserNotificationCenter.Current.RequestAuthorization(
                UNAuthorizationOptions.Alert |
                UNAuthorizationOptions.Badge |
                UNAuthorizationOptions.Sound,
                (approvalGranted, error) =>
                {
                    if (approvalGranted && error == null)
                        RegisterForRemoteNotifications();
                });
    }
    
  15. Nog steeds in FinishedLaunchingroept u ProcessNotificationActions direct na de aanroep naar LoadApplication als het argument opties het UIApplication.LaunchOptionsRemoteNotificationKey bevat het resulterende userInfo object door te geven.

    using (var userInfo = options?.ObjectForKey(
        UIApplication.LaunchOptionsRemoteNotificationKey) as NSDictionary)
            ProcessNotificationActions(userInfo);
    

De oplossing testen

U kunt nu het verzenden van meldingen testen via de back-endservice.

Een testmelding verzenden

  1. Open een nieuw tabblad in Postman-.

  2. Stel de aanvraag in op POST-en voer het volgende adres in:

    https://<app_name>.azurewebsites.net/api/notifications/requests
    
  3. Als u ervoor hebt gekozen om de Clients verifiëren met behulp van een sectie API-sleutel te voltooien, moet u de aanvraagheaders zo configureren dat deze uw apikey waarde bevatten.

    Sleutel Waarde
    apikey <your_api_key>
  4. Kies de onbewerkte optie voor de Hoofdtekst, kies vervolgens JSON- in de lijst met indelingsopties en neem vervolgens een tijdelijke aanduiding op JSON- inhoud:

    {
        "text": "Message from Postman!",
        "action": "action_a"
    }
    
  5. Selecteer de knop Code, die zich onder de knop Opslaan in de rechterbovenhoek van het venster bevindt. De aanvraag moet er ongeveer uitzien als in het volgende voorbeeld wanneer deze wordt weergegeven voor HTML- (afhankelijk van of u een apikey header hebt opgenomen):

    POST /api/notifications/requests HTTP/1.1
    Host: https://<app_name>.azurewebsites.net
    apikey: <your_api_key>
    Content-Type: application/json
    
    {
        "text": "Message from backend service",
        "action": "action_a"
    }
    
  6. Voer de PushDemo-toepassing uit op een of beide doelplatforms (Android- en iOS-).

    Notitie

    Als u test op Android- ervoor zorgt dat u niet in Foutopsporinguitvoert, of als de app is geïmplementeerd door de toepassing uit te voeren, moet u de app geforceerd sluiten en opnieuw starten vanuit het startprogramma.

  7. Tik in de PushDemo-app op de knop Registreren.

  8. Sluit in Postmanhet venster Codefragmenten genereren (als u dit nog niet hebt gedaan) en klik vervolgens op de knop Verzenden.

  9. Controleer of u een 200 OK antwoord krijgt in Postman- en de waarschuwing wordt weergegeven in de app met ActieA-actie ontvangen.

  10. Sluit de PushDemo-app en klik vervolgens nogmaals op de knop Verzenden in Postman-.

  11. Controleer of u een 200 OK antwoord krijgt in Postman-. Controleer of er een melding wordt weergegeven in het systeemvak voor de PushDemo-app met het juiste bericht.

  12. Tik op de melding om te bevestigen dat de app wordt geopend en de ActieA-actie waarschuwing heeft ontvangen.

  13. Wijzig in Postmande vorige aanvraagbody om een melding op de achtergrond te verzenden die action_b opgeeft in plaats van action_a voor de actie waarde.

    {
        "action": "action_b",
        "silent": true
    }
    
  14. Als de app nog steeds is geopend, klikt u op de knop Verzenden in Postman-.

  15. Controleer of u een 200 OK antwoord krijgt in Postman- en of de waarschuwing wordt weergegeven in de app met ActieB-actie ontvangen in plaats van ActieA-actieontvangen.

  16. Sluit de PushDemo-app en klik vervolgens nogmaals op de knop Verzenden in Postman-.

  17. Controleer of u een 200 OK antwoord krijgt in Postman- en dat de melding op de achtergrond niet wordt weergegeven in het systeemvak.

Probleemoplossing

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.

Controleer of u het basisadres correct hebt opgegeven in Postman- of in de configuratie van de mobiele app bij het testen via de client. Het basisadres moet indicatief worden https://<api_name>.azurewebsites.net/ of https://localhost:5001/ bij het lokaal testen.

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

Zorg ervoor dat u zich opnieuw registreert nadat u een foutopsporingssessie hebt gestart of gestopt. Het foutopsporingsprogramma zorgt ervoor dat er een nieuw Firebase--token wordt gegenereerd. De installatie van de Notification Hub moet ook worden bijgewerkt.

Een 401-statuscode ontvangen van de back-endservice

Controleer of u de apikey instelt aanvraagheader en 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 de clientconfiguratie, overeenkomt met de Authentication:ApiKey waarde voor de gebruikersinstelling die wordt gebruikt door de API-.

Als u test met een API-app, controleert u of de sleutelwaarde in het clientconfiguratiebestand overeenkomt met de -toepassingsinstelling Authentication:ApiKey die u gebruikt in de API-app.

Notitie

Als u deze instelling hebt gemaakt of gewijzigd nadat u de back-endservice hebt geïmplementeerd, moet u de service opnieuw starten om deze van kracht te laten worden.

Als u ervoor hebt gekozen om de Clients verifiëren met behulp van een sectie API-sleutel niet te voltooien, moet u ervoor zorgen dat u het kenmerk Autoriseren niet hebt toegepast op de klasse NotificationsController.

Een 404-statuscode ontvangen van de back-endservice

Controleer of het eindpunt en de HTTP-aanvraagmethode juist zijn. De eindpunten moeten bijvoorbeeld indicatief zijn:

  • [PUT]https://<api_name>.azurewebsites.net/api/notifications/installations
  • [DELETE]https://<api_name>.azurewebsites.net/api/notifications/installations/<installation_id>
  • [POST]https://<api_name>.azurewebsites.net/api/notifications/requests

Of wanneer u lokaal test:

  • [PUT]https://localhost:5001/api/notifications/installations
  • [DELETE]https://localhost:5001/api/notifications/installations/<installation_id>
  • [POST]https://localhost:5001/api/notifications/requests

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

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

Controleer of het testapparaat netwerkconnectiviteit heeft. Bepaal vervolgens de http-antwoordstatuscode door een onderbrekingspunt in te stellen om de eigenschapswaarde van de StatusCode in de HttpResponse-te controleren.

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

Stel een onderbrekingspunt in op de regels die deze 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 via Postman- met behulp van de juiste nettolading. Gebruik de werkelijke nettolading die is gemaakt door de clientcode voor het betreffende platform.

Bekijk de platformspecifieke configuratiesecties om ervoor te zorgen dat er geen stappen zijn gemist. Controleer of geschikte waarden worden omgezet voor installation id en token variabelen voor het juiste platform.

Kan een id voor het foutbericht van het apparaat niet oplossen

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

Volgende stappen

U moet nu een eenvoudige Xamarin.Forms-app hebben die is verbonden met een Notification Hub via een back-endservice en meldingen kan verzenden en ontvangen.

Waarschijnlijk moet u het voorbeeld dat in deze zelfstudie wordt gebruikt aanpassen aan uw eigen scenario. Het implementeren van robuustere foutafhandeling, logica voor opnieuw proberen en logboekregistratie wordt ook aanbevolen.

Visual Studio App Center- kan snel worden opgenomen in mobiele apps die analyse- en diagnostische gegevens om hulp te bieden bij het oplossen van problemen.