Zelfstudie: Pushmeldingen verzenden naar Xamarin.Forms-apps met behulp van Azure Notification Hubs via een back-endservice
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:
- Push Notification Services en Azure Notification Hubs instellen.
- een ASP.NET Core Web API-back-endtoepassing maken.
- Een platformoverschrijdende Xamarin.Forms-toepassing maken.
- het systeemeigen Android-project configureren voor pushmeldingen.
- Het systeemeigen iOS-project configureren voor pushmeldingen.
- De oplossing testen.
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:
- Een actief Apple Developer-account.
- Een fysiek iOS-apparaat dat is geregistreerd bij uw ontwikkelaarsaccount(met iOS 13.0 en hoger).
- Een .p12ontwikkelingscertificaat geïnstalleerd in uw sleutelhanger zodat u een app kunt uitvoeren op een fysiek apparaat.
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.
- Apple Developer Portal
- ASP.NET Core en web-API
- Google Firebase Console
- Microsoft Azure en Pushmeldingen verzenden naar iOS-apps met behulp van Azure Notification Hubs.
- Xamarin en Xamarin.Forms.
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
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.
Nadat u uw project hebt gemaakt, selecteert u Firebase toevoegen aan uw Android-app.
Voer op de pagina Firebase toevoegen aan uw Android-app de volgende stappen uit.
Voer voor de Android-pakketnaameen naam in voor uw pakket. Bijvoorbeeld:
com.<organization_identifier>.<package_name>
.Selecteer App-registreren.
Selecteer google-services.jsondownloaden. Sla het bestand vervolgens op in een lokale map voor later gebruik en selecteer Volgende.
downloaden
Selecteer Volgende.
Selecteer Console doorgaan
Notitie
Als de knop Doorgaan naar de console niet is ingeschakeld, kiest u deze stap overslaanvanwege de de installatie controleren.
Selecteer in de Firebase-console het tandwiel voor uw project. Selecteer vervolgens projectinstellingen.
Notitie
Als u het google-services.json bestand nog niet hebt gedownload, kunt u het downloaden op deze pagina.
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.
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.
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.
Selecteer in het scherm Een nieuwe id registreren het keuzerondje app-id's. Selecteer vervolgens Doorgaan.
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.pushmeldingen: controleer de optie Pushmeldingen in de sectie Capabilities.
Met deze actie wordt uw app-id gegenereerd en worden de gegevens bevestigd. Selecteer Doorgaanen selecteer registreren om de nieuwe app-id te bevestigen.
Nadat u registreren hebt geselecteerd, ziet u de nieuwe app-id als regelitem op de pagina Certificaten, Id's & Profielen.
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:
Een p12-pushcertificaat maken dat rechtstreeks naar Notification Hub kan worden geüpload (de oorspronkelijke benadering)
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
Voer op uw Mac het hulpprogramma Sleutelhangertoegang uit. Het kan worden geopend vanuit de Utilities map of de Andere map op launchpad.
Selecteer sleutelhangertoegang, vouw certificaatassistentuit en selecteer vervolgens Een certificaat aanvragen bij een certificeringsinstantie.
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.
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.
Voer een naam in voor het CSR-bestand (Certificate Signing Request) in Opslaan als, selecteer de locatie in Waaren selecteer vervolgens Opslaan.
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.
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.
Het venster Apple Push Notification Service TLS/SSL-certificaten wordt weergegeven. Selecteer de knop Certificaat maken onder de sectie Development TLS/SSL Certificate.
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.
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.
Nadat de portal het certificaat heeft gemaakt, selecteert u de knop Downloaden. Sla het certificaat op en onthoud de locatie waarop het is opgeslagen.
Het certificaat wordt gedownload en opgeslagen op uw computer in de map Downloads.
Notitie
Standaard heeft het gedownloade ontwikkelingscertificaat de naam aps_development.cer.
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:
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.
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.
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
Noteer de volgende details:
- voorvoegsel voor app-id's (team-id)
- bundel-id
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.
Klik op de knop + (of de knop Een sleutel maken) om een nieuwe sleutel te maken.
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.
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.
Klik in Sleutelsop de sleutel die u hebt gemaakt (of een bestaande sleutel als u ervoor hebt gekozen om die te gebruiken).
Noteer de sleutel-id waarde.
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
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.
Selecteer
onder Development als het inrichtingsprofieltype en selecteer vervolgensDoorgaan .Selecteer vervolgens de app-id die u hebt gemaakt in de vervolgkeuzelijst App-id en selecteer Doorgaan.
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-.
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.
Selecteer in het venster Certificaten selecteren het ontwikkelingscertificaat dat u hebt gemaakt. Selecteer vervolgens Doorgaan.
Selecteer vervolgens de apparaten die u wilt gebruiken voor testen en selecteer Doorgaan.
Kies ten slotte een naam voor het profiel in Inrichtingsprofielnaamen selecteer genereren.
Wanneer het nieuwe inrichtingsprofiel wordt gemaakt, selecteert u downloaden. Onthoud de locatie waarop deze is opgeslagen.
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.
Meld u aan bij Azure.
Klik op Een resource maken, zoek en kies Notification Hub-en klik vervolgens op Maken.
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 behoudenNotitie
Tenzij u het maximum aantal hubs in de gratis laag hebt bereikt.
Zodra de Notification Hub is ingericht, gaat u naar die resource.
Navigeer naar uw nieuwe Notification Hub-.
Selecteer toegangsbeleid in de lijst (onder BEHEREN).
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
Selecteer Certificaat.
Selecteer het bestandspictogram.
Selecteer het .p12-bestand dat u eerder hebt geëxporteerd en selecteer vervolgens Open.
Geef indien nodig het juiste wachtwoord op.
Selecteer Sandbox- modus.
Selecteer opslaan.
OPTIE 2: Verificatie op basis van tokens gebruiken
Selecteer token.
Voer de volgende waarden in die u eerder hebt verkregen:
- sleutel-id
- bundel-id
- team-id
- token
Kies Sandbox-.
Selecteer opslaan.
Uw Notification Hub configureren met FCM-gegevens
- Selecteer Google- (GCM/FCM) in de sectie Instellingen in het linkermenu.
- Voer de -serversleutel in die u hebt genoteerd in de Google Firebase Console.
- 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
Selecteer in Visual StudioFile>New Solution.
Selecteer .NET Core>App>ASP.NET Core>API>Volgende.
Selecteer in het dialoogvenster Uw nieuwe ASP.NET Core Web-API configurerenTarget Framework van .NET Core 3.1-.
Voer PushDemoApi- in voor de projectnaam en selecteer maken.
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:
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.
Klik op Ja wanneer u wordt gevraagd om het nieuwe certificaat te installeren en te vertrouwenen voer vervolgens het wachtwoord voor de sleutelhanger in.
Vouw de map Controllers uit en verwijder WeatherForecastController.cs.
Verwijder WeatherForecast.cs.
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 toegangsbeleidNotitie
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-.
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.
Control + Klik op in het project PushDemoApi, kies nieuwe map in het menu toevoegen en klik vervolgens op toevoegen met Authentication als de mapnaam.
Control + klik op in de map Authentication en kies New File... in het menu Toevoegen.
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; } } }
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.
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.
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); }
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.
Control + Klik op in de map Afhankelijkheden en kies vervolgens NuGet-pakketten beheren....
Zoek Microsoft.Azure.NotificationHubs en controleer of deze is ingeschakeld.
Klik op Pakketten toevoegenen klik vervolgens op Accepteren wanneer u wordt gevraagd de licentievoorwaarden te accepteren.
Control + Klik op in het project PushDemoApi, kies nieuwe map in het menu toevoegen en klik vervolgens op toevoegen met modellen als de mapnaam.
Control + Klik op in de map Modellen en kies vervolgens Nieuw bestand... in het menu Toevoegen.
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.
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>(); } }
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; } } }
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; } } }
Voeg een nieuwe map toe aan het project PushDemoApi met de naam Services.
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); } }
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.
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
Control + Klik op in de map Controllers en kies vervolgens Nieuw bestand... in het menu Toevoegen.
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.
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;
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.
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]
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; }
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.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.
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.
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> 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.
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.
Meld u aan bij de Azure Portal.
Klik op Een resource maken, zoek en kies API-appen klik vervolgens op Maken.
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 makenNotitie
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.Zodra de API-app is ingericht, gaat u naar die resource.
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
.Selecteer Configuratie- in de lijst (onder Instellingen).
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.
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.
Wijzig de configuratie van Debug in Release als u dit nog niet hebt gedaan.
Control + Klik op het project PushDemoApi en kies vervolgens Publiceren naar Azure... in het menu Publiceren.
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.
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
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/
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> Kies de onbewerkte optie voor de Hoofdtekst, kies vervolgens JSON- in de lijst met indelingsopties en neem vervolgens een tijdelijke aanduiding op JSON- inhoud:
{}
Klik op verzenden.
Notitie
U ontvangt een 422 UnprocessableEntity status van de service.
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
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 deorganisatie-id overeenkomt met de waarde die u eerder hebt gebruikt en dat zowel Android- alsiOS- doelen zijn gecontroleerd.Control + Klik op in de oplossing PushDemo en kies vervolgens NuGet-pakketten bijwerken.
Control + Klik op in de oplossing PushDemo en kies vervolgens NuGet-pakketten beheren..
Zoek Newtonsoft.Json- en controleer of deze is ingeschakeld.
Klik op Pakketten toevoegenen klik vervolgens op Accepteren wanneer u wordt gevraagd de licentievoorwaarden te accepteren.
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
Control + Klik op in het project PushDemo, kies nieuwe map in het menu toevoegen en klik vervolgens op toevoegen met modellen als mapnaam.
Control + Klik op in de map Modellen en kies vervolgens Nieuw bestand... in het menu Toevoegen.
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>(); } }
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 } }
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).
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.
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.
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.
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.
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.
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); } } }
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.
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.
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
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>
Voeg nu in MainPage.xaml.cseen alleen-lezen back-upveld toe om een verwijzing op te slaan naar de INotificationRegistrationService-implementatie.
readonly INotificationRegistrationService _notificationRegistrationService;
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>(); }
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; }));
Controleer nu in App.xaml.csof naar de volgende naamruimten wordt verwezen.
using PushDemo.Models; using PushDemo.Services; using Xamarin.Essentials; using Xamarin.Forms;
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; }));
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
Open in PushDemo.Androidde ProjectoptiesAndroid-toepassing in de sectie Build.
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
.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.
Zorg ervoor dat de INTERNET-- en READ_PHONE_STATE-machtigingen zijn ingeschakeld onder Vereiste machtigingen.
Klik op OK-
De Xamarin Google Play Services-basis en Xamarin.Firebase.Messaging-pakketten toevoegen
Klik in PushDemo.Android-Control + klik op in de map Pakketten en kies vervolgens NuGet-pakketten beheren....
Zoek naar Xamarin.GooglePlayServices.Base (niet Basement) en controleer of deze is ingeschakeld.
Zoek Xamarin.Firebase.Messaging- en controleer of deze is ingeschakeld.
Klik op Pakketten toevoegenen klik vervolgens op Accepteren wanneer u wordt gevraagd de licentievoorwaarden te accepteren.
Het JSON-bestand van Google Services toevoegen
Control + Klik op in het
PushDemo.Android
project en kies vervolgens Bestaand bestand... in het menu toevoegen.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.
Wanneer u hierom wordt gevraagd, kiest u ervoor om het bestand te kopiëren naar de map.
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
Control + Klik op in het
PushDemo.Android
project, kies nieuwe map in het menu toevoegen en klik vervolgens op toevoegen met Services als mapnaam.Control + Klik op in de map Services en kies vervolgens Nieuw bestand... in het menu Toevoegen.
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.
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); } } }
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;
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)]
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>());
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(); }
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); } }
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 opSingleTop- , wordt er eenintent verzonden naar de bestaandeActiviteit instantie via deMethode OnNewIntent in plaats van de methodeOnCreate . Daarom moet u een binnenkomende intentie afhandelen in zowelOnCreate alsOnNewIntent methoden.Werk de methode OnCreate bij om
Bootstrap.Begin
aan te roepen direct na de aanroep ombase.OnCreate
de platformspecifieke implementatie van IDeviceInstallationServicedoor te geven.Bootstrap.Begin(() => new DeviceInstallationService());
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); }
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
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.
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
.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.
Open de projectopties voor PushDemo.iOS- (dubbelklik op het project).
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-.
Open in
PushDemo.iOS- Rechten.plist en zorg ervoor datPushmeldingen inschakelen is ingeschakeld wanneer deze wordt weergegeven op het tabbladRechten . Controleer vervolgens of de instellingAPS-omgeving is ingesteld op ontwikkeling wanneer deze wordt weergegeven op het tabbladBron .
Pushmeldingen voor iOS verwerken
Control Klik op in het projectPushDemo.iOS , kiesNieuwe map in het menutoevoegen en klik vervolgens op toevoegen met Services als mapnaam. Control + Klik op in de map Services en kies vervolgens Nieuw bestand... in het menu Toevoegen.
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.
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(); } } }
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;
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>());
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(); }); }
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(); }
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); } }
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; });
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);
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.
Werk de methode FinishedLaunching bij om
Bootstrap.Begin
aan te roepen direct na de aanroep omForms.Init
door te geven aan de platformspecifieke implementatie van IDeviceInstallationService.Bootstrap.Begin(() => new DeviceInstallationService());
In dezelfde methode vraagt u autorisatie voorwaardelijk aan en registreert u zich onmiddellijk na
Bootstrap.Begin
voor externe meldingen.if (DeviceInstallationService.NotificationsSupported) { UNUserNotificationCenter.Current.RequestAuthorization( UNAuthorizationOptions.Alert | UNAuthorizationOptions.Badge | UNAuthorizationOptions.Sound, (approvalGranted, error) => { if (approvalGranted && error == null) RegisterForRemoteNotifications(); }); }
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
Open een nieuw tabblad in Postman-.
Stel de aanvraag in op POST-en voer het volgende adres in:
https://<app_name>.azurewebsites.net/api/notifications/requests
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> 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" }
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" }
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.
Tik in de PushDemo-app op de knop Registreren.
Sluit in Postmanhet venster Codefragmenten genereren (als u dit nog niet hebt gedaan) en klik vervolgens op de knop Verzenden.
Controleer of u een 200 OK antwoord krijgt in Postman- en de waarschuwing wordt weergegeven in de app met ActieA-actie ontvangen.
Sluit de PushDemo-app en klik vervolgens nogmaals op de knop Verzenden in Postman-.
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.
Tik op de melding om te bevestigen dat de app wordt geopend en de ActieA-actie waarschuwing heeft ontvangen.
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 }
Als de app nog steeds is geopend, klikt u op de knop Verzenden in Postman-.
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.
Sluit de PushDemo-app en klik vervolgens nogmaals op de knop Verzenden in Postman-.
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.
Verwante koppelingen
- Overzicht van Azure Notification Hubs
- Visual Studio voor Mac installeren
- Xamarin installeren in Windows
- Notification Hubs SDK voor back-endbewerkingen
- Notification Hubs SDK op GitHub
- registreren bij de back-end van de toepassing
- registratiebeheer
- Werken met tags
- Werken met aangepaste sjablonen
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.