Partager via


Tutoriel : Envoyer des notifications Push à des applications Xamarin.Forms à l’aide d’Azure Notification Hubs via un service back-end

Télécharger l’exemple de Télécharger l’exemple de

Dans ce tutoriel, vous utilisez Azure Notification Hubs pour envoyer des notifications à une application Xamarin.Forms ciblant Android et iOS.

Un serveur principal d’API web ASP.NET Core est utilisé pour gérer d’inscription d’appareil pour le client à l’aide de la dernière approche installation. Le service envoie également des notifications Push de manière multiplateforme.

Ces opérations sont gérées à l’aide du Kit de développement logiciel (SDK) notification Hubs de . Pour plus d’informations sur l’approche globale, consultez la documentation Inscription à partir de votre serveur principal d’application documentation.

Ce didacticiel vous guide tout au long des étapes suivantes :

Conditions préalables

Pour suivre le suivi, vous avez besoin des informations suivantes :

  • Un abonnement Azure où vous pouvez créer et gérer des ressources.
  • Un Mac avec Visual Studio pour Mac installé ou un PC exécutant Visual Studio 2019.
  • utilisateurs de Visual Studio 2019 doivent également avoir développement Mobile avec .NET et ASP.NET et les charges de travail de développement web installées.
  • Possibilité d’exécuter l’application sur Android (appareils physiques ou émulateurs) ou iOS (appareils physiques uniquement).

Pour Android, vous devez avoir :

  • Un appareil physique déverrouillé ou un émulateur (exécutant l’API 26 et versions ultérieures avec Google Play Services installé).

Pour iOS, vous devez avoir :

  • Un compte développeur Apple actif .
  • Un appareil iOS physique inscrit à votre compte de développeur(exécutant iOS 13.0 et versions ultérieures).
  • Un certificat de développement .p12installé dans votre trousseau vous permettant d'exécuter une application sur un appareil physique.

Note

Le simulateur iOS ne prend pas en charge les notifications à distance et un appareil physique est donc nécessaire lors de l’exploration de cet exemple sur iOS. Toutefois, vous n’avez pas besoin d’exécuter l’application sur Android et iOS pour suivre ce didacticiel.

Vous pouvez suivre les étapes décrites dans cet exemple de premier principe sans expérience préalable. Toutefois, vous bénéficiez d’une connaissance des aspects suivants.

Important

Les étapes fournies sont spécifiques à Visual Studio pour Mac. Il est possible de suivre l’utilisation de Visual Studio 2019, mais il peut y avoir des différences à rapprocher. Par exemple, les descriptions de l’interface utilisateur et des flux de travail, des noms de modèles, de la configuration de l’environnement, et ainsi de suite.

Configurer Push Notification Services et Azure Notification Hub

Dans cette section, vous configurez Firebase Cloud Messaging (FCM) et Apple Push Notification Services (APNS). Vous créez et configurez ensuite un hub de notification pour qu’il fonctionne avec ces services.

Créer un projet Firebase et activer Firebase Cloud Messaging pour Android

  1. Connectez-vous à la console Firebase. Créez un projet Firebase entrant PushDemo en tant que nom de projet .

    Note

    Un nom unique sera généré pour vous. Par défaut, il s’agit d’une variante minuscule du nom que vous avez fourni et d’un nombre généré séparé par un tiret. Vous pouvez modifier ce paramètre si vous le souhaitez, car il est toujours unique à l’échelle mondiale.

  2. Après avoir créé votre projet, sélectionnez Ajouter Firebase à votre application Android.

    Ajouter Firebase à votre application Android

  3. Dans la page Ajouter Firebase à votre application Android, procédez comme suit.

    1. Pour le nom du package Android, entrez un nom pour votre package. Par exemple : com.<organization_identifier>.<package_name>.

      Spécifier le nom du package

    2. Sélectionnez Inscrire l’application.

    3. Sélectionnez Télécharger google-services.json. Enregistrez ensuite le fichier dans un dossier local à utiliser ultérieurement, puis sélectionnez suivant .

      télécharger google-services.json

    4. Sélectionnez suivant.

    5. Sélectionnez continuer vers la console

      Note

      Si le bouton Continuer à la console n’est pas activé, en raison du vérifier l’installation vérifier, choisissez Ignorer cette étape.

  4. Dans la console Firebase, sélectionnez la roue dentée de votre projet. Sélectionnez ensuite paramètres du projet.

    sélectionner des paramètres de projet

    Note

    Si vous n’avez pas téléchargé le fichier google-services.json, vous pouvez le télécharger sur cette page.

  5. Basculez vers l’onglet Cloud Messaging en haut. Copiez et enregistrez la clé de serveur pour une utilisation ultérieure. Vous utilisez cette valeur pour configurer votre hub de notification.

    Copier la clé de serveur

Inscrire votre application iOS pour les notifications Push

Pour envoyer des notifications Push à une application iOS, inscrivez votre application auprès d’Apple et inscrivez-vous également aux notifications Push.

  1. Si vous n’avez pas déjà inscrit votre application, accédez au portail d’approvisionnement iOS au Centre de développement Apple. Connectez-vous au portail avec votre ID Apple, accédez à Certificats, Identificateurs & Profils, puis sélectionnez Identificateurs. Cliquez sur + pour inscrire une nouvelle application.

    page ID d’application du portail d’approvisionnement iOS

  2. Dans l’écran Inscrire un nouvel identificateur, sélectionnez les ID d’application case d’option. Sélectionnez ensuite Continuer.

    portail d’approvisionnement iOS inscrire une nouvelle page d’ID

  3. Mettez à jour les trois valeurs suivantes pour votre nouvelle application, puis sélectionnez Continuer:

    • Description: tapez un nom descriptif pour votre application.

    • ID d’offre groupée: entrez un ID groupé du formulaire com.<organization_identifier>.<product_name> comme mentionné dans le guide de distribution des applications . Dans la capture d’écran suivante, la valeur mobcat est utilisée comme identificateur d’organisation et la valeur PushDemo est utilisée comme nom de produit.

      portail d’approvisionnement iOS inscrire la page d’ID d’application

    • notifications Push: cochez l’option notifications Push dans la section Fonctionnalités.

      Formulaire pour inscrire un nouvel ID d’application

      Cette action génère votre ID d’application et vos demandes que vous confirmez les informations. Sélectionnez Continuer, puis sélectionnez Inscrire pour confirmer le nouvel ID d’application.

      Confirmer la nouvelle d’ID d’application

      Une fois que vous avez sélectionné Inscrire, vous voyez le nouvel ID d’application en tant qu’élément de ligne dans la page Certificats, Identificateurs & Profils.

  4. Dans la page Certificats, identificateurs & profils, sous Identificateurs, recherchez l’élément de ligne ID d’application que vous avez créé. Sélectionnez ensuite sa ligne pour afficher l’écran Modifier votre configuration d’ID d’application.

Création d’un certificat pour Notification Hubs

Un certificat est nécessaire pour permettre au hub de notification d’utiliser Apple Push Notification Services (APNS) et peut être fourni de deux façons :

  1. Création d’un certificat push p12 qui peut être chargé directement dans notification Hub (l’approche d’origine)

  2. Création d’un certificat p8 qui peut être utilisé pour l’authentification basée sur des jetons (l’approche plus récente et recommandée)

L’approche la plus récente présente un certain nombre d’avantages, comme indiqué dans authentification basée sur un jeton (HTTP/2) pour APNS. Moins d’étapes sont requises, mais elles sont également imposées pour des scénarios spécifiques. Toutefois, les étapes ont été fournies pour les deux approches, car l’une ou l’autre fonctionne à des fins de ce didacticiel.

OPTION 1 : Création d’un certificat Push p12 qui peut être chargé directement sur Notification Hub
  1. Sur votre Mac, exécutez l’outil Keychain Access. Il peut être ouvert à partir du dossier Utilitaires de ou du dossier Autre sur Launchpad.

  2. Sélectionnez d’accès au trousseau, développez Assistant Certificat, puis sélectionnez Demander un certificat auprès d’une autorité de certification.

    Utiliser l’accès au trousseau pour demander une nouvelle de certificat

    Note

    Par défaut, Keychain Access sélectionne le premier élément de la liste. Cela peut être un problème si vous êtes dans la catégorie certificats et Apple Worldwide Developer Relations Certification Authority n’est pas le premier élément de la liste. Assurez-vous que vous disposez d’un élément non clé ou que l’autorité de certification des relations des développeurs Apple Dans le monde est sélectionnée, avant de générer la demande de signature de certificat(CSR).

  3. Sélectionnez votre adresse e-mail utilisateur, entrez votre valeur nom commun , vérifiez que vous spécifiez enregistré sur le disque, puis sélectionnez Continuer. Laissez adresse e-mail de l’autorité de certification vide, car elle n’est pas requise.

    informations de certificat attendues

  4. Entrez un nom pour le fichier demande de signature de certificat (CSR) dans Enregistrer sous, sélectionnez l’emplacement dans , puis sélectionnez Enregistrer.

    Choisir un nom de fichier pour le certificat

    Cette action enregistre le fichier CSR à l’emplacement sélectionné. L’emplacement par défaut est Desktop. N’oubliez pas l’emplacement choisi pour le fichier.

  5. De retour sur la page Certificats, Identificateurs & Profils dans le portail d’approvisionnement iOS , faites défiler jusqu’à l’option Notifications Push activée, puis sélectionnez Configurer pour créer le certificat.

    page Modifier l’ID d’application

  6. La fenêtre certificats TLS/SSL du service de notification Push Apple s’affiche. Sélectionnez le bouton Créer un certificat sous la section de certificat TLS/SSL de développement .

    bouton Créer un certificat pour l’ID d’application

    L’écran Créer un nouveau certificat s’affiche.

    Note

    Ce tutoriel utilise un certificat de développement. Le même processus est utilisé lors de l’inscription d’un certificat de production. Veillez simplement à utiliser le même type de certificat lors de l’envoi de notifications.

  7. Sélectionnez Choisir un fichier, accédez à l’emplacement où vous avez enregistré le fichier CSR , puis double-cliquez sur le nom du certificat pour le charger. Sélectionnez ensuite Continuer.

  8. Une fois le portail créé le certificat, sélectionnez le bouton Télécharger. Enregistrez le certificat et n’oubliez pas l’emplacement dans lequel il est enregistré.

    page de téléchargement de certificat généré

    Le certificat est téléchargé et enregistré sur votre ordinateur dans votre dossier Téléchargements.

    Localiser le fichier de certificat dans le dossier Téléchargements

    Note

    Par défaut, le certificat de développement téléchargé est nommé aps_development.cer.

  9. Double-cliquez sur le certificat Push téléchargé aps_development.cer. Cette action installe le nouveau certificat dans le trousseau, comme illustré dans l’image suivante :

    liste des certificats d’accès au trousseau montrant la nouvelle de certificat

    Note

    Bien que le nom de votre certificat soit différent, le nom est préfixé par Apple Development iOS Push Services et disposez de l’identificateur de bundle approprié associé à celui-ci.

  10. Dans Keychain Access, Control + Cliquez sur sur le nouveau certificat Push que vous avez créé dans la catégorie Certificats. Sélectionnez Exporter, nommez le fichier, sélectionnez le format p12, puis sélectionnez Enregistrer.

    Exporter un certificat au format p12

    Vous pouvez choisir de protéger le certificat avec un mot de passe, mais un mot de passe est facultatif. Cliquez sur OK si vous souhaitez contourner la création du mot de passe. Notez le nom de fichier et l’emplacement du certificat p12 exporté. Ils sont utilisés pour activer l’authentification avec des API.

    Note

    Le nom et l’emplacement de votre fichier p12 peuvent être différents de ce qui est illustré dans ce tutoriel.

OPTION 2 : Création d’un certificat p8 qui peut être utilisé pour l’authentification basée sur des jetons
  1. Notez les détails suivants :

    • préfixe d’ID d’application (ID d’équipe)
    • ID de bundle
  2. De retour dans Certificats, identificateurs & profils, cliquez sur clés.

    Note

    Si vous disposez déjà d’une clé configurée pour APNS, vous pouvez réutiliser le certificat p8 que vous avez téléchargé juste après sa création. Si c’est le cas, vous pouvez ignorer les étapes 3 via 5.

  3. Cliquez sur le bouton + (ou sur le bouton Créer une clé) pour créer une clé.

  4. Fournissez une valeur de de nom de clé appropriée, puis cochez l’option de du service de notifications Push Apple (APNS), puis cliquez sur Continuer, suivi de Inscrire sur l’écran suivant.

  5. Cliquez sur Télécharger, puis déplacez le fichier p8 (préfixé par AuthKey_) vers un répertoire local sécurisé, puis cliquez sur Terminé.

    Note

    Veillez à conserver votre fichier p8 dans un emplacement sécurisé (et enregistrez une sauvegarde). Après avoir téléchargé votre clé, elle ne peut pas être téléchargée à nouveau, car la copie du serveur est supprimée.

  6. Sur clés, cliquez sur la clé que vous avez créée (ou une clé existante si vous avez choisi de l’utiliser à la place).

  7. Notez la valeur de l’ID de clé .

  8. Ouvrez votre certificat p8 dans une application appropriée de votre choix, par exemple Visual Studio Code. Notez la valeur de clé (entre -----BEGIN PRIVATE KEY----- et -----END PRIVATE KEY-----).

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

    Note

    Il s’agit de la valeur de jeton qui sera utilisée ultérieurement pour configurer notification Hub.

À la fin de ces étapes, vous devez disposer des informations suivantes pour une utilisation ultérieure dans Configurer votre hub de notification avec des informations APNS:

  • ID d’équipe (voir l’étape 1)
  • ID de bundle (voir l’étape 1)
  • ID de clé (voir l’étape 7)
  • valeur de jeton (valeur de clé p8 obtenue à l’étape 8)

Créer un profil d’approvisionnement pour l’application

  1. Revenez au portail d’approvisionnement iOS , sélectionnez Certificats, Identificateurs & Profils, sélectionnez Profils dans le menu de gauche, puis sélectionnez + pour créer un profil. L’écran Inscrire un nouveau profil d’approvisionnement s’affiche.

  2. Sélectionnez de développement d’applications iOS sous de développement comme type de profil d’approvisionnement, puis sélectionnez Continuer.

    liste de profils d’approvisionnement

  3. Ensuite, sélectionnez l’ID d’application que vous avez créé dans la liste déroulante ID d’application, puis sélectionnez Continuer.

    Sélectionner l’ID d’application

  4. Dans la fenêtre Sélectionner des certificats, sélectionnez le certificat de développement que vous utilisez pour la signature de code, puis sélectionnez Continuer.

    Note

    Ce certificat n’est pas le certificat Push que vous avez créé à l’étape précédente. Il s’agit de votre certificat de développement. S’il n’existe pas, vous devez le créer, car il s’agit d’un prérequis pour ce didacticiel. Les certificats de développeur peuvent être créés dans ledu portail des développeurs Apple , via Xcode ou dans Visual Studio.

  5. Revenez à la page Certificats, Identificateurs & Profils, sélectionnez Profils dans le menu de gauche, puis sélectionnez + pour créer un profil. L’écran Inscrire un nouveau profil d’approvisionnement s’affiche.

  6. Dans la fenêtre Sélectionner des certificats, sélectionnez le certificat de développement que vous avez créé. Sélectionnez ensuite Continuer.

  7. Ensuite, sélectionnez les appareils à utiliser pour les tests, puis sélectionnez Continuer.

  8. Enfin, choisissez un nom pour le profil dans Nom du profil d’approvisionnement, puis sélectionnez Générer.

    Choisir un nom de profil d’approvisionnement

  9. Lorsque le nouveau profil d’approvisionnement est créé, sélectionnez Télécharger. N’oubliez pas l’emplacement dans lequel il est enregistré.

  10. Accédez à l’emplacement du profil d’approvisionnement, puis double-cliquez dessus pour l’installer sur votre ordinateur de développement.

Créer un hub de notification

Dans cette section, vous allez créer un hub de notification et configurer l’authentification avec APNS. Vous pouvez utiliser un certificat push p12 ou une authentification basée sur un jeton. Si vous souhaitez utiliser un hub de notification que vous avez déjà créé, vous pouvez passer à l’étape 5.

  1. Connectez-vous à Azure .

  2. Cliquez sur Créer une ressource, puis recherchez et choisissez notification Hub, puis cliquez sur Créer.

  3. Mettez à jour les champs suivants, puis cliquez sur Créer:

    DÉTAILS DE BASE

    abonnement : Choisir l' d’abonnement cible dans la liste déroulante
    groupe de ressources : Créer un nouveau groupe de ressources (ou choisir un groupe de ressources existant)

    détails de l’espace de noms

    notification Hub Namespace : entrez un nom global unique pour l’espace de noms Notification Hub

    Note

    Vérifiez que l’option Créer une nouvelle est sélectionnée pour ce champ.

    DÉTAILS NOTIFICATION HUB

    Notification Hub : entrez un nom pour le du hub de notification
    Emplacement : Choisir un emplacement approprié dans la liste déroulante
    niveau tarifaire : conserver l’option de
    gratuite par défaut

    Note

    Sauf si vous avez atteint le nombre maximal de hubs sur le niveau gratuit.

  4. Une fois que le Notification Hub a été approvisionné, accédez à cette ressource.

  5. Accédez à votre nouveau hub de notification .

  6. Sélectionnez stratégies d’accès dans la liste (sous MANAGE).

  7. Notez les valeurs nom de la stratégie ainsi que leurs valeurs de chaîne de connexion correspondantes.

Configurer votre Hub de notification avec des informations APNS

Sous Notification Services, sélectionnez Apple puis suivez les étapes appropriées en fonction de l’approche que vous avez choisie précédemment dans la section Création d’un certificat pour Notification Hubs.

Note

Utilisez le de production pour mode application uniquement si vous souhaitez envoyer des notifications Push aux utilisateurs qui ont acheté votre application à partir du Store.

OPTION 1 : Utilisation d’un certificat Push .p12

  1. Sélectionnez certificat.

  2. Sélectionnez l’icône de fichier.

  3. Sélectionnez le fichier .p12 que vous avez exporté précédemment, puis sélectionnez Ouvrir.

  4. Si nécessaire, spécifiez le mot de passe correct.

  5. Sélectionnez mode sandbox.

  6. Sélectionnez Enregistrer.

OPTION 2 : Utilisation de l’authentification basée sur les jetons

  1. Sélectionnez jeton.

  2. Entrez les valeurs suivantes que vous avez acquises précédemment :

    • id de clé
    • ID de bundle
    • id d’équipe
    • jeton
  3. Choisissez bac à sable.

  4. Sélectionnez Enregistrer.

Configurer votre hub de notification avec des informations FCM

  1. Sélectionnez google (GCM/FCM) dans la section paramètres dans le menu de gauche.
  2. Entrez la clé de serveur vous avez notée à partir de la console Google Firebase.
  3. Sélectionnez Enregistrer dans la barre d’outils.

Créer une application principale d’API web ASP.NET Core

Dans cette section, vous allez créer l’API web ASP.NET Core back-end pour gérer d’inscription des appareils et l’envoi de notifications à l’application mobile Xamarin.Forms.

Créer un projet web

  1. Dans Visual Studio, sélectionnez fichier>nouvelle solution.

  2. Sélectionnez 'API .NET Core>App>ASP.NET Core>>suivante.

  3. Dans la boîte de dialogue Configurer votre nouvelle API web ASP.NET Core, sélectionnez Framework cible de .NET Core 3.1.

  4. Entrez PushDemoApi pour le nom du projet , puis sélectionnez Créer.

  5. Démarrez le débogage (Commande + Entrer) pour tester l’application modèle.

    Note

    L’application modélisée est configurée pour utiliser le WeatherForecastController commelaunchUrl . Cette valeur est définie dans Propriétés>launchSettings.json.

    Si vous êtes invité à utiliser un certificat de développement non valide trouvé message :

    1. Cliquez sur Oui pour accepter d’exécuter l’outil « dotnet dev-certs https » pour résoudre ce problème. L’outil « dotnet dev-certs https » vous invite ensuite à entrer un mot de passe pour le certificat et le mot de passe de votre trousseau.

    2. Cliquez sur Oui lorsque vous êtes invité à Installer et approuver le nouveau certificat, puis entrez le mot de passe de votre trousseau.

  6. Développez le dossier contrôleurs , puis supprimez WeatherForecastController.cs.

  7. Supprimer WeatherForecast.cs.

  8. Configurez les valeurs de configuration locales à l’aide de l’outil Secret Manager. Découpler les secrets de la solution garantit qu’ils ne se retrouvent pas dans le contrôle de code source. Ouvrez Terminal puis accédez au répertoire du fichier projet et exécutez les commandes suivantes :

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

    Remplacez les valeurs d’espace réservé par votre propre nom de hub de notification et vos propres valeurs de chaîne de connexion. Vous avez noté ces informations dans la créer un hub de notification section. Sinon, vous pouvez les rechercher dans Azure.

    NotificationHub :Name:
    Consultez nom dans le résumé Essentials en haut de Vue d’ensemble.

    NotificationHub :ConnectionString:
    Consultez DefaultFullSharedAccessSignature dans stratégies d’accès

    Note

    Pour les scénarios de production, vous pouvez examiner des options telles que Azure KeyVault pour stocker en toute sécurité la chaîne de connexion. Par souci de simplicité, les secrets seront ajoutés aux paramètres d’application Azure App Service.

Authentifier des clients à l’aide d’une clé API (facultatif)

Les clés API ne sont pas aussi sécurisées que les jetons, mais suffiront pour les besoins de ce didacticiel. Une clé API peut être configurée facilement via le ASP.NET middleware.

  1. Ajoutez la clé API aux valeurs de configuration locales.

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

    Note

    Vous devez remplacer la valeur de l’espace réservé par votre propre et prendre note de celle-ci.

  2. ControlCliquez sur dans le projet PushDemoApi, choisissez nouveau dossier dans le menu Ajouter, puis cliquez sur Ajouter à l’aide du d’authentification en tant que nom de dossier .

  3. ControlCliquez sur dans le dossier d’authentification , puis choisissez Nouveau fichier... dans le menu Ajouter .

  4. Sélectionnez classe vide, entrez ApiKeyAuthOptions.cs pour l'nom du , puis cliquez sur Nouveau ajout de l’implémentation suivante.

    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. Ajoutez un autre classe vide au dossier Authentication appelé ApiKeyAuthHandler.cs, puis ajoutez l’implémentation suivante.

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

    Note

    Un gestionnaire d’authentification est un type qui implémente le comportement d’un schéma, dans ce cas un schéma de clé API personnalisé.

  6. Ajoutez une autre classe vide au dossier Authentication appelé ApiKeyAuthenticationBuilderExtensions.cs, puis ajoutez l’implémentation suivante.

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

    Note

    Cette méthode d’extension simplifie le code de configuration de l’intergiciel dans Startup.cs ce qui facilite la lecture et facilite généralement le suivi.

  7. Dans Startup.cs, mettez à jour la méthode ConfigureServices pour configurer l’authentification par clé API sous l’appel aux services . AddControllers méthode.

    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. Toujours dans Startup.cs, mettez à jour la méthode Configurer pour appeler les méthodes d’extension UseAuthentication et UseAuthorization sur les IApplicationBuilder de l’application. Vérifiez que ces méthodes sont appelées après UseRouting et avant application. 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();
        });
    }
    

    Note

    L’appel UseAuthentication inscrit le middleware qui utilise les schémas d’authentification précédemment inscrits (à partir de ConfigureServices). Cela doit être appelé avant tout intergiciel qui dépend de l’authentification des utilisateurs.

Ajouter des dépendances et configurer des services

ASP.NET Core prend en charge le modèle de conception logicielle d’injection de dépendances , qui est une technique permettant d’obtenir inversion de contrôle (IoC) entre les classes et leurs dépendances.

L’utilisation du hub de notification et du Kit de développement logiciel (SDK) notification Hubs pour les opérations principales est encapsulée dans un service. Le service est inscrit et mis à disposition via une abstraction appropriée.

  1. ControlCliquez sur dans le dossier dépendances , puis choisissez Gérer les packages NuGet....

  2. Recherchez Microsoft.Azure.NotificationHubs et vérifiez qu’elle est cochée.

  3. Cliquez sur Ajouter des packages, puis cliquez sur Accepter lorsque vous êtes invité à accepter les termes du contrat de licence.

  4. ControlCliquez sur dans le projet PushDemoApi, choisissez nouveau dossier dans le menu Ajouter, puis cliquez sur Ajouter à l’aide de Modèles commenom du dossier .

  5. Control + Cliquez sur dans le dossier Models, puis choisissez Nouveau fichier... dans le menu Ajouter.

  6. Sélectionnez classe vide générale, entrez PushTemplates.cs pour l'nom de , puis cliquez sur nouveau ajout de l’implémentation suivante.

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

    Note

    Cette classe contient les charges utiles de notification par jeton pour les notifications génériques et silencieuses requises par ce scénario. Les charges utiles sont définies en dehors du Installation pour permettre l’expérimentation sans avoir à mettre à jour les installations existantes via le service. La gestion des modifications apportées aux installations de cette façon est hors de portée pour ce didacticiel. Pour la production, envisagez de modèles personnalisés.

  7. Ajoutez un autre classe vide au dossier Models appelé DeviceInstallation.cs, puis ajoutez l’implémentation suivante.

    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. Ajoutez un autre classe vide au dossier Models appelé NotificationRequest.cs, puis ajoutez l’implémentation suivante.

    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. Ajoutez un autre classe vide au dossier Models appelé NotificationHubOptions.cs, puis ajoutez l’implémentation suivante.

    using System.ComponentModel.DataAnnotations;
    
    namespace PushDemoApi.Models
    {
        public class NotificationHubOptions
        {
            [Required]
            public string Name { get; set; }
    
            [Required]
            public string ConnectionString { get; set; }
        }
    }
    
  10. Ajoutez un nouveau dossier au projet PushDemoApi appelé Services.

  11. Ajoutez une interface vide au dossier services appelé INotificationService.cs, puis ajoutez l’implémentation suivante.

    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. Ajoutez un de classe vide au dossier services appelé NotificationHubsService.cs, puis ajoutez le code suivant pour implémenter l’interface INotificationService :

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

    Note

    L’expression de balise fournie à SendTemplateNotificationAsync est limitée à 20 balises. Il est limité à 6 pour la plupart des opérateurs, mais l’expression contient uniquement des OR (||) dans ce cas. S’il existe plus de 20 balises dans la demande, elles doivent être divisées en plusieurs requêtes. Pour plus d’informations, consultez la documentation routage et expressions de balise.

  13. Dans Startup.cs, mettez à jour la méthode ConfigureServices pour ajouter le NotificationHubsService en tant qu’implémentation singleton de 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();
    }
    

Créer l’API de notifications

  1. ControlCliquez sur dans le dossier contrôleurs de , puis choisissez Nouveau fichier... dans le menu Ajouter.

  2. Sélectionnez ASP.NET classe de contrôleur d’API web core, entrez notificationsController pour lenom de , puis cliquez sur Nouveau.

    Note

    Si vous suivez Visual Studio 2019, choisissez le contrôleur d’API avec des actions en lecture/écriture modèle.

  3. Ajoutez les espaces de noms suivants en haut du fichier.

    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. Mettez à jour le contrôleur modé afin qu’il dérive de ControllerBase et soit décoré avec l’attribut ApiController.

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

    Note

    La classe de base Controller fournit la prise en charge des vues, mais cela n’est pas nécessaire dans ce cas et ControllerBase peut être utilisé à la place. Si vous suivez visual Studio 2019, vous pouvez ignorer cette étape.

  5. Si vous avez choisi de terminer la section Authentifier les clients à l’aide d’une clé API, vous devez également décorer l' notificationsController avec l’attribut Autoriser .

    [Authorize]
    
  6. Mettez à jour le constructeur pour accepter l’instance inscrite de INotificationService en tant qu’argument et l’affecter à un membre en lecture seule.

    readonly INotificationService _notificationService;
    
    public NotificationsController(INotificationService notificationService)
    {
        _notificationService = notificationService;
    }
    
  7. Dans launchSettings.json (dans le dossier propriétés de ), remplacez le launchUrl de par api/notifications pour qu’il corresponde à l’URL spécifiée dans l’attribut RegistrationsControllerRoute.

  8. Démarrez le débogage (CommandeEntrer) pour valider que l’application fonctionne avec le nouveau NotificationsController et retourne un état 401 Non autorisé.

    Note

    Visual Studio ne peut pas lancer automatiquement l’application dans le navigateur. Vous utiliserez Postman pour tester l’API à partir de ce point.

  9. Sous un nouvel onglet Postman, définissez la requête sur GET. Entrez l’adresse ci-dessous en remplaçant l’espace réservé applicationUrl par le applicationUrl https trouvé dans PropriétéslaunchSettings.json.

    <applicationUrl>/api/notifications
    

    Note

    Le applicationurl doit être' pour le profil par défaut. Si vous utilisez IIS (par défaut dans Visual Studio 2019 sur Windows), vous devez utiliser l’applicationUr l spécifiée dans l’élément iisSettings à la place. Vous recevrez une réponse 404 si l’adresse est incorrecte.

  10. Si vous avez choisi de terminer la section Authentifier les clients à l’aide d’une clé API section, veillez à configurer les en-têtes de requête pour inclure votre valeur apikey.

    Clé Valeur
    apikey <your_api_key>
  11. Cliquez sur le bouton Envoyer.

    Note

    Vous devez recevoir un état 200 OK avec un contenu JSON.

    Si vous recevez un avertissement de vérification de certificat SSL, vous pouvez basculer la vérification du certificat SSL de la demande Postman désactivé dans leparamètres de .

  12. Remplacez les méthodes de classe modèle dans NotificationsController.cs par le code suivant.

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

Créer l’application API

Vous créez maintenant une application API dans Azure App Service pour héberger le service principal.

  1. Connectez-vous au portail Azure .

  2. Cliquez sur Créer une ressource, puis recherchez et choisissez application API, puis cliquez sur Créer.

  3. Mettez à jour les champs suivants, puis cliquez sur Créer.

    nom de l’application :
    Entrez un nom global unique pour l’application API

    Abonnement :
    Choisissez la même cible abonnement vous avez créé le hub de notification.

    groupe de ressources :
    Choisissez le même groupe de ressources dans lequel vous avez créé le hub de notification.

    plan/emplacement App Service :
    Créer un plan App Service

    Note

    Passez de l’option par défaut à un plan qui inclut prise en charge des SSL. Dans le cas contraire, vous devez prendre les mesures appropriées lors de l’utilisation de l’application mobile pour empêcher requêtes http d’être bloquées.

    Application Insights :
    Conservez l’option suggérée (une nouvelle ressource sera créée à l’aide de ce nom) ou choisissez une ressource existante.

  4. Une fois que l’application API a été provisionnée, accédez à cette ressource.

  5. Notez l’URL propriété dans le résumé Essentials en haut de la Vue d’ensemble. Cette URL est votre point de terminaison principal qui sera utilisé plus loin dans ce didacticiel.

    Note

    L’URL utilise le nom de l’application API que vous avez spécifié précédemment, avec le format https://<app_name>.azurewebsites.net.

  6. Sélectionnez configuration dans la liste (sous Paramètres).

  7. Pour chacun des paramètres ci-dessous, cliquez sur nouveau paramètre d’application pour entrer le nom de et une valeur, puis cliquez sur OK.

    Nom Valeur
    Authentication:ApiKey <api_key_value>
    NotificationHub:Name <hub_name_value>
    NotificationHub:ConnectionString <hub_connection_string_value>

    Note

    Il s’agit des mêmes paramètres que ceux que vous avez définis précédemment dans les paramètres utilisateur. Vous devriez être en mesure de les copier. Le paramètre Authentication :ApiKey n’est nécessaire que si vous avez choisi de terminer la section Authentifier les clients à l’aide d’une clé API. Pour les scénarios de production, vous pouvez examiner des options telles que Azure KeyVault. Ces paramètres ont été ajoutés en tant que paramètres d’application par souci de simplicité dans ce cas.

  8. Une fois que tous les paramètres d’application ont été ajoutés, cliquez sur Enregistrer, puis Continuer.

Publier le service principal

Ensuite, vous déployez l’application sur l’application API pour la rendre accessible à partir de tous les appareils.

Note

Les étapes suivantes sont spécifiques à Visual Studio pour Mac. Si vous suivez Visual Studio 2019 sur Windows, le flux de publication sera différent. Consultez Publier sur Azure App Service sur Windows.

  1. Modifiez votre configuration de de débogage en Version si vous ne l’avez pas déjà fait.

  2. ControlCliquez le projet PushDemoApi , puis choisissez Publier sur Azure... dans le menu Publier.

  3. Suivez le flux d’authentification si vous y êtes invité. Utilisez le compte que vous avez utilisé dans la section créer l’application API section.

  4. Sélectionnez l’application d’API Azure App Service que vous avez créée précédemment dans la liste en tant que cible de publication, puis cliquez sur Publier.

Une fois l’Assistant terminé, il publie l’application sur Azure, puis ouvre l’application. Notez l’URL si vous ne l’avez pas déjà fait. Cette URL est votre point de terminaison principal qui est utilisé plus loin dans ce didacticiel.

Validation de l’API publiée

  1. Dans Postman ouvrir un nouvel onglet, définissez la demande sur put et entrez l’adresse ci-dessous. Remplacez l’espace réservé par l’adresse de base que vous avez notée dans la section précédente publier le service principal section.

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

    Note

    L’adresse de base doit être au format https://<app_name>.azurewebsites.net/

  2. Si vous avez choisi de terminer la section Authentifier les clients à l’aide d’une clé API section, veillez à configurer les en-têtes de requête pour inclure votre valeur apikey.

    Clé Valeur
    apikey <your_api_key>
  3. Choisissez l’option brute pour le corps , puis choisissez JSON dans la liste des options de format, puis incluez un espace réservé contenu json :

    {}
    
  4. Cliquez sur envoyer.

    Note

    Vous devez recevoir un état 422 UnprocessableEntity du service.

  5. Effectuez à nouveau les étapes 1 à 4, mais cette fois en spécifiant le point de terminaison des requêtes pour valider que vous recevez une réponse 400 requêtes incorrectes.

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

Note

Il n’est pas encore possible de tester l’API à l’aide de données de requête valides, car cela nécessite des informations spécifiques à la plateforme de l’application mobile cliente.

Créer une application Xamarin.Forms multiplateforme

Dans cette section, vous créez un Xamarin.Forms application mobile implémentant des notifications Push de manière multiplateforme.

Il vous permet d’inscrire et de désinscrire à partir d’un hub de notification via le service principal que vous avez créé.

Une alerte s’affiche lorsqu’une action est spécifiée et que l’application est au premier plan. Sinon, les notifications s’affichent dans le centre de notification.

Note

Vous devez généralement effectuer les actions d’inscription (et de désinscription) pendant le point approprié dans le cycle de vie de l’application (ou dans le cadre de votre expérience de première exécution peut-être) sans entrées explicites d’inscription/de désinscription d’utilisateurs. Toutefois, cet exemple nécessite une entrée utilisateur explicite pour permettre à cette fonctionnalité d’être explorée et testée plus facilement.

Créer la solution Xamarin.Forms

  1. Dans Visual Studio, créez une solution Xamarin.Forms à l’aide de application Forms vide comme modèle et entrez PushDemo pour lenom du projet .

    Note

    Dans la boîte de dialogue Configurer votre application Forms vide, vérifiez que l' identificateur d’organisation correspond à la valeur que vous avez utilisée précédemment et que les cibles Android et iOS sont cochées.

  2. Control + Cliquez sur sur la solution PushDemo, puis choisissez Mettre à jour les packages NuGet.

  3. Control + Cliquez sur sur la solution PushDemo, puis choisissez Gérer les packages NuGet..

  4. Recherchez Newtonsoft.Json et vérifiez qu’elle est cochée.

  5. Cliquez sur Ajouter des packages, puis cliquez sur Accepter lorsque vous êtes invité à accepter les termes du contrat de licence.

  6. Générez et exécutez l’application sur chaque plateforme cible (Commande + Entrer) pour tester l’application modèle s’exécute sur votre ou vos appareils.

Implémenter les composants multiplateformes

  1. Control + Cliquez sur dans le projet PushDemo, choisissez nouveau dossier dans le menu Ajouter, puis cliquez sur Ajouter à l’aide de modèles comme nom de dossier .

  2. Control + Cliquez sur dans le dossier Models, puis choisissez Nouveau fichier... dans le menu Ajouter.

  3. Sélectionnez >classe vide générale, entrez DeviceInstallation.cs, puis ajoutez l’implémentation suivante.

    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. Ajoutez un d’énumération vide au dossier Models appelé PushDemoAction.cs avec l’implémentation suivante.

    namespace PushDemo.Models
    {
        public enum PushDemoAction
        {
            ActionA,
            ActionB
        }
    }
    
  5. Ajoutez un nouveau dossier au projet PushDemo appelé Services puis ajoutez un de classe vide à ce dossier appelé ServiceContainer.cs avec l’implémentation suivante.

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

    Note

    Il s’agit d’une version réduite de la classe ServiceContainer du référentiel XamCAT. Il sera utilisé comme conteneur IoC léger (Inversion de Control).

  6. Ajoutez un d’interface vide au dossier Services appelé IDeviceInstallationService.cs, puis ajoutez le code suivant.

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

    Note

    Cette interface sera implémentée et démarrée par chaque cible ultérieurement pour fournir les fonctionnalités spécifiques à la plateforme et DeviceInstallation informations requises par le service principal.

  7. Ajoutez une autre interface vide au dossier Services appelé INotificationRegistrationService.cs, puis ajoutez le code suivant.

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

    Note

    Cela gère l’interaction entre le client et le service principal.

  8. Ajoutez une autre interface vide au dossier services appelé INotificationActionService.cs, puis ajoutez le code suivant.

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

    Note

    Il s’agit d’un mécanisme simple pour centraliser la gestion des actions de notification.

  9. Ajoutez un d’interface vide au dossier Services appelé IPushDemoNotificationActionService.cs qui dérive de l'INotificationActionService , avec l’implémentation suivante.

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

    Note

    Ce type est spécifique à l’application PushDemo et utilise l’énumération PushDemoAction pour identifier l’action déclenchée de manière fortement typée.

  10. Ajoutez un de classe vide au dossier Services appelé NotificationRegistrationService.cs implémentant le INotificationRegistrationService avec le code suivant.

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

    Note

    L’argument apiKey n’est nécessaire que si vous avez choisi de terminer la section Authentifier les clients à l’aide d’une clé API.

  11. Ajoutez un de classe vide au dossier services appelé PushDemoNotificationActionService.cs l’implémentation du IPushDemoNotificationActionService avec le code suivant.

    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. Ajoutez un de classe vide au projet PushDemo appelé Config.cs avec l’implémentation suivante.

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

    Note

    Il s’agit d’une méthode simple pour empêcher les secrets du contrôle de code source. Vous pouvez remplacer ces valeurs dans le cadre d’une build automatisée ou les remplacer à l’aide d’une classe partielle locale. Vous allez le faire à l’étape suivante.

    Le champ ApiKey n’est nécessaire que si vous avez choisi de terminer la section Authentifier les clients à l’aide d’une clé API.

  13. Ajoutez un autre classe vide au projet PushDemo cette fois appelé Config.local_secrets.cs avec l’implémentation suivante.

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

    Note

    Remplacez les valeurs d’espace réservé par vos propres valeurs. Vous devez avoir noté ces informations lorsque vous avez créé le service back-end. L’URL de l’application API doit être . N’oubliez pas d’ajouter *.local_secrets.* à votre fichier gitignore pour éviter de valider ce fichier.

    Le champ ApiKey n’est nécessaire que si vous avez choisi de terminer la section Authentifier les clients à l’aide d’une clé API.

  14. Ajoutez un de classe vide au projet PushDemo appelé Bootstrap.cs avec l’implémentation suivante.

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

    Note

    La méthode Begin sera appelée par chaque plateforme lorsque l’application lance la transmission d’une implémentation spécifique à la plateforme de IDeviceInstallationService.

    L’argument NotificationRegistrationServiceapiKey constructeur n’est nécessaire que si vous avez choisi de terminer la section Authentifier les clients à l’aide d’une clé API.

Implémenter l’interface utilisateur multiplateforme

  1. Dans le projet PushDemo, ouvrez MainPage.xaml et remplacez le contrôle StackLayout par ce qui suit.

    <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. Maintenant, dans MainPage.xaml.cs, ajoutez un champ de stockage en lecture seule pour stocker une référence à l’implémentation INotificationRegistrationService.

    readonly INotificationRegistrationService _notificationRegistrationService;
    
  3. Dans le constructeur MainPage , résolvez l’implémentation INotificationRegistrationService à l’aide du ServiceContainer et affectez-le au champ de stockage notificationRegistrationService.

    public MainPage()
    {
        InitializeComponent();
    
        _notificationRegistrationService =
            ServiceContainer.Resolve<INotificationRegistrationService>();
    }
    
  4. Implémentez les gestionnaires d’événements pour le RegisterButton et les boutons DeregisterButton des événements Clicked appelant les méthodesRegister correspondantes.

    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. À présent, dans App.xaml.cs, vérifiez que les espaces de noms suivants sont référencés.

    using PushDemo.Models;
    using PushDemo.Services;
    using Xamarin.Essentials;
    using Xamarin.Forms;
    
  6. Implémentez le gestionnaire d’événements pour l’événement IPushDemoNotificationActionServiceActionTriggered.

    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. Dans le constructeur d’application , résolvez l’implémentation IPushNotificationActionService à l’aide du ServiceContainer et abonnez-vous à l’événement IPushDemoNotificationActionServiceActionTriggered.

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

    Note

    Il s’agit simplement de démontrer la réception et la propagation des actions de notification Push. En règle générale, ils sont gérés en mode silencieux, par exemple en accédant à une vue spécifique ou en actualisant certaines données plutôt que d’afficher une alerte via la racinePage , MainPage dans ce cas.

Configurer le projet Android natif pour les notifications Push

Valider le nom et les autorisations du package

  1. Dans PushDemo.Android, ouvrez le Options de projet, puis application Android à partir de la section Générer.

  2. Vérifiez que le nom du package correspond à la valeur que vous avez utilisée dans le projet projetPushDemo de la console Firebase. Le nom du package était au format com.<organization>.pushdemo.

  3. Définissez la version Minimale d’Android sur Android 8.0 (niveau d’API 26) et la version Cible android au dernier niveau d’API .

    Note

    Seuls les appareils exécutant niveau d’API 26 et versions ultérieures sont pris en charge pour les besoins de ce didacticiel. Toutefois, vous pouvez l’étendre pour prendre en charge les appareils exécutant des versions antérieures.

  4. Vérifiez que les autorisations INTERNET et READ_PHONE_STATE sont activées sous autorisations requises.

  5. Cliquez sur OK

Ajouter les packages Xamarin Google Play Services et Xamarin.Firebase.Messaging

  1. Dans PushDemo.Android, Control + Cliquez sur dans le dossier Packages, puis choisissez Gérer les packages NuGet....

  2. Recherchez Xamarin.GooglePlayServices.Base (et non sous-sol) et vérifiez qu’elle est vérifiée.

  3. Recherchez Xamarin.Firebase.Messaging et vérifiez qu’elle est cochée.

  4. Cliquez sur Ajouter des packages, puis cliquez sur Accepter lorsque vous êtes invité à accepter les termes du contrat de licence .

Ajouter le fichier JSON Google Services

  1. ContrôleCliquez sur dans le projet , puis choisissez fichier existant... dans le menu Ajouter .

  2. Choisissez le fichier google-services.json que vous avez téléchargé précédemment lorsque vous configurez le projet PushDemo dans la console Firebase, puis cliquez sur Ouvrir.

  3. Lorsque vous y êtes invité, choisissez de Copier le fichier dans le répertoire.

  4. Control + Cliquez sur dans le fichier google-services.json à partir du projet PushDemo.Android, puis vérifiez que GoogleServicesJson est défini comme 'action de génération.

Gérer les notifications Push pour Android

  1. ControlCliquez sur dans le projet de , choisissez nouveau dossier dans le menu Ajouter, puis cliquez sur Ajouter à l’aide de Services commenom du dossier .

  2. ControlCliquez sur dans le dossier services , puis choisissez Nouveau fichier... dans le menu Ajouter .

  3. Sélectionnez classe vide générale, entrez DeviceInstallationService.cs pour l'nom de , puis cliquez sur nouveau ajout de l’implémentation suivante.

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

    Note

    Cette classe fournit un ID unique (à l’aide de Secure.AndroidId) dans le cadre de la charge utile d’inscription du hub de notification.

  4. Ajoutez un autre classe vide au dossier services appelé PushNotificationFirebaseMessagingService.cs, puis ajoutez l’implémentation suivante.

    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. Dans MainActivity.cs, vérifiez que les espaces de noms suivants ont été ajoutés en haut du fichier.

    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. Dans MainActivity.cs, définissez le LaunchMode sur SingleTop afin que MainActivity ne soit pas recréé lors de l’ouverture.

    [Activity(
        Label = "PushDemo",
        LaunchMode = LaunchMode.SingleTop,
        Icon = "@mipmap/icon",
        Theme = "@style/MainTheme",
        MainLauncher = true,
        ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
    
  7. Ajoutez des propriétés privées et des champs de stockage correspondants pour stocker une référence aux implémentations IPushNotificationActionService et IDeviceInstallationService.

    IPushDemoNotificationActionService _notificationActionService;
    IDeviceInstallationService _deviceInstallationService;
    
    IPushDemoNotificationActionService NotificationActionService
        => _notificationActionService ??
            (_notificationActionService =
            ServiceContainer.Resolve<IPushDemoNotificationActionService>());
    
    IDeviceInstallationService DeviceInstallationService
        => _deviceInstallationService ??
            (_deviceInstallationService =
            ServiceContainer.Resolve<IDeviceInstallationService>());
    
  8. Implémentez l’interface IOnSuccessListener pour récupérer et stocker le jeton Firebase .

    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. Ajoutez une nouvelle méthode appelée ProcessNotificationActions qui vérifie si une Intention donnée a une valeur supplémentaire nommée action. Déclenchez conditionnellement cette action à l’aide de l’implémentation IPushDemoNotificationActionService.

    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. Remplacez la méthode OnNewIntent pour appeler méthode ProcessNotificationActions.

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

    Note

    Étant donné que le LaunchMode de l’activité de est défini sur SingleTop, une Intention sera envoyée à l’instance d’activité existante via le OnNewIntent méthode plutôt que la méthode OnCreate. Vous devez donc gérer une intention entrante dans les méthodes OnCreate et OnNewIntent.

  11. Mettez à jour la méthode OnCreate pour appeler Bootstrap.Begin juste après l’appel à base.OnCreate passer l’implémentation spécifique à la plateforme de IDeviceInstallationService.

    Bootstrap.Begin(() => new DeviceInstallationService());
    
  12. Dans la même méthode, appelez de manière conditionnelle GetInstanceId sur l’instance FirebaseApp, juste après l’appel à Bootstrap.Begin, en ajoutant MainActivity comme IOnSuccessListener.

    if (DeviceInstallationService.NotificationsSupported)
    {
        FirebaseInstanceId.GetInstance(Firebase.FirebaseApp.Instance)
            .GetInstanceId()
            .AddOnSuccessListener(this);
    }
    
  13. Toujours dans OnCreate, appelez ProcessNotificationActions immédiatement après l’appel à LoadApplication passage de l’intention actuelle.

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

Note

Vous devez réinscrire l’application chaque fois que vous l’exécutez et l’arrêter d’une session de débogage pour continuer à recevoir des notifications Push.

Configurer le projet iOS natif pour les notifications Push

Configurer Info.plist et Entitlements.plist

  1. Assurez-vous que vous êtes connecté à votre compte de développeur Apple dans Préférences>Visual Studio...>Publication>comptes de développeur Apple et les de certificat appropriés et profil d’approvisionnement ont été téléchargés. Vous devez avoir créé ces ressources dans le cadre des étapes précédentes.

  2. Dans PushDemo.iOS, ouvrez Info.plist et vérifiez que le BundleIdentifier correspond à la valeur utilisée pour le profil de provisionnement respectif dans le Portail des développeurs Apple. Le BundleIdentifier était au format com.<organization>.PushDemo.

  3. Dans le même fichier, définissez version minimale du système sur 13.0.

    Note

    Seuls les appareils exécutant iOS 13.0 et versions ultérieures sont pris en charge pour les besoins de ce didacticiel, mais vous pouvez l’étendre pour prendre en charge les appareils exécutant des versions antérieures.

  4. Ouvrez options de projet pour PushDemo.iOS (double-cliquez sur le projet).

  5. Dans options de projet, sous build >de signature groupée iOS, vérifiez que votre compte développeur est sélectionné sous Team. Vérifiez ensuite que « Gérer automatiquement la signature » est sélectionnée et que votre certificat de signature et votre profil d’approvisionnement sont automatiquement sélectionnés.

    Note

    Si votre de certificat de signature et profil d’approvisionnement n’ont pas été sélectionnés automatiquement, choisissez d’approvisionnement manuel, puis cliquez sur options de signature groupées. Vérifiez que votre d’équipe de est sélectionné pour d’identité de signature et que votre profil d’approvisionnement PushDemo spécifique est sélectionné pour profil d’approvisionnement pour les de débogage et versions, ce qui garantit que iPhone est sélectionné pour le plateforme dans les deux cas.

  6. Dans PushDemo.iOS, ouvrez Droits d’utilisation.plist et vérifiez que Activer les notifications Push est cochée quand elle est consultée sous l’onglet Droits d’utilisation. Vérifiez ensuite que le paramètre d’environnement APS est défini sur de développement lorsqu’il est consulté dans l’onglet source .

Gérer les notifications Push pour iOS

  1. ControlCliquez sur dans le projet PushDemo.iOS PushDemo.iOS, choisissez nouveau dossier dans le menu Ajouter, puis cliquez sur Ajouter à l’aide de Services comme nom de dossier .

  2. ControlCliquez sur dans le dossier services , puis choisissez Nouveau fichier... dans le menu Ajouter .

  3. Sélectionnez classe vide générale, entrez DeviceInstallationService.cs pour l'nom de , puis cliquez sur nouveau ajout de l’implémentation suivante.

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

    Note

    Cette classe fournit un ID unique (à l’aide de la UIDevice.IdentifierForVendor valeur) et de la charge utile d’inscription du hub de notification.

  4. Ajoutez un nouveau dossier au projet PushDemo.iOS appelé Extensions puis ajoutez un de classe vide à ce dossier appelé NSDataExtensions.cs avec l’implémentation suivante.

    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. Dans AppDelegate.cs, vérifiez que les espaces de noms suivants ont été ajoutés en haut du fichier.

    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. Ajoutez des propriétés privées et leurs champs de stockage respectifs pour stocker une référence aux IPushDemoNotificationActionService, INotificationRegistrationServiceet implémentations IDeviceInstallationService.

    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. Ajoutez la méthode RegisterForRemoteNotifications pour inscrire les paramètres de notification utilisateur, puis pour les notifications à distance avec 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. Ajoutez la méthode CompleteRegistrationAsync pour définir la valeur de propriété IDeviceInstallationService.Token. Actualisez l’inscription et mettez en cache le jeton d’appareil s’il a été mis à jour depuis son dernier stockage.

    Task CompleteRegistrationAsync(NSData deviceToken)
    {
        DeviceInstallationService.Token = deviceToken.ToHexString();
        return NotificationRegistrationService.RefreshRegistrationAsync();
    }
    
  9. Ajoutez la méthode ProcessNotificationActions pour le traitement des données de notification NSDictionary et appel conditionnel 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. Remplacez la méthode RegisteredForRemoteNotifications en passant l’argument deviceToken à la méthode CompleteRegistrationAsync.

    public override void RegisteredForRemoteNotifications(
        UIApplication application,
        NSData deviceToken)
        => CompleteRegistrationAsync(deviceToken).ContinueWith((task)
            => { if (task.IsFaulted) throw task.Exception; });
    
  11. Remplacez la méthode ReceivedRemoteNotification en passant l’argument userInfo à la méthode ProcessNotificationActions.

    public override void ReceivedRemoteNotification(
        UIApplication application,
        NSDictionary userInfo)
        => ProcessNotificationActions(userInfo);
    
  12. Remplacez la méthode FailedToRegisterForRemoteNotifications pour consigner l’erreur.

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

    Note

    Il s’agit d’un espace réservé. Vous souhaiterez implémenter la journalisation et la gestion des erreurs appropriées pour les scénarios de production.

  13. Mettez à jour la méthode FinishedLaunching pour appeler Bootstrap.Begin juste après l’appel à Forms.Init passage de l’implémentation spécifique à la plateforme de IDeviceInstallationService.

    Bootstrap.Begin(() => new DeviceInstallationService());
    
  14. Dans la même méthode, demandez de manière conditionnelle l’autorisation et inscrivez-vous aux notifications à distance immédiatement après Bootstrap.Begin.

    if (DeviceInstallationService.NotificationsSupported)
    {
        UNUserNotificationCenter.Current.RequestAuthorization(
                UNAuthorizationOptions.Alert |
                UNAuthorizationOptions.Badge |
                UNAuthorizationOptions.Sound,
                (approvalGranted, error) =>
                {
                    if (approvalGranted && error == null)
                        RegisterForRemoteNotifications();
                });
    }
    
  15. Toujours dans FinishedLaunching , appelez ProcessNotificationActions immédiatement après l’appel à LoadApplication si l’argument options contient l’argument UIApplication.LaunchOptionsRemoteNotificationKey en passant l’objet userInfo résultant.

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

Tester la solution

Vous pouvez maintenant tester l’envoi de notifications via le service principal.

Envoyer une notification de test

  1. Ouvrez un nouvel onglet dans Postman.

  2. Définissez la requête sur POST, puis entrez l’adresse suivante :

    https://<app_name>.azurewebsites.net/api/notifications/requests
    
  3. Si vous avez choisi de terminer la section Authentifier les clients à l’aide d’une clé API section, veillez à configurer les en-têtes de requête pour inclure votre valeur apikey.

    Clé Valeur
    apikey <your_api_key>
  4. Choisissez l’option brute pour le corps , puis choisissez JSON dans la liste des options de format, puis incluez un espace réservé contenu json :

    {
        "text": "Message from Postman!",
        "action": "action_a"
    }
    
  5. Sélectionnez le bouton Code, qui se trouve sous le bouton Enregistrer en haut à droite de la fenêtre. La requête doit ressembler à l’exemple suivant lorsqu’elle s’affiche pour HTML (selon que vous avez inclus un apikey en-tête) :

    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. Exécutez l’application PushDemo sur une ou les deux plateformes cibles ( Android et iOS).

    Note

    Si vous effectuez des tests sur Android assurez-vous que vous n’êtes pas en cours d’exécution dans déboguer, ou si l’application a été déployée en exécutant l’application, forcez la fermeture de l’application et redémarrez-la à partir du lanceur.

  7. Dans l’application PushDemo, appuyez sur le bouton Inscrire.

  8. De retour dans Postman, fermez la fenêtre Générer des extraits de code (si vous ne l’avez pas déjà fait), puis cliquez sur le bouton Envoyer.

  9. Vérifiez que vous obtenez une réponse 200 OK dans Postman et que l’alerte s’affiche dans l’application montrant action ActionA reçue.

  10. Fermez l’application PushDemo , puis cliquez à nouveau sur le bouton Envoyer dans Postman.

  11. Vérifiez que vous obtenez à nouveau une réponse 200 OK dans Postman. Vérifiez qu’une notification s’affiche dans la zone de notification de l’application PushDemo avec le message correct.

  12. Appuyez sur la notification pour confirmer qu’elle ouvre l’application et affiche l’action ActionA reçue alerte.

  13. De retour dans Postman, modifiez le corps de la demande précédente pour envoyer une notification silencieuse spécifiant action_b au lieu de action_a pour l’action de valeur.

    {
        "action": "action_b",
        "silent": true
    }
    
  14. Une fois l’application toujours ouverte, cliquez sur le bouton Envoyer dans Postman.

  15. Vérifiez que vous obtenez une réponse 200 OK dans Postman et que l’alerte apparaît dans l’application montrant action ActionB reçue au lieu d'action ActionA reçue.

  16. Fermez l’application PushDemo , puis cliquez à nouveau sur le bouton Envoyer dans Postman.

  17. Vérifiez que vous obtenez une réponse 200 OK dans Postman et que la notification silencieuse n’apparaît pas dans la zone de notification.

Dépannage

Aucune réponse du service back-end

Lors du test local, assurez-vous que le service back-end est en cours d’exécution et utilise le port approprié.

Si vous effectuez des tests sur l’application API Azure , vérifiez que le service est en cours d’exécution et a été déployé et a démarré sans erreur.

Veillez à vérifier que vous avez spécifié correctement l’adresse de base dans Postman ou dans la configuration de l’application mobile lors du test via le client. L’adresse de base doit être https://<api_name>.azurewebsites.net/ ou https://localhost:5001/ lors du test localement.

Ne pas recevoir de notifications sur Android après le démarrage ou l’arrêt d’une session de débogage

Veillez à vous réinscrire après le démarrage ou l’arrêt d’une session de débogage. Le débogueur entraîne la génération d’un nouveau jeton Firebase . L’installation du hub de notification doit également être mise à jour.

Réception d’un code d’état 401 à partir du service principal

Vérifiez que vous définissez l’en-tête de requête apikey et que cette valeur correspond à celle que vous avez configurée pour le service principal.

Si vous recevez cette erreur lors du test localement, vérifiez que la valeur de clé que vous avez définie dans la configuration du client correspond à la valeur Authentication :ApiKey paramètre utilisateur utilisée par l’API .

Si vous effectuez des tests avec une application API , vérifiez que la valeur de clé dans le fichier de configuration du client correspond au paramètre d’application Authentication :ApiKey que vous utilisez dans l’application API .

Note

Si vous avez créé ou modifié ce paramètre après avoir déployé le service principal, vous devez redémarrer le service pour qu’il prenne effet.

Si vous avez choisi de ne pas terminer la section Authentifier les clients à l’aide d’une clé API, vérifiez que vous n’avez pas appliqué l’attribut Autoriser à la classe NotificationsController.

Réception d’un code d’état 404 à partir du service principal

Vérifiez que le point de terminaison et la méthode de requête HTTP sont corrects. Par exemple, les points de terminaison doivent être :

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

Ou lors du test local :

  • [PUT]
  • [DELETE]
  • [POST]https://localhost:5001/api/notifications/requests

Lorsque vous spécifiez l’adresse de base dans l’application cliente, assurez-vous qu’elle se termine par un /. L’adresse de base doit être https://<api_name>.azurewebsites.net/ ou https://localhost:5001/ lors du test localement.

Impossible d’inscrire et un message d’erreur du hub de notification s’affiche

Vérifiez que l’appareil de test dispose d’une connectivité réseau. Ensuite, déterminez le code d’état de la réponse Http en définissant un point d’arrêt pour inspecter la valeur de propriété StatusCode dans leHttpResponse .

Passez en revue les suggestions de résolution des problèmes précédentes, le cas échéant, en fonction du code d’état.

Définissez un point d’arrêt sur les lignes qui retournent ces codes d’état spécifiques pour l’API respective. Essayez ensuite d’appeler le service principal lors du débogage localement.

Vérifiez que le service principal fonctionne comme prévu via Postman à l’aide de la charge utile appropriée. Utilisez la charge utile réelle créée par le code client pour la plateforme en question.

Passez en revue les sections de configuration spécifiques à la plateforme pour vous assurer qu’aucune procédure n’a été manquée. Vérifiez que les valeurs appropriées sont résolues pour installation id et token variables pour la plateforme appropriée.

Impossible de résoudre un ID pour le message d’erreur de l’appareil s’affiche

Passez en revue les sections de configuration spécifiques à la plateforme pour vous assurer qu’aucune procédure n’a été manquée.

Étapes suivantes

Vous devez maintenant disposer d’une application Xamarin.Forms de base connectée à un hub de notification via un service back-end et recevoir des notifications.

Vous devrez probablement adapter l’exemple utilisé dans ce tutoriel pour qu’il corresponde à votre propre scénario. L’implémentation d’une gestion des erreurs plus robuste, une logique de nouvelle tentative et la journalisation sont également recommandées.

Visual Studio App Center peut être rapidement incorporé dans des applications mobiles fournissant des analytique et des diagnostics pour faciliter la résolution des problèmes.