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

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

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

Un back-end d’API web ASP.NET Core est utilisé pour gérer l’inscription des appareils pour le client à l’aide de l’approche d’installation la plus récente et la meilleure. 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 pour les opérations back-end. Pour plus d’informations sur l’approche globale, consultez la documentation Inscription à partir de votre back-end d’application .

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

Prérequis

Pour suivre, vous avez besoin des éléments suivants :

Pour Android, vous devez disposer des éléments suivants :

  • Un développeur a déverrouillé un appareil physique ou un émulateur (exécutant l’API 26 et ultérieure avec google Play Services installés).

Pour iOS, vous devez disposer des éléments suivants :

Notes

Le simulateur iOS ne prend pas en charge les notifications à distance. Par conséquent, un appareil physique est requis 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 tutoriel.

Vous pouvez suivre les étapes de cet exemple de premier principe sans expérience préalable. Toutefois, vous aurez avantage à vous familiariser avec les aspects suivants.

Les étapes fournies sont spécifiques à macOS. Il est possible de suivre sur Windows en ignorant les aspects iOS .

Configurer Push Notification Services et Azure Notification Hub

Dans cette section, vous allez configurer 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 en entrant PushDemo comme nom du projet.

    Notes

    Un nom unique sera généré pour vous. Par défaut, il s’agit d’une variante en minuscules du nom que vous avez fourni et d’un nombre généré séparé par un tiret. Vous pouvez le modifier si vous le souhaitez, à condition qu’il reste globalement unique.

  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 , effectuez les étapes suivantes.

    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 une application.

    3. Sélectionnez Télécharger google-services.json. Enregistrez ensuite le fichier dans un dossier local pour une utilisation ultérieure, puis sélectionnez Suivant.

      Télécharger google-services.json

    4. Sélectionnez Suivant.

    5. Sélectionnez Continuer vers la console

      Notes

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

  4. Dans la console Firebase, sélectionnez l’engrenage de votre projet. Sélectionnez ensuite Paramètres du projet.

    Sélectionnez Paramètres du projet

    Notes

    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é du 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 encore inscrit votre application, accédez au portail d’approvisionnement iOS dans le Centre de développement Apple. Connectez-vous au portail avec votre ID Apple, accédez à Certificats, Identificateurs & Profils, puis sélectionnez Identificateurs. Cliquez + pour inscrire une nouvelle application.

    Page ID d’application du portail d’approvisionnement iOS

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

    Page inscrire un nouvel ID dans le portail d’approvisionnement iOS

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

    • Description : tapez un nom descriptif pour votre application.

    • ID de bundle : entrez un ID d’offre groupée au format com.organization_identifier<>.<>product_name comme indiqué dans le Guide de distribution des applications. Dans la capture d’écran suivante, la mobcat valeur est utilisée comme identificateur de organization et la valeur PushDemo est utilisée comme nom de produit.

      Page d’ID d’inscription d’application du portail d’approvisionnement iOS

    • 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 vous demande de confirmer les informations. Sélectionnez Continuer, puis s’inscrire pour confirmer le nouvel ID d’application.

      Confirmer le nouvel ID d’application

      Après avoir sélectionné Inscrire, vous voyez le nouvel ID d’application comme é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 la configuration de votre ID d’application .

Création d’un certificat pour Notification Hubs

Un certificat est requis pour permettre au hub de notification de fonctionner avec 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 sur Notification Hub (approche d’origine)

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

Cette approche plus récente présente un certain nombre d’avantages, comme indiqué dans l’authentification basée sur des jetons (HTTP/2) pour APNS. Moins d’étapes sont requises, mais sont également obligatoires pour des scénarios spécifiques. Toutefois, des étapes ont été fournies pour les deux approches, car l’une ou l’autre fonctionne dans le cadre 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 d’accès au trousseau. Il peut être ouvert à partir du dossier Utilitaires ou du dossier Autre du Launchpad.

  2. Sélectionnez 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 un nouveau certificat

    Notes

    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 que l’autorité de certification Apple Worldwide Developer Relations n’est pas le premier élément de la liste. Vérifiez que vous disposez d’un élément non clé ou que la clé d’autorité de certification Apple Worldwide Developer Relations est sélectionnée avant de générer la demande de signature de certificat (CSR).

  3. Sélectionnez votre adresse de Email d’utilisateur, entrez votre valeur Nom commun, assurez-vous que vous spécifiez Enregistré sur le disque, puis sélectionnez Continuer. Laissez l’adresse Email de l’autorité de certification vide, car elle n’est pas nécessaire.

    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. Dans la page Certificats, identificateurs & profils du portail d’approvisionnement iOS, faites défiler jusqu’à l’option Notifications Push coché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 Certificat TLS/SSL de développement .

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

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

    Notes

    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 que le portail a créé le certificat, sélectionnez le bouton Télécharger . Enregistrez le certificat et mémorisez l’emplacement où 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 .

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

    Notes

    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 le nouveau certificat

    Notes

    Bien que le nom de votre certificat puisse être différent, le nom est préfixé par Apple Development iOS Push Services et l’identificateur de bundle approprié est associé.

  10. Dans Accès au trousseau, Contrôle + Cliquez 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 le 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 ignorer 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 les APN.

    Notes

    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 les jetons
  1. Notez les détails suivants :

    • Préfixe d’ID d’application (ID d’équipe)
    • ID d’offre groupée
  2. De retour dans Certificats, identificateurs & profils, cliquez sur Clés.

    Notes

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

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

  4. Fournissez une valeur de nom de clé appropriée, puis case activée l’option APNS (Apple Push Notifications Service), puis cliquez sur Continuer, puis sur 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é.

    Notes

    Veillez à conserver votre fichier p8 dans un endroit sécurisé (et à enregistrer 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 sur 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, telle que Visual Studio Code. Notez la valeur de la clé (entre -----BEGIN PRIVATE KEY----- et -----END PRIVATE KEY-----).

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

    Notes

    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 les informations APNS :

  • ID d’équipe (voir l’étape 1)
  • ID de bundle (voir é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 Développement d’applications iOS sous Développement comme type de profil d’approvisionnement, puis sélectionnez Continuer.

    Liste des 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.

    Notes

    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’en 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 le 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 des jetons. 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, 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’abonnement cible dans la liste déroulante
    Groupe de ressources : Créer un groupe de ressources (ou en choisir un existant)

    DÉTAILS DE L’ESPACE DE NOMS

    Espace de noms du hub de notification : Entrez un nom global unique pour l’espace de noms Notification Hub

    Notes

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

    DÉTAILS DU HUB DE NOTIFICATION

    Notification Hub : Entrez un nom pour le hub de notification
    Emplacement: Choisir un emplacement approprié dans la liste déroulante
    Niveau tarifaire : Conserver l’option Gratuit par défaut

    Notes

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

  4. Une fois le hub de notification 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 GÉRER).

  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 les 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 .

Notes

Utilisez production pour le 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 bac à sable .

  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 d’offre groupée
    • ID d’équipe
    • Jeton
  3. Choisissez Bac à sable.

  4. Sélectionnez Enregistrer.

Configurer votre hub de notification avec les informations FCM

  1. Sélectionnez Google (GCM/FCM) dans la section Paramètres du menu de gauche.
  2. Entrez la clé de serveur que 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 le back-end d’API web ASP.NET Core pour gérer l’inscription des appareils et l’envoi de notifications à l’application mobile Flutter.

Créer un projet web

  1. Dans Visual Studio, sélectionnez Fichier>Nouvelle solution.

  2. SélectionnezApplication>.NET Core>ASP.NET Core>API>Suivant.

  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 comme Nom du projet , puis sélectionnez Créer.

  5. Démarrez le débogage (Entrée de commande + ) pour tester l’application avec modèle.

    Notes

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

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

    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 Controllers , puis supprimez WeatherForecastController.cs.

  7. Supprimer WeatherForecast.cs.

  8. Configurez les valeurs de configuration locales à l’aide de l’outil Secret Manager. Le découplage des 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 chaîne de connexion valeurs. Vous en avez pris note dans la section Créer un hub de notification . 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

    Notes

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

Authentifier les 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 l’intergiciel ASP.NET.

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

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

    Notes

    Vous devez remplacer la valeur d’espace réservé par la vôtre et en prendre note.

  2. Contrôle + Cliquez sur le projet PushDemoApi , choisissez Nouveau dossier dans le menu Ajouter , puis cliquez sur Ajouter à l’aide de l’authentification comme nom du dossier.

  3. Contrôle + Cliquez sur le dossier Authentification , puis choisissez Nouveau fichier... dans le menu Ajouter .

  4. Sélectionnez Classe vide générale>, entrez ApiKeyAuthOptions.cs pour le Nom, puis cliquez sur Nouveau en ajoutant 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 une autre classe vide au dossier d’authentification appelée 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));
            }
        }
    }
    

    Notes

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

    Notes

    Cette méthode d’extension simplifie le code de configuration du middleware dans Startup.cs le rendant plus lisible et généralement plus facile à suivre.

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

    using PushDemoApi.Authentication;
    using PushDemoApi.Models;
    using PushDemoApi.Services;
    
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddControllers();
    
        services.AddAuthentication(options =>
        {
            options.DefaultAuthenticateScheme = ApiKeyAuthOptions.DefaultScheme;
            options.DefaultChallengeScheme = ApiKeyAuthOptions.DefaultScheme;
        }).AddApiKeyAuth(Configuration.GetSection("Authentication").Bind);
    }
    
  8. Toujours dans Startup.cs, mettez à jour la méthode Configure pour appeler les méthodes d’extension UseAuthentication et UseAuthorization sur iApplicationBuilder de l’application. Vérifiez que ces méthodes sont appelées après UseRouting et avant l’application. UtilisezEndpoints.

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

    Notes

    L’appel de UseAuthentication inscrit l’intergiciel 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 de logiciel d’injection de dépendances (DI), qui est une technique permettant d’obtenir l’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 back-end est encapsulée dans un service. Le service est inscrit et mis à disposition via une abstraction appropriée.

  1. Contrôle + Cliquez sur le dossier Dépendances , puis choisissez Gérer les packages NuGet....

  2. Recherchez Microsoft.Azure.NotificationHubs et vérifiez qu’il est vérifié.

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

  4. Contrôle + Cliquez sur le projet PushDemoApi , choisissez Nouveau dossier dans le menu Ajouter , puis cliquez sur Ajouter à l’aide de modèles comme nom du dossier.

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

  6. Sélectionnez Général>Classe vide, entrez PushTemplates.cs pour le Nom, puis cliquez sur Nouveau en ajoutant 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)\" }";
            }
        }
    }
    

    Notes

    Cette classe contient les charges utiles de notification avec jetons pour les notifications génériques et silencieuses requises par ce scénario. Les charges utiles sont définies en dehors de l’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 tutoriel. Pour la production, envisagez des modèles personnalisés.

  7. Ajoutez une autre classe vide au dossier Models appelée 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 une autre classe vide au dossier Models appelée 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 une autre classe vide au dossier Models appelée 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ée 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 une classe vide au dossier Services appelée 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);
            }
        }
    }
    

    Notes

    L’expression de balise fournie à SendTemplateNotificationAsync est limitée à 20 balises. Elle est limitée à 6 pour la plupart des opérateurs, mais l’expression contient uniquement des OR (||) dans ce cas. S’il y a 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 NotificationHubsService en tant qu’implémentation singleton d’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. Contrôle + Cliquez sur le dossier Contrôleurs , puis choisissez Nouveau fichier... dans le menu Ajouter .

  2. Sélectionnez ASP.NET Core>Classe de contrôleur d’API Web, entrez NotificationsContrôleur comme Nom, puis cliquez sur Nouveau.

    Notes

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

  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 basé sur un modèle 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
    }
    

    Notes

    La classe de base Controller prend en charge les vues, mais cela n’est pas nécessaire dans ce cas et controllerBase peut donc être utilisé à la place. Si vous suivez avec 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 notificationsController avec l’attribut Authorize .

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

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

  8. Démarrez le débogage (Entrée de commande + ) pour vérifier que l’application fonctionne avec le nouveau NotificationsController et retourne une status non autorisée 401.

    Notes

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

  9. Dans 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 l’applicationUrl https trouvée dans Propriétés>launchSettings.json.

    <applicationUrl>/api/notifications
    

    Notes

    ApplicationUrl doit être «https://localhost:5001 » pour le profil par défaut. Si vous utilisez IIS (valeur par défaut dans Visual Studio 2019 sur Windows), vous devez utiliser l’applicationUrl spécifié 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 , 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 .

    Notes

    Vous devez recevoir un status 200 OK avec du contenu JSON.

    Si vous recevez un avertissement de vérification de certificat SSL , vous pouvez désactiver le paramètre Postman de demande de vérification du certificat SSL dans paramètres.

  12. Remplacez les méthodes de classe modèles 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 back-end.

  1. Connectez-vous au portail Azure.

  2. Cliquez sur Créer une ressource, 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 l’abonnement cible dans lequel vous avez créé le hub de notification.

    Groupe de ressources :
    Choisissez le groupe de ressources dans lequel vous avez créé le hub de notification.

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

    Notes

    Passez de l’option par défaut à un plan qui inclut la prise en charge SSL . Sinon, vous devez prendre les mesures appropriées lorsque vous utilisez l’application mobile pour empêcher le blocage des requêtes HTTP .

    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 l’application API approvisionnée, accédez à cette ressource.

  5. Notez la propriété URL 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 tutoriel.

    Notes

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

    Notes

    Il s’agit des mêmes paramètres que vous avez définis précédemment dans les paramètres utilisateur. Vous devriez pouvoir les copier. Le paramètre Authentication :ApiKey est requis uniquement si vous choisissez d’effectuer la section Authentifier les clients à l’aide d’une clé API . Pour les scénarios de production, vous pouvez examiner des options telles qu’Azure KeyVault. Ceux-ci ont été ajoutés en tant que paramètres d’application pour plus de simplicité dans ce cas.

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

Publier le service back-end

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

Notes

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. Si ce n’est déjà fait, modifiez votre configuration de Débogage en Version .

  2. Contrôle + Cliquez sur 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 précédente.

  4. Sélectionnez l’application 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 dans 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 , ouvrez 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 publier le service back-end précédente.

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

    Notes

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

  2. Si vous avez choisi d’effectuer la section Authentifier les clients à l’aide d’une clé API , 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 du Corps, puis choisissez JSON dans la liste des options de format, puis incluez du contenu JSON d’espace réservé :

    {}
    
  4. Cliquez sur Envoyer.

    Notes

    Vous devez recevoir un status 422 UnprocessableEntity du service.

  5. Effectuez à nouveau les étapes 1 à 4, mais cette fois, en spécifiant le point de terminaison des demandes pour valider, vous recevez une réponse de demande incorrecte 400 .

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

Notes

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 Flutter multiplateforme

Dans cette section, vous allez créer une application mobile Flutter qui implémente des notifications Push de manière multiplateforme.

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

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

Notes

Vous effectuez généralement les actions d’inscription (et de désinscription) pendant le point approprié du cycle de vie de l’application (ou dans le cadre de votre expérience de première exécution) sans entrées d’inscription/désinscription d’utilisateur explicites. 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 Flutter

  1. Ouvrez une nouvelle instance de Visual Studio Code.

  2. Ouvrez la palette de commandes (Maj + , commande + P).

  3. Sélectionnez la commande Flutter : Nouveau projet , puis appuyez sur Entrée.

  4. Entrez push_demo pour le nom du projet , puis sélectionnez un emplacement de projet.

  5. Lorsque vous y êtes invité, choisissez Obtenir des packages.

  6. Contrôle + Cliquez sur le dossier kotlin (sous app>src>main), puis choisissez Révéler dans le Finder. Ensuite, renommez les dossiers enfants (sous le dossier kotlin ) en com, <your_organization>et pushdemo respectivement.

    Notes

    Lorsque vous utilisez le modèle Visual Studio Code , ces dossiers par défaut sont com, par exemple, <project_name>. En supposant que mobcat est utilisé pour le organization, la structure de dossiers doit apparaître de manière indicative comme suit :

    • Kotlin
      • Com
        • mobcat
          • pushdemo
  7. De retour dans Visual Studio Code, mettez à jour la valeur applicationId dans android>app>build.gradle sur com.<your_organization>.pushdemo.

    Notes

    Vous devez utiliser votre propre nom organization pour l’espace <réservé your_organization>. Par exemple, l’utilisation de mobcat comme organization entraîne une valeur de nom de packagecom.mobcat.pushdemo.

  8. Mettez à jour l’attribut de package dans les fichiers AndroidManifest.xml, respectivement sous leprofilsrc>debug, src>main et src>. Assurez-vous que les valeurs correspondent à l’id d’application que vous avez utilisé à l’étape précédente.

    <manifest
        xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.<your_organization>.pushdemo>">
        ...
    </manifest>
    
  9. Mettez à jour l’attribut android:label dans le fichier AndroidManifest.xml sous src>main vers PushDemo. Ensuite, ajoutez l’attribut android:allowBackup , directement sous android:label, en définissant sa valeur sur false.

    <application
        android:name="io.flutter.app.FlutterApplication"
        android:label="PushDemo"
        android:allowBackup="false"
        android:icon="@mipmap/ic_launcher">
        ...
    </application>
    
  10. Ouvrez le fichier build.gradle au niveau de l’application (android>app>build.gradle), puis mettez à jour compileSdkVersion (à partir de la section Android ) pour utiliser l’API 29. Ensuite, mettez à jour les valeurs minSdkVersion et targetSdkVersion (à partir de la section defaultConfig ), respectivement sur 26 et 29 .

    Notes

    Seuls les appareils exécutant l’API de niveau 26 et supérieur sont pris en charge dans le cadre de ce didacticiel, mais vous pouvez l’étendre pour prendre en charge les appareils exécutant des versions antérieures.

  11. Contrôle + Cliquez sur le dossier ios , puis choisissez Ouvrir dans Xcode.

  12. Dans Xcode, cliquez sur Runner ( le xcodeproj en haut, et non le dossier). Ensuite, sélectionnez la cible Runner et sélectionnez l’onglet Général . Une fois la configuration de build Tout sélectionné, mettez à jour l’identificateur de bundle sur com.<your_organization>.PushDemo.

    Notes

    Vous devez utiliser votre propre nom organization pour l’espace <réservé your_organization>. Par exemple, l’utilisation de mobcat comme organization entraîne une valeur d’identificateur groupéde com.mobcat.PushDemo.

  13. Cliquez sur Info.plist , puis mettez à jour la valeur du nom de l’offre groupée sur PushDemo

  14. Fermez Xcode et revenez à Visual Studio Code.

  15. De retour dans Visual Studio Code, ouvrez pubspec.yaml, ajoutez les packages http et flutter_secure_storageDart en tant que dépendances. Ensuite, enregistrez le fichier et cliquez sur Obtenir des packages lorsque vous y êtes invité.

    dependencies:
      flutter:
        sdk: flutter
    
      http: ^0.12.1
      flutter_secure_storage: ^3.3.3
    
  16. Dans Terminal, remplacez le répertoire par le dossier ios (pour votre projet Flutter). Ensuite, exécutez la commande d’installation du pod pour installer de nouveaux pods (requis par le package flutter_secure_storage ).

  17. Contrôle + Cliquez sur le dossier lib , puis choisissez Nouveau fichier dans le menu en utilisant main_page.dart comme nom de fichier. Ensuite, ajoutez le code suivant.

    import 'package:flutter/material.dart';
    
    class MainPage extends StatefulWidget {
      @override
      _MainPageState createState() => _MainPageState();
    }
    
    class _MainPageState extends State<MainPage> {
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          body: SafeArea(
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.stretch,
              children: <Widget>[],
            )
          )
        );
      }
    }
    
  18. Dans main.dart, remplacez le code modèle par ce qui suit.

    import 'package:flutter/material.dart';
    import 'package:push_demo/main_page.dart';
    
    final navigatorKey = GlobalKey<NavigatorState>();
    
    void main() => runApp(MaterialApp(home: MainPage(), navigatorKey: navigatorKey));
    
  19. Dans Terminal, générez et exécutez l’application sur chaque plateforme cible pour tester l’application modèle s’exécute sur vos appareils. Assurez-vous que les appareils pris en charge sont connectés.

    flutter run
    

Implémenter les composants multiplateformes

  1. Contrôle + Cliquez sur le dossier lib , puis choisissez Nouveau dossier dans le menu en utilisant modèles comme nom du dossier.

  2. Contrôle + Cliquez sur le dossier models , puis choisissez Nouveau fichier dans le menu en utilisant device_installation.dart comme nom de fichier. Ensuite, ajoutez le code suivant.

    class DeviceInstallation {
        final String deviceId;
        final String platform;
        final String token;
        final List<String> tags;
    
        DeviceInstallation(this.deviceId, this.platform, this.token, this.tags);
    
        DeviceInstallation.fromJson(Map<String, dynamic> json)
          : deviceId = json['installationId'],
            platform = json['platform'],
            token = json['pushChannel'],
            tags = json['tags'];
    
        Map<String, dynamic> toJson() =>
        {
          'installationId': deviceId,
          'platform': platform,
          'pushChannel': token,
          'tags': tags,
        };
    }
    
  3. Ajoutez un nouveau fichier au dossier models appelé push_demo_action.dart définissant l’énumération des actions prises en charge dans cet exemple.

    enum PushDemoAction {
      actionA,
      actionB,
    }
    
  4. Ajoutez un nouveau dossier au projet appelé services , puis ajoutez un nouveau fichier à ce dossier appelé device_installation_service.dart avec l’implémentation suivante.

    import 'package:flutter/services.dart';
    
    class DeviceInstallationService {
      static const deviceInstallation = const MethodChannel('com.<your_organization>.pushdemo/deviceinstallation');
      static const String getDeviceIdChannelMethod = "getDeviceId";
      static const String getDeviceTokenChannelMethod = "getDeviceToken";
      static const String getDevicePlatformChannelMethod = "getDevicePlatform";
    
      Future<String> getDeviceId() {
        return deviceInstallation.invokeMethod(getDeviceIdChannelMethod);
      }
    
      Future<String> getDeviceToken() {
        return deviceInstallation.invokeMethod(getDeviceTokenChannelMethod);
      }
    
      Future<String> getDevicePlatform() {
        return deviceInstallation.invokeMethod(getDevicePlatformChannelMethod);
      }
    }
    

    Notes

    Vous devez utiliser votre propre nom organization pour l’espace <réservé your_organization>. Par exemple, l’utilisation de mobcat comme organization entraîne un nom MethodChannelde com.mobcat.pushdemo/deviceinstallation.

    Cette classe encapsule l’utilisation de la plateforme native sous-jacente pour acquérir les détails d’installation de l’appareil requis. Un MethodChannel facilite la communication asynchrone bidirectionnelle avec les plateformes natives sous-jacentes. L’équivalent spécifique à la plateforme pour ce canal sera créé dans les étapes ultérieures.

  5. Ajoutez un autre fichier à ce dossier appelé notification_action_service.dart avec l’implémentation suivante.

    import 'package:flutter/services.dart';
    import 'dart:async';
    import 'package:push_demo/models/push_demo_action.dart';
    
    class NotificationActionService {
      static const notificationAction =
          const MethodChannel('com.<your_organization>.pushdemo/notificationaction');
      static const String triggerActionChannelMethod = "triggerAction";
      static const String getLaunchActionChannelMethod = "getLaunchAction";
    
      final actionMappings = {
        'action_a' : PushDemoAction.actionA,
        'action_b' : PushDemoAction.actionB
      };
    
      final actionTriggeredController = StreamController.broadcast();
    
      NotificationActionService() {
        notificationAction
            .setMethodCallHandler(handleNotificationActionCall);
      }
    
      Stream get actionTriggered => actionTriggeredController.stream;
    
      Future<void> triggerAction({action: String}) async {
    
        if (!actionMappings.containsKey(action)) {
          return;
        }
    
        actionTriggeredController.add(actionMappings[action]);
      }
    
      Future<void> checkLaunchAction() async {
        final launchAction = await notificationAction.invokeMethod(getLaunchActionChannelMethod) as String;
    
        if (launchAction != null) {
          triggerAction(action: launchAction);
        }
      }
    
      Future<void> handleNotificationActionCall(MethodCall call) async {
        switch (call.method) {
          case triggerActionChannelMethod:
            return triggerAction(action: call.arguments as String);
          default:
            throw MissingPluginException();
            break;
        }
      }
    }
    

    Notes

    Il s’agit d’un mécanisme simple pour centraliser la gestion des actions de notification afin qu’elles puissent être gérées de manière multiplateforme à l’aide d’une énumération fortement typée. Le service permet à la plateforme native sous-jacente de déclencher une action, lorsqu’une action est spécifiée dans la charge utile de notification. Il permet également au code commun de case activée rétrospectivement si une action a été spécifiée lors du lancement de l’application une fois que Flutter est prêt à la traiter. Par exemple, lorsque l’application est lancée en appuyant sur une notification à partir du centre de notifications.

  6. Ajoutez un nouveau fichier au dossier services appelé notification_registration_service.dart avec l’implémentation suivante.

    import 'dart:convert';
    import 'package:flutter/services.dart';
    import 'package:http/http.dart' as http;
    import 'package:push_demo/services/device_installation_service.dart';
    import 'package:push_demo/models/device_installation.dart';
    import 'package:flutter_secure_storage/flutter_secure_storage.dart';
    
    class NotificationRegistrationService {
      static const notificationRegistration =
          const MethodChannel('com.<your_organization>.pushdemo/notificationregistration');
    
      static const String refreshRegistrationChannelMethod = "refreshRegistration";
      static const String installationsEndpoint = "api/notifications/installations";
      static const String cachedDeviceTokenKey = "cached_device_token";
      static const String cachedTagsKey = "cached_tags";
    
      final deviceInstallationService = DeviceInstallationService();
      final secureStorage = FlutterSecureStorage();
    
      String baseApiUrl;
      String apikey;
    
      NotificationRegistrationService(this.baseApiUrl, this.apikey) {
        notificationRegistration
            .setMethodCallHandler(handleNotificationRegistrationCall);
      }
    
      String get installationsUrl => "$baseApiUrl$installationsEndpoint";
    
      Future<void> deregisterDevice() async {
        final cachedToken = await secureStorage.read(key: cachedDeviceTokenKey);
        final serializedTags = await secureStorage.read(key: cachedTagsKey);
    
        if (cachedToken == null || serializedTags == null) {
          return;
        }
    
        var deviceId = await deviceInstallationService.getDeviceId();
    
        if (deviceId.isEmpty) {
          throw "Unable to resolve an ID for the device.";
        }
    
        var response = await http
            .delete("$installationsUrl/$deviceId", headers: {"apikey": apikey});
    
        if (response.statusCode != 200) {
          throw "Deregister request failed: ${response.reasonPhrase}";
        }
    
        await secureStorage.delete(key: cachedDeviceTokenKey);
        await secureStorage.delete(key: cachedTagsKey);
      }
    
      Future<void> registerDevice(List<String> tags) async {
        try {
          final deviceId = await deviceInstallationService.getDeviceId();
          final platform = await deviceInstallationService.getDevicePlatform();
          final token = await deviceInstallationService.getDeviceToken();
    
          final deviceInstallation =
              DeviceInstallation(deviceId, platform, token, tags);
    
          final response = await http.put(installationsUrl,
              body: jsonEncode(deviceInstallation),
              headers: {"apikey": apikey, "Content-Type": "application/json"});
    
          if (response.statusCode != 200) {
            throw "Register request failed: ${response.reasonPhrase}";
          }
    
          final serializedTags = jsonEncode(tags);
    
          await secureStorage.write(key: cachedDeviceTokenKey, value: token);
          await secureStorage.write(key: cachedTagsKey, value: serializedTags);
        } on PlatformException catch (e) {
          throw e.message;
        } catch (e) {
          throw "Unable to register device: $e";
        }
      }
    
      Future<void> refreshRegistration() async {
        final currentToken = await deviceInstallationService.getDeviceToken();
        final cachedToken = await secureStorage.read(key: cachedDeviceTokenKey);
        final serializedTags = await secureStorage.read(key: cachedTagsKey);
    
        if (currentToken == null ||
            cachedToken == null ||
            serializedTags == null ||
            currentToken == cachedToken) {
          return;
        }
    
        final tags = jsonDecode(serializedTags);
    
        return registerDevice(tags);
      }
    
      Future<void> handleNotificationRegistrationCall(MethodCall call) async {
        switch (call.method) {
          case refreshRegistrationChannelMethod:
            return refreshRegistration();
          default:
            throw MissingPluginException();
            break;
        }
      }
    }
    

    Notes

    Cette classe encapsule l’utilisation de DeviceInstallationService et les demandes adressées au service principal pour effectuer les actions d’inscription, de désinscription et d’actualisation requises. L’argument apiKey n’est requis que si vous avez choisi d’effectuer la section Authentifier les clients à l’aide d’une clé API .

  7. Ajoutez un nouveau fichier au dossier lib appelé config.dart avec l’implémentation suivante.

    class Config {
      static String apiKey = "API_KEY";
      static String backendServiceEndpoint = "BACKEND_SERVICE_ENDPOINT";
    }
    

    Notes

    Cette méthode est utilisée comme un moyen simple de définir les secrets d’application. Remplacez les valeurs d’espace réservé par les vôtres. Vous devez avoir pris note de ceux-ci lorsque vous avez créé le service back-end. L’URL de l’application API doit être https://<api_app_name>.azurewebsites.net/. Le membre apiKey n’est requis que si vous avez choisi d’effectuer la section Authentifier les clients à l’aide d’une clé API .

    Veillez à l’ajouter à votre fichier gitignore pour éviter de valider ces secrets dans le contrôle de code source.

Implémenter l’interface utilisateur multiplateforme

  1. Dans main_page.dart, remplacez la fonction build par ce qui suit.

    @override
    Widget build(BuildContext context) {
    return Scaffold(
        body: Padding(
          padding: const EdgeInsets.symmetric(horizontal: 20.0, vertical: 40.0),
          child: Column(
            mainAxisAlignment: MainAxisAlignment.end,
            crossAxisAlignment: CrossAxisAlignment.stretch,
            children: <Widget>[
              FlatButton(
                child: Text("Register"),
                onPressed: registerButtonClicked,
              ),
              FlatButton(
                child: Text("Deregister"),
                onPressed: deregisterButtonClicked,
              ),
            ],
          ),
        ),
      );
    }
    
  2. Ajoutez les importations requises en haut du fichier main_page.dart .

    import 'package:push_demo/services/notification_registration_service.dart';
    import 'config.dart';
    
  3. Ajoutez un champ à la classe _MainPageState pour stocker une référence à NotificationRegistrationService.

    final notificationRegistrationService = NotificationRegistrationService(Config.backendServiceEndpoint, Config.apiKey);
    
  4. Dans la classe _MainPageState , implémentez les gestionnaires d’événements pour les boutons Inscrire et Annuler l’inscriptiondes événements surPressed . Appelez les méthodes Register/Deregister correspondantes, puis affichez une alerte pour indiquer le résultat.

    void registerButtonClicked() async {
        try {
          await notificationRegistrationService.registerDevice(List<String>());
          await showAlert(message: "Device registered");
        }
        catch (e) {
          await showAlert(message: e);
        }
      }
    
      void deregisterButtonClicked() async {
        try {
          await notificationRegistrationService.deregisterDevice();
          await showAlert(message: "Device deregistered");
        }
        catch (e) {
          await showAlert(message: e);
        }
      }
    
      Future<void> showAlert({ message: String }) async {
        return showDialog<void>(
          context: context,
          barrierDismissible: false,
          builder: (BuildContext context) {
            return AlertDialog(
              title: Text('PushDemo'),
              content: SingleChildScrollView(
                child: ListBody(
                  children: <Widget>[
                    Text(message),
                  ],
                ),
              ),
              actions: <Widget>[
                FlatButton(
                  child: Text('OK'),
                  onPressed: () {
                    Navigator.of(context).pop();
                  },
                ),
              ],
            );
          },
        );
      }
    
  5. Maintenant, dans main.dart, vérifiez que les importations suivantes sont présentes en haut du fichier.

    import 'package:flutter/material.dart';
    import 'package:push_demo/models/push_demo_action.dart';
    import 'package:push_demo/services/notification_action_service.dart';
    import 'package:push_demo/main_page.dart';
    
  6. Déclarez une variable pour stocker la référence à un instance de NotificationActionService et initialisez-la.

    final notificationActionService = NotificationActionService();
    
  7. Ajoutez des fonctions pour gérer l’affichage d’une alerte lorsqu’une action est déclenchée.

    void notificationActionTriggered(PushDemoAction action) {
      showActionAlert(message: "${action.toString().split(".")[1]} action received");
    }
    
    Future<void> showActionAlert({ message: String }) async {
      return showDialog<void>(
        context: navigatorKey.currentState.overlay.context,
        barrierDismissible: false,
        builder: (BuildContext context) {
          return AlertDialog(
            title: Text('PushDemo'),
            content: SingleChildScrollView(
              child: ListBody(
                children: <Widget>[
                  Text(message),
                ],
              ),
            ),
            actions: <Widget>[
              FlatButton(
                child: Text('OK'),
                onPressed: () {
                  Navigator.of(context).pop();
                },
              ),
            ],
          );
        },
      );
    }
    
  8. Mettez à jour la fonction main pour observer le flux d’action NotificationActionServiceTriggered et case activée pour toutes les actions capturées lors du lancement de l’application.

    void main() async {
      runApp(MaterialApp(home: MainPage(), navigatorKey: navigatorKey,));
      notificationActionService.actionTriggered.listen((event) { notificationActionTriggered(event as PushDemoAction); });
      await notificationActionService.checkLaunchAction();
    }
    

    Notes

    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 au lieu d’afficher une alerte dans ce cas.

Configurer le projet Android natif pour les notifications Push

Ajouter le fichier JSON des services Google

  1. Contrôle + Cliquez sur le dossier android , puis choisissez Ouvrir dans Android Studio. Basculez ensuite vers la vue Projet (si ce n’est pas déjà le cas).

  2. Recherchez le fichier google-services.json que vous avez téléchargé précédemment lorsque vous avez configuré le projet PushDemo dans la console Firebase. Ensuite, faites-le glisser dans le répertoire racine du moduled’application (applicationandroid>android>).

Configurer les paramètres de build et les autorisations

  1. Basculez la vue Projet sur Android.

  2. Ouvrez AndroidManifest.xml, puis ajoutez les autorisations INTERNET et READ_PHONE_STATE après l’élément application avant la balise fermante .

    <manifest>
        <application>...</application>
        <uses-permission android:name="android.permission.INTERNET" />
        <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    </manifest>
    

Ajouter les KITS de développement logiciel (SDK) Firebase

  1. Dans Android Studio, ouvrez le fichier build.gradle au niveau du projet (Gradle Scripts>build.gradle (Projet : android)). et vérifiez que vous avez le classpath « com.google.gms :google-services » dans le buildscript> nœud dépendances.

    buildscript {
    
      repositories {
        // Check that you have the following line (if not, add it):
        google()  // Google's Maven repository
      }
    
      dependencies {
        // ...
    
        // Add the following line:
        classpath 'com.google.gms:google-services:4.3.3'  // Google Services plugin
      }
    }
    
    allprojects {
      // ...
    
      repositories {
        // Check that you have the following line (if not, add it):
        google()  // Google's Maven repository
        // ...
      }
    }
    

    Notes

    Veillez à référencer la dernière version conformément aux instructions fournies dans la console Firebase lorsque vous avez créé le projet Android.

  2. Dans le fichier build.gradle au niveau de l’application (Gradle Scripts>build.gradle (Module : app)), appliquez le plug-in Google Services Gradle. Appliquez le plug-in juste au-dessus du nœud Android .

    // ...
    
    // Add the following line:
    apply plugin: 'com.google.gms.google-services'  // Google Services plugin
    
    android {
      // ...
    }
    
  3. Dans le même fichier, dans le nœud dépendances , ajoutez la dépendance pour la bibliothèque Android Cloud Messaging .

    dependencies {
        // ...
        implementation 'com.google.firebase:firebase-messaging:20.2.0'
    }
    

    Notes

    Veillez à référencer la dernière version conformément à la documentation du client Android Cloud Messaging.

  4. Enregistrez les modifications, puis cliquez sur le bouton Synchroniser maintenant (à partir de l’invite de la barre d’outils) ou Synchroniser le projet avec Gradle Files.

Gérer les notifications Push pour Android

  1. Dans Android Studio, Ctrl + Cliquez sur le dossier du package com.your_organization.pushdemo<> (app>src>main>kotlin), choisissez Package dans le menu Nouveau. Entrez services comme nom, puis appuyez sur Retour.

  2. Contrôle + Cliquez sur le dossier services , puis choisissez Fichier/classe Kotlin dans le menu Nouveau . Entrez DeviceInstallationService comme nom, puis appuyez sur Retour.

  3. Implémentez DeviceInstallationService à l’aide du code suivant.

    package com.<your_organization>.pushdemo.services
    
    import android.annotation.SuppressLint
    import android.content.Context
    import android.provider.Settings.Secure
    import com.google.android.gms.common.ConnectionResult
    import com.google.android.gms.common.GoogleApiAvailability
    import io.flutter.embedding.engine.FlutterEngine
    import io.flutter.plugin.common.MethodCall
    import io.flutter.plugin.common.MethodChannel
    
    @SuppressLint("HardwareIds")
    class DeviceInstallationService {
    
        companion object {
            const val DEVICE_INSTALLATION_CHANNEL = "com.<your_organization>.pushdemo/deviceinstallation"
            const val GET_DEVICE_ID = "getDeviceId"
            const val GET_DEVICE_TOKEN = "getDeviceToken"
            const val GET_DEVICE_PLATFORM = "getDevicePlatform"
        }
    
        private var context: Context
        private var deviceInstallationChannel : MethodChannel
    
        val playServicesAvailable
            get() = GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(context) == ConnectionResult.SUCCESS
    
        constructor(context: Context, flutterEngine: FlutterEngine) {
            this.context = context
            deviceInstallationChannel = MethodChannel(flutterEngine.dartExecutor.binaryMessenger, DEVICE_INSTALLATION_CHANNEL)
            deviceInstallationChannel.setMethodCallHandler { call, result -> handleDeviceInstallationCall(call, result) }
        }
    
        fun getDeviceId() : String
            = Secure.getString(context.applicationContext.contentResolver, Secure.ANDROID_ID)
    
        fun getDeviceToken() : String {
            if(!playServicesAvailable) {
                throw Exception(getPlayServicesError())
            }
    
            // TODO: Revisit once we have created the PushNotificationsFirebaseMessagingService
            val token = "Placeholder_Get_Value_From_FirebaseMessagingService_Implementation"
    
            if (token.isNullOrBlank()) {
                throw Exception("Unable to resolve token for FCM.")
            }
    
            return token
        }
    
        fun getDevicePlatform() : String = "fcm"
    
        private fun handleDeviceInstallationCall(call: MethodCall, result: MethodChannel.Result) {
            when (call.method) {
                GET_DEVICE_ID -> {
                    result.success(getDeviceId())
                }
                GET_DEVICE_TOKEN -> {
                    getDeviceToken(result)
                }
                GET_DEVICE_PLATFORM -> {
                    result.success(getDevicePlatform())
                }
                else -> {
                    result.notImplemented()
                }
            }
        }
    
        private fun getDeviceToken(result: MethodChannel.Result) {
            try {
                val token = getDeviceToken()
                result.success(token)
            }
            catch (e: Exception) {
                result.error("ERROR", e.message, e)
            }
        }
    
        private fun getPlayServicesError(): String {
            val resultCode = GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(context)
    
            if (resultCode != ConnectionResult.SUCCESS) {
                return if (GoogleApiAvailability.getInstance().isUserResolvableError(resultCode)){
                    GoogleApiAvailability.getInstance().getErrorString(resultCode)
                } else {
                    "This device is not supported"
                }
            }
    
            return "An error occurred preventing the use of push notifications"
        }
    }
    

    Notes

    Cette classe implémente l’équivalent spécifique à la plateforme pour le com.<your_organization>.pushdemo/deviceinstallation canal. Cela a été défini dans la partie Flutter de l’application dans DeviceInstallationService.dart. Dans ce cas, les appels sont effectués à partir du code commun vers l’hôte natif. Veillez à remplacer <your_organization> par votre propre organization partout où il est utilisé.

    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 fichier/classe Kotlin au dossier des services appelé NotificationRegistrationService, puis ajoutez le code suivant.

    package com.<your_organization>.pushdemo.services
    
    import io.flutter.embedding.engine.FlutterEngine
    import io.flutter.plugin.common.MethodChannel
    
    class NotificationRegistrationService {
    
        companion object {
            const val NOTIFICATION_REGISTRATION_CHANNEL = "com.<your_organization>.pushdemo/notificationregistration"
            const val REFRESH_REGISTRATION = "refreshRegistration"
        }
    
        private var notificationRegistrationChannel : MethodChannel
    
        constructor(flutterEngine: FlutterEngine) {
            notificationRegistrationChannel = MethodChannel(flutterEngine.dartExecutor.binaryMessenger, NotificationRegistrationService.NOTIFICATION_REGISTRATION_CHANNEL)
        }
    
        fun refreshRegistration() {
            notificationRegistrationChannel.invokeMethod(REFRESH_REGISTRATION, null)
        }
    }
    

    Notes

    Cette classe implémente l’équivalent spécifique à la plateforme pour le com.<your_organization>.pushdemo/notificationregistration canal. Cela a été défini dans la partie Flutter de l’application dans NotificationRegistrationService.dart. Dans ce cas, les appels sont effectués à partir de l’hôte natif vers le code commun. Là encore, veillez à remplacer <your_organization> par vos propres organization partout où cela est utilisé.

  5. Ajoutez un autre fichier/classe Kotlin au dossier des services appelé NotificationActionService, puis ajoutez le code suivant.

    package com.<your_organization>.pushdemo.services
    
    import io.flutter.embedding.engine.FlutterEngine
    import io.flutter.plugin.common.MethodCall
    import io.flutter.plugin.common.MethodChannel
    
    class NotificationActionService {
        companion object {
            const val NOTIFICATION_ACTION_CHANNEL = "com.<your_organization>.pushdemo/notificationaction"
            const val TRIGGER_ACTION = "triggerAction"
            const val GET_LAUNCH_ACTION = "getLaunchAction"
        }
    
        private var notificationActionChannel : MethodChannel
        var launchAction : String? = null
    
        constructor(flutterEngine: FlutterEngine) {
            notificationActionChannel = MethodChannel(flutterEngine.dartExecutor.binaryMessenger, NotificationActionService.NOTIFICATION_ACTION_CHANNEL)
            notificationActionChannel.setMethodCallHandler { call, result -> handleNotificationActionCall(call, result) }
        }
    
        fun triggerAction(action: String) {
            notificationActionChannel.invokeMethod(NotificationActionService.TRIGGER_ACTION, action)
        }
    
        private fun handleNotificationActionCall(call: MethodCall, result: MethodChannel.Result) {
            when (call.method) {
                NotificationActionService.GET_LAUNCH_ACTION -> {
                    result.success(launchAction)
                }
                else -> {
                    result.notImplemented()
                }
            }
        }
    }
    

    Notes

    Cette classe implémente l’équivalent spécifique à la plateforme pour le com.<your_organization>.pushdemo/notificationaction canal. Cela a été défini dans la partie Flutter de l’application dans NotificationActionService.dart. Dans ce cas, les appels peuvent être effectués dans les deux sens. Veillez à remplacer <your_organization> par votre propre organization partout où il est utilisé.

  6. Ajoutez un nouveau fichier/classe Kotlin au package com.your_organization.pushdemo<> appelé PushNotificationsFirebaseMessagingService, puis implémentez le code suivant.

    package com.<your_organization>.pushdemo
    
    import android.os.Handler
    import android.os.Looper
    import com.google.firebase.messaging.FirebaseMessagingService
    import com.google.firebase.messaging.RemoteMessage
    import com.<your_organization>.pushdemo.services.NotificationActionService
    import com.<your_organization>.pushdemo.services.NotificationRegistrationService
    
    class PushNotificationsFirebaseMessagingService : FirebaseMessagingService() {
    
        companion object {
            var token : String? = null
            var notificationRegistrationService : NotificationRegistrationService? = null
            var notificationActionService : NotificationActionService? = null
        }
    
        override fun onNewToken(token: String) {
            PushNotificationsFirebaseMessagingService.token = token
            notificationRegistrationService?.refreshRegistration()
        }
    
        override fun onMessageReceived(message: RemoteMessage) {
            message.data.let {
                Handler(Looper.getMainLooper()).post {
                    notificationActionService?.triggerAction(it.getOrDefault("action", null))
                }
            }
        }
    }
    

    Notes

    Cette classe est responsable de la gestion des notifications lorsque l’application s’exécute au premier plan. Il appelle de manière conditionnelle l’action triggerAction sur NotificationActionService si une action est incluse dans la charge utile de notification reçue dans onMessageReceived. Cela appelle également refreshRegistration sur notificationRegistrationService lorsque le jeton Firebase est régénéré en remplaçant la fonction onNewToken .

    Une fois de plus, veillez à remplacer <your_organization> par vos propres organization où qu’ils soient utilisés.

  7. Dans AndroidManifest.xml (app>src>main), ajoutez pushNotificationsFirebaseMessagingService au bas de l’élément application avec le com.google.firebase.MESSAGING_EVENT filtre intention.

    <manifest>
        <application>
            <!-- EXISTING MANIFEST CONTENT -->
             <service
                android:name="com.<your_organization>.pushdemo.PushNotificationsFirebaseMessagingService"
                android:exported="false">
                <intent-filter>
                    <action android:name="com.google.firebase.MESSAGING_EVENT" />
                </intent-filter>
            </service>
        </application>
    </manifest>
    
  8. De retour dans DeviceInstallationService, vérifiez que les importations suivantes sont présentes en haut du fichier.

    package com.<your_organization>.pushdemo
    import com.<your_organization>.pushdemo.services.PushNotificationsFirebaseMessagingService
    

    Notes

    Remplacez <your_organization> par votre propre valeur organization.

  9. Mettez à jour le texte de l’espace réservé Placeholder_Get_Value_From_FirebaseMessagingService_Implementation pour obtenir la valeur du jeton à partir du PushNotificationFirebaseMessagingService.

    fun getDeviceToken() : String {
        if(!playServicesAvailable) {
            throw Exception(getPlayServicesError())
        }
    
        // Get token from the PushNotificationsFirebaseMessagingService.token field.
        val token = PushNotificationsFirebaseMessagingService.token
    
        if (token.isNullOrBlank()) {
            throw Exception("Unable to resolve token for FCM.")
        }
    
        return token
    }
    
  10. Dans MainActivity, vérifiez que les importations suivantes sont présentes en haut du fichier.

    package com.<your_organization>.pushdemo
    
    import android.content.Intent
    import android.os.Bundle
    import com.google.android.gms.tasks.OnCompleteListener
    import com.google.firebase.iid.FirebaseInstanceId
    import com.<your_organization>.pushdemo.services.DeviceInstallationService
    import com.<your_organization>.pushdemo.services.NotificationActionService
    import com.<your_organization>.pushdemo.services.NotificationRegistrationService
    import io.flutter.embedding.android.FlutterActivity
    

    Notes

    Remplacez <your_organization> par votre propre valeur organization.

  11. Ajoutez une variable pour stocker une référence à DeviceInstallationService.

    private lateinit var deviceInstallationService: DeviceInstallationService
    
  12. Ajoutez une fonction appelée processNotificationActions pour case activée si une intention a une valeur supplémentaire nommée action. Déclenchez cette action de manière conditionnelle ou stockez-la pour une utilisation ultérieure si l’action est en cours de traitement lors du lancement de l’application.

     private fun processNotificationActions(intent: Intent, launchAction: Boolean = false) {
        if (intent.hasExtra("action")) {
            var action = intent.getStringExtra("action");
    
            if (action.isNotEmpty()) {
                if (launchAction) {
                    PushNotificationsFirebaseMessagingService.notificationActionService?.launchAction = action
                }
                else {
                    PushNotificationsFirebaseMessagingService.notificationActionService?.triggerAction(action)
                }
            }
        }
    }
    
  13. Remplacez la fonction onNewIntent pour appeler processNotificationActions.

    override fun onNewIntent(intent: Intent) {
        super.onNewIntent(intent)
        processNotificationActions(intent)
    }
    

    Notes

    Étant donné que LaunchMode pour MainActivity est défini sur SingleTop, une intention est envoyée à l’instance d’activité existante via la fonction onNewIntent plutôt que la fonction onCreate. Vous devez donc gérer une intention entrante dans les fonctions onCreate et onNewIntent.

  14. Remplacez la fonction onCreate, définissez deviceInstallationService sur une nouvelle instance de DeviceInstallationService.

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
    
        flutterEngine?.let {
            deviceInstallationService = DeviceInstallationService(context, it)
        }
    }
    
  15. Définissez les propriétés notificationActionService et notificationRegistrationService sur PushNotificationFirebaseMessagingServices.

    flutterEngine?.let {
      deviceInstallationService = DeviceInstallationService(context, it)
      PushNotificationsFirebaseMessagingService.notificationActionService = NotificationActionService(it)
      PushNotificationsFirebaseMessagingService.notificationRegistrationService = NotificationRegistrationService(it)
    }
    
  16. Dans la même fonction, appelez de manière conditionnelle FirebaseInstanceId.getInstance().instanceId. Implémentez OnCompleteListener pour définir la valeur du jeton résultant sur PushNotificationFirebaseMessagingService avant d’appeler refreshRegistration.

    if(deviceInstallationService?.playServicesAvailable) {
        FirebaseInstanceId.getInstance().instanceId
            .addOnCompleteListener(OnCompleteListener { task ->
                if (!task.isSuccessful)
                    return@OnCompleteListener
    
                PushNotificationsFirebaseMessagingService.token = task.result?.token
                PushNotificationsFirebaseMessagingService.notificationRegistrationService?.refreshRegistration()
            })
    }
    
  17. Toujours dans onCreate, appelez processNotificationActions à la fin de la fonction. Utilisez true pour l’argument launchAction afin d’indiquer que cette action est en cours de traitement pendant le lancement de l’application.

    processNotificationActions(this.intent, true)
    

Notes

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

Configurer le projet iOS natif pour les notifications Push

Configurer la cible de l’exécuteur et Info.plist

  1. Dans Visual Studio Code, Contrôle + Cliquez sur le dossier ios , puis choisissez Ouvrir dans Xcode.

  2. Dans Xcode, cliquez sur Runner ( le xcodeproj en haut, pas le dossier), puis sélectionnez la cible de l’exécuteur , puis signature & fonctionnalités. Une fois la configuration de build tout sélectionnée, choisissez votre compte développeur pour l’équipe. Vérifiez que l’option « Gérer automatiquement la signature » est activée et que votre certificat de signature et votre profil d’approvisionnement sont automatiquement sélectionnés.

    Notes

    Si vous ne voyez pas la nouvelle valeur du profil d’approvisionnement, essayez d’actualiser les profils de l’identité de signature en sélectionnantComptede préférences>Xcode>, puis sélectionnez le bouton Télécharger les profils manuels pour télécharger les profils.

  3. Cliquez sur + Capacité, puis recherchez Notifications Push. Double-cliquez sur Notifications Push pour ajouter cette fonctionnalité.

  4. Ouvrez Info.plist et définissez Version système minimale sur 13.0.

    Notes

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

  5. Ouvrez Runner.entitlements et vérifiez que le paramètre d’environnement APS est défini sur le développement.

Gérer les notifications Push pour iOS

  1. Contrôle + Cliquez sur le dossier Runner (dans le projet Runner), puis choisissez Nouveau groupe en utilisant Services comme nom.

  2. Contrôle + Cliquez sur le dossier Services , puis choisissez Nouveau fichier.... Ensuite, choisissez Fichier Swift , puis cliquez sur Suivant. Spécifiez DeviceInstallationService comme nom, puis cliquez sur Créer.

  3. Implémentez DeviceInstallationService.swift à l’aide du code suivant.

    import Foundation
    
    class DeviceInstallationService {
    
        enum DeviceRegistrationError: Error {
            case notificationSupport(message: String)
        }
    
        var token : Data? = nil
    
        let DEVICE_INSTALLATION_CHANNEL = "com.<your_organization>.pushdemo/deviceinstallation"
        let GET_DEVICE_ID = "getDeviceId"
        let GET_DEVICE_TOKEN = "getDeviceToken"
        let GET_DEVICE_PLATFORM = "getDevicePlatform"
    
        private let deviceInstallationChannel : FlutterMethodChannel
    
        var notificationsSupported : Bool {
            get {
                if #available(iOS 13.0, *) {
                    return true
                }
                else {
                    return false
                }
            }
        }
    
        init(withBinaryMessenger binaryMessenger : FlutterBinaryMessenger) {
            deviceInstallationChannel = FlutterMethodChannel(name: DEVICE_INSTALLATION_CHANNEL, binaryMessenger: binaryMessenger)
            deviceInstallationChannel.setMethodCallHandler(handleDeviceInstallationCall)
        }
    
        func getDeviceId() -> String {
            return UIDevice.current.identifierForVendor!.description
        }
    
        func getDeviceToken() throws -> String {
            if(!notificationsSupported) {
                let notificationSupportError = getNotificationsSupportError()
                throw DeviceRegistrationError.notificationSupport(message: notificationSupportError)
            }
    
            if (token == nil) {
                throw DeviceRegistrationError.notificationSupport(message: "Unable to resolve token for APNS.")
            }
    
            return token!.reduce("", {$0 + String(format: "%02X", $1)})
        }
    
        func getDevicePlatform() -> String {
            return "apns"
        }
    
        private func handleDeviceInstallationCall(call: FlutterMethodCall, result: @escaping FlutterResult) {
            switch call.method {
            case GET_DEVICE_ID:
                result(getDeviceId())
            case GET_DEVICE_TOKEN:
                getDeviceToken(result: result)
            case GET_DEVICE_PLATFORM:
                result(getDevicePlatform())
            default:
                result(FlutterMethodNotImplemented)
            }
        }
    
        private func getDeviceToken(result: @escaping FlutterResult) {
            do {
                let token = try getDeviceToken()
                result(token)
            }
            catch let error {
                result(FlutterError(code: "UNAVAILABLE", message: error.localizedDescription, details: nil))
            }
        }
    
        private func getNotificationsSupportError() -> String {
    
            if (!notificationsSupported) {
                return "This app only supports notifications on iOS 13.0 and above. You are running \(UIDevice.current.systemVersion)"
            }
    
            return "An error occurred preventing the use of push notifications."
        }
    }
    

    Notes

    Cette classe implémente l’équivalent spécifique à la plateforme pour le com.<your_organization>.pushdemo/deviceinstallation canal. Cela a été défini dans la partie Flutter de l’application dans DeviceInstallationService.dart. Dans ce cas, les appels sont effectués à partir du code commun vers l’hôte natif. Veillez à remplacer <your_organization> par votre propre organization partout où il est utilisé.

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

  4. Ajoutez un autre fichier Swift au dossier Services appelé NotificationRegistrationService, puis ajoutez le code suivant.

    import Foundation
    
    class NotificationRegistrationService {
    
        let NOTIFICATION_REGISTRATION_CHANNEL = "com.<your_organization>.pushdemo/notificationregistration"
        let REFRESH_REGISTRATION = "refreshRegistration"
    
        private let notificationRegistrationChannel : FlutterMethodChannel
    
        init(withBinaryMessenger binaryMessenger : FlutterBinaryMessenger) {
           notificationRegistrationChannel = FlutterMethodChannel(name: NOTIFICATION_REGISTRATION_CHANNEL, binaryMessenger: binaryMessenger)
        }
    
        func refreshRegistration() {
            notificationRegistrationChannel.invokeMethod(REFRESH_REGISTRATION, arguments: nil)
        }
    }
    

    Notes

    Cette classe implémente l’équivalent spécifique à la plateforme pour le com.<your_organization>.pushdemo/notificationregistration canal. Cela a été défini dans la partie Flutter de l’application dans NotificationRegistrationService.dart. Dans ce cas, les appels sont effectués à partir de l’hôte natif vers le code commun. Là encore, veillez à remplacer <your_organization> par vos propres organization partout où cela est utilisé.

  5. Ajoutez un autre fichier Swift au dossier Services appelé NotificationActionService, puis ajoutez le code suivant.

    import Foundation
    
    class NotificationActionService {
    
        let NOTIFICATION_ACTION_CHANNEL = "com.<your_organization>.pushdemo/notificationaction"
        let TRIGGER_ACTION = "triggerAction"
        let GET_LAUNCH_ACTION = "getLaunchAction"
    
        private let notificationActionChannel: FlutterMethodChannel
    
        var launchAction: String? = nil
    
        init(withBinaryMessenger binaryMessenger: FlutterBinaryMessenger) {
            notificationActionChannel = FlutterMethodChannel(name: NOTIFICATION_ACTION_CHANNEL, binaryMessenger: binaryMessenger)
            notificationActionChannel.setMethodCallHandler(handleNotificationActionCall)
        }
    
        func triggerAction(action: String) {
           notificationActionChannel.invokeMethod(TRIGGER_ACTION, arguments: action)
        }
    
        private func handleNotificationActionCall(call: FlutterMethodCall, result: @escaping FlutterResult) {
            switch call.method {
            case GET_LAUNCH_ACTION:
                result(launchAction)
            default:
                result(FlutterMethodNotImplemented)
            }
        }
    }
    

    Notes

    Cette classe implémente l’équivalent spécifique à la plateforme pour le com.<your_organization>.pushdemo/notificationaction canal. Cela a été défini dans la partie Flutter de l’application dans NotificationActionService.dart. Dans ce cas, les appels peuvent être effectués dans les deux sens. Veillez à remplacer <your_organization> par votre propre organization partout où il est utilisé.

  6. Dans AppDelegate.swift, ajoutez des variables pour stocker une référence aux services que vous avez créés précédemment.

    var deviceInstallationService : DeviceInstallationService?
    var notificationRegistrationService : NotificationRegistrationService?
    var notificationActionService : NotificationActionService?
    
  7. Ajoutez une fonction appelée processNotificationActions pour le traitement des données de notification. Déclenchez cette action de manière conditionnelle ou stockez-la pour une utilisation ultérieure si l’action est en cours de traitement lors du lancement de l’application.

    func processNotificationActions(userInfo: [AnyHashable : Any], launchAction: Bool = false) {
        if let action = userInfo["action"] as? String {
            if (launchAction) {
                notificationActionService?.launchAction = action
            }
            else {
                notificationActionService?.triggerAction(action: action)
            }
        }
    }
    
  8. Remplacez la fonction didRegisterForRemoteNotificationsWithDeviceToken en définissant la valeur du jeton pour deviceInstallationService. Ensuite, appelez refreshRegistration sur notificationRegistrationService.

    override func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
      deviceInstallationService?.token = deviceToken
      notificationRegistrationService?.refreshRegistration()
    }
    
  9. Remplacez la fonction didReceiveRemoteNotification en passant l’argument userInfo à la fonction processNotificationActions .

    override func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any]) {
        processNotificationActions(userInfo: userInfo)
    }
    
  10. Remplacez la fonction didFailToRegisterForRemoteNotificationsWithError pour consigner l’erreur.

    override func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
        print(error);
    }
    

    Notes

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

  11. Dans didFinishLaunchingWithOptions, instanciez les variables deviceInstallationService, notificationRegistrationService et notificationActionService .

    let controller : FlutterViewController = window?.rootViewController as! FlutterViewController
    
    deviceInstallationService = DeviceInstallationService(withBinaryMessenger: controller.binaryMessenger)
    notificationRegistrationService = NotificationRegistrationService(withBinaryMessenger: controller.binaryMessenger)
    notificationActionService = NotificationActionService(withBinaryMessenger: controller.binaryMessenger)
    
  12. Dans la même fonction, demandez une autorisation conditionnelle et inscrivez-vous pour les notifications à distance.

    if #available(iOS 13.0, *) {
      UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound, .badge]) {
          (granted, error) in
    
          if (granted)
          {
              DispatchQueue.main.async {
                  let pushSettings = UIUserNotificationSettings(types: [.alert, .sound, .badge], categories: nil)
                  application.registerUserNotificationSettings(pushSettings)
                  application.registerForRemoteNotifications()
              }
          }
      }
    }
    
  13. Si launchOptions contient la clé remoteNotification , appelez processNotificationActions à la fin de la fonction didFinishLaunchingWithOptions . Passez l’objet userInfo résultant et utilisez true pour l’argument launchAction . Une valeur true indique que l’action est en cours de traitement pendant le lancement de l’application.

    if let userInfo = launchOptions?[.remoteNotification] as? [AnyHashable : Any] {
        processNotificationActions(userInfo: userInfo, launchAction: true)
    }
    

Tester la solution

Vous pouvez maintenant tester l’envoi de notifications via le service back-end.

Envoyer une notification de test

  1. Ouvrez un nouvel onglet dans Postman.

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

    https://<app_name>.azurewebsites.net/api/notifications/requests
    
  3. Si vous avez choisi d’effectuer la section Authentifier les clients à l’aide d’une clé API , 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 du Corps, puis choisissez JSON dans la liste des options de format, puis incluez du contenu JSON d’espace réservé :

    {
        "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 demande doit ressembler à l’exemple suivant lorsqu’elle est affichée pour le code HTML (selon que vous avez inclus ou non un en-tête apikey ) :

    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 l’une ou les deux plateformes cibles (Android et iOS).

    Notes

    Si vous testez sur Android , assurez-vous que vous n’exécutez pas 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 ActionA action 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’alerte ActionA reçue .

  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 la valeur d’action .

    {
        "action": "action_b",
        "silent": true
    }
    
  14. L’application étant 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 s’affiche dans l’application montrant l’action ActionB reçue au lieu de l’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

Lorsque vous testez localement, vérifiez que le service principal est en cours d’exécution et utilise le port approprié.

Si vous effectuez un test sur l’application API Azure, case activée le service est en cours d’exécution et a été déployé et a démarré sans erreur.

Veillez à case activée vous avez correctement spécifié 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/https://localhost:5001/ ou à titre indicatif lors d’un test local.

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

Veillez à vous inscrire à nouveau 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 401 status du service back-end

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 back-end.

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 du paramètre utilisateur Authentication :ApiKey utilisée par l’API.

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

Notes

Si vous avez créé ou modifié ce paramètre après avoir déployé le service back-end, 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 Authorize à la classe NotificationsController .

Réception d’un code 404 status 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]https://<api_name>.azurewebsites.net/api/notifications/installations
  • [DELETE]https://<api_name>.azurewebsites.net/api/notifications/installations/<installation_id>
  • [POST]https://<api_name>.azurewebsites.net/api/notifications/requests

Ou lors d’un test local :

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

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

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

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

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

Définissez un point d’arrêt sur les lignes qui retournent ces codes status spécifiques pour l’API correspondante. Essayez ensuite d’appeler le service back-end lors du débogage local.

Vérifiez que le service back-end 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 étape n’a été manquée. Vérifiez que les valeurs appropriées sont résolues pour installation id les variables et token 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 étape n’a été manquée.

Étapes suivantes

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

Vous devrez probablement adapter l’exemple utilisé dans ce didacticiel pour l’adapter à votre propre scénario. L’implémentation d’une gestion des erreurs, d’une logique de nouvelle tentative et d’une journalisation plus robustes est également recommandée.

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