Tutoriel : Envoyer des notifications Push vers des applications Android spécifiques à l’aide d’Azure Notification Hubs
Remarque
Pour plus d’informations sur les étapes de dépréciation et de migration de Firebase Cloud Messaging, consultez Migration de Google Firebase Cloud Messaging.
Ce didacticiel explique comment utiliser Azure Notification Hubs pour envoyer des notifications Push à un utilisateur particulier d'une application sur un appareil spécifique. Un code WebAPI principal ASP.NET est utilisé pour authentifier les clients et pour générer les notifications, comme le présente l’article Inscription auprès du serveur principal de votre application. Ce tutoriel s’appuie sur le hub de notification que vous avez créé dans le Tutoriel : Notifications Push vers des appareils Android à l’aide d’Azure Notification Hubs et de Firebase Cloud Messaging.
Dans ce tutoriel, vous effectuez les étapes suivantes :
- Créer le projet d’API Web principale qui authentifie les utilisateurs.
- Mettre à jour une application Android.
- Test de l'application
Prérequis
Suivre le Tutoriel : Notifications Push vers des appareils Android avec Azure Notification Hubs et Firebase Cloud Messaging avant de passer à ce tutoriel.
Création du projet WebAPI
Les sections suivantes traitent de la création d’un serveur principal WebAPI ASP.NET. Ce processus a trois objectifs principaux :
- Authentification des clients : ajoutez un gestionnaire de messages pour authentifier les demandes des clients et associer l’utilisateur à la demande.
- Inscriptions aux notifications à l’aide du serveur principal WebAPI : ajoutez un contrôleur pour gérer les nouvelles inscriptions afin qu’un appareil client puisse recevoir des notifications. Le nom d’utilisateur authentifié est automatiquement ajouté à l’inscription en tant que balise.
- Envoi de notifications aux clients : ajoutez un contrôleur permettant aux utilisateurs de déclencher une notification push sécurisée pour les appareils et les clients associés à la balise.
Pour créer le serveur principal ASP.NET Core 6.0, procédez comme suit :
Pour ce faire, lancez Visual Studio. Dans le menu Outils, sélectionnez Extensions et mises à jour. Recherchez Gestionnaire de package NuGet pour votre version de Visual Studio et vérifiez que vous disposez de la dernière version. Si vous ne disposez pas de la version la plus récente, désinstallez votre version actuelle et réinstallez le Gestionnaire de package NuGet.
Remarque
Assurez-vous que le Kit de développement logiciel (SDK) Azure Visual Studio est installé, pour le déploiement du site web.
Démarrez Visual Studio ou Visual Studio Express.
Sélectionnez Explorateur de serveurs et connectez-vous à votre compte Azure. Pour créer les ressources du site web sur votre compte, vous devez être connecté.
Dans Visual Studio, dans le menu Fichier, sélectionnez Nouveau>Projet.
Entrez API web dans le champ de recherche.
Sélectionnez le modèle de projet API web ASP.NET Core, puis Suivant.
Dans la boîte de dialogue Configurer votre nouveau projet, nommez le projet AppBackend, puis sélectionnez Suivant.
Dans la boîte de dialogue Informations supplémentaires :
- Vérifiez que le framework est .NET 6.0 (prise en charge à long terme).
- Vérifiez que la case à cocher Utiliser des contrôleurs (décocher pour utiliser les API minimales) est cochée.
- Décochez Activer la prise en charge d’OpenAPI.
- Sélectionnez Create (Créer).
Supprimer les fichiers de modèle WeatherForecast
- Supprimez les fichiers d’exemple WeatherForecast.cs et Controllers/WeatherForecastController.cs du nouveau projet AppBackend.
- Ouvrez Properties\launchSettings.json.
- Modifiez les propriétés launchUrl de weatherforcast en appbackend.
Dans la fenêtre Configurer l’application web Microsoft Azure, sélectionnez l’abonnement puis effectuez l’une des actions suivantes dans la liste Plan App Service :
- Sélectionnez un plan Azure App Service que vous avez déjà créé.
- Sélectionnez Créer un plan App Service, et créez-en un.
Vous n'avez pas besoin de base de données pour ce didacticiel. Une fois que vous avez sélectionné votre plan App Service, sélectionnez OK pour créer le projet.
Si vous ne voyez pas la page Configurer le plan App Service, poursuivez le tutoriel. Vous pourrez le configurer plus tard, lors de la publication de l’application.
Authentification des clients sur le serveur principal WebAPI
Dans cette section, vous créez une classe de gestionnaire de messages nommée AuthenticationTestHandler pour le nouveau serveur principal. Cette classe est dérivée de DelegatingHandler et ajoutée comme gestionnaire de messages afin de pouvoir traiter toutes les demandes entrantes dans le serveur principal.
Dans l’Explorateur de solutions, cliquez avec le bouton droit sur le projet AppBackend, puis sélectionnez Ajouter et Classe.
Nommez la nouvelle classe AuthenticationTestHandler.cs, puis sélectionnez Ajouter pour générer la classe. Par souci de simplification, cette classe permet d’authentifier les utilisateurs via l’ Authentification de base . Votre application peut utiliser n’importe quel schéma d’authentification.
Dans AuthenticationTestHandler.cs, ajoutez les instructions
using
suivantes :using System.Net.Http; using System.Threading; using System.Security.Principal; using System.Net; using System.Text; using System.Threading.Tasks;
Dans AuthenticationTestHandler.cs, remplacez la définition de classe
AuthenticationTestHandler
par le code suivant :Ce gestionnaire autorise la demande lorsque les trois conditions suivantes sont vraies :
- La demande comprenait un en-tête d’autorisation.
- La demande utilise l’authentification de base .
- Les chaînes du nom d’utilisateur et du mot de passe sont identiques.
Sinon, la demande est rejetée. Cette authentification ne répond pas à une véritable approche d’authentification et d’autorisation. Il s’agit uniquement d’un exemple très simple pour ce didacticiel.
Si le message de la demande est authentifié et autorisé par
AuthenticationTestHandler
, l’utilisateur de l’authentification de base est attaché à la demande actuelle sur HttpContext. Les informations utilisateur dans HttpContext sont utilisées ultérieurement par un autre contrôleur (RegisterController) pour ajouter une balise à la demande d’inscription aux notifications.public class AuthenticationTestHandler : DelegatingHandler { protected override Task<HttpResponseMessage> SendAsync( HttpRequestMessage request, CancellationToken cancellationToken) { var authorizationHeader = request.Headers.GetValues("Authorization").First(); if (authorizationHeader != null && authorizationHeader .StartsWith("Basic ", StringComparison.InvariantCultureIgnoreCase)) { string authorizationUserAndPwdBase64 = authorizationHeader.Substring("Basic ".Length); string authorizationUserAndPwd = Encoding.Default .GetString(Convert.FromBase64String(authorizationUserAndPwdBase64)); string user = authorizationUserAndPwd.Split(':')[0]; string password = authorizationUserAndPwd.Split(':')[1]; if (VerifyUserAndPwd(user, password)) { // Attach the new principal object to the current HttpContext object HttpContext.Current.User = new GenericPrincipal(new GenericIdentity(user), new string[0]); System.Threading.Thread.CurrentPrincipal = System.Web.HttpContext.Current.User; } else return Unauthorized(); } else return Unauthorized(); return base.SendAsync(request, cancellationToken); } private bool VerifyUserAndPwd(string user, string password) { // This is not a real authentication scheme. return user == password; } private Task<HttpResponseMessage> Unauthorized() { var response = new HttpResponseMessage(HttpStatusCode.Forbidden); var tsc = new TaskCompletionSource<HttpResponseMessage>(); tsc.SetResult(response); return tsc.Task; } }
Notes
Note de sécurité : la classe
AuthenticationTestHandler
n’offre pas de véritable authentification. Elle sert uniquement à simuler l’authentification de base et n’est pas sécurisée. Vous devez mettre en œuvre un mécanisme d’authentification sécurisé dans vos applications de production et vos services.Pour enregistrer le gestionnaire de messages, ajoutez le code suivant à la fin de la méthode
Register
dans le fichier Program.cs :config.MessageHandlers.Add(new AuthenticationTestHandler());
Enregistrez vos modifications.
Inscription aux notifications à l’aide du serveur principal WebAPI
Dans cette section, vous ajoutez un nouveau contrôleur au serveur principal WebAPI pour gérer les demandes d’inscription d’un utilisateur et d’un appareil aux notifications à l’aide de la bibliothèque cliente pour les hubs de notification. Le contrôleur ajoute une balise d’utilisateur pour l’utilisateur qui a été authentifié et attaché à HttpContext par AuthenticationTestHandler
. La balise a le format de chaîne "username:<actual username>"
.
Dans l’Explorateur de solutions, cliquez avec le bouton droit sur le projet AppBackend, puis sélectionnez Gérer les packages NuGet.
Dans le volet gauche, sélectionnez En ligne puis tapez Microsoft.Azure.NotificationHubs dans la zone Recherche.
Dans la liste de résultats, sélectionnez Microsoft Azure Notification Hubs, puis Installer. Procédez à l’installation, puis fermez la fenêtre du Gestionnaire de package NuGet.
Cette action ajoute une référence au Kit de développement logiciel (SDK) Azure Notification Hubs à l’aide du package NuGet Microsoft.Azure.Notification Hubs.
Créez un nouveau fichier de classe qui représente la connexion avec le hub de notification utilisé pour envoyer des notifications. Dans l’Explorateur de solutions, cliquez avec le bouton droit sur le dossier Modèles, sélectionnez Ajouter, puis Classe. Nommez la nouvelle classe Notifications.cs, puis sélectionnez Ajouter pour générer la classe.
Dans Notifications.cs, ajoutez l’instruction
using
suivante en haut du fichier :using Microsoft.Azure.NotificationHubs;
Remplacez la définition de classe
Notifications
par le code suivant et les deux espaces réservés par la chaîne de connexion (avec accès complet) de votre centre Notification Hubs et le nom du hub (disponible sur le Portail Azure) :public class Notifications { public static Notifications Instance = new Notifications(); public NotificationHubClient Hub { get; set; } private Notifications() { Hub = NotificationHubClient.CreateClientFromConnectionString("<your hub's DefaultFullSharedAccessSignature>", "<hub name>"); } }
Important
Entrez le nom et la DefaultFullSharedAccessSignature de votre hub avant de continuer.
Ensuite, créez un contrôleur nommé RegisterController. Dans l’Explorateur de solutions, cliquez avec le bouton droit sur le dossier Contrôleurs, sélectionnez Ajouter, puis Contrôleur.
Sélectionnez Contrôleur API - Vide, puis Ajouter.
Dans la boîte Nom du contrôleur, tapez RegisterController pour nommer la nouvelle classe, puis sélectionnez Ajouter.
Dans RegisterController.cs, ajoutez les instructions
using
suivantes :using Microsoft.Azure.NotificationHubs; using Microsoft.Azure.NotificationHubs.Messaging; using AppBackend.Models; using System.Threading.Tasks; using System.Web;
Ajoutez le code suivant dans la définition de classe
RegisterController
. Dans ce code, vous ajoutez une balise d’utilisateur pour l’utilisateur attaché à HttpContext. L’utilisateur a été authentifié et attaché à HttpContext par le filtre de messages que vous avez ajouté,AuthenticationTestHandler
. Vous pouvez également ajouter des contrôles facultatifs afin de vérifier que l’utilisateur dispose des droits d’inscription nécessaires pour les balises requises.private NotificationHubClient hub; public RegisterController() { hub = Notifications.Instance.Hub; } public class DeviceRegistration { public string Platform { get; set; } public string Handle { get; set; } public string[] Tags { get; set; } } // POST api/register // This creates a registration id public async Task<string> Post(string handle = null) { string newRegistrationId = null; // make sure there are no existing registrations for this push handle (used for iOS and Android) if (handle != null) { var registrations = await hub.GetRegistrationsByChannelAsync(handle, 100); foreach (RegistrationDescription registration in registrations) { if (newRegistrationId == null) { newRegistrationId = registration.RegistrationId; } else { await hub.DeleteRegistrationAsync(registration); } } } if (newRegistrationId == null) newRegistrationId = await hub.CreateRegistrationIdAsync(); return newRegistrationId; } // PUT api/register/5 // This creates or updates a registration (with provided channelURI) at the specified id public async Task<HttpResponseMessage> Put(string id, DeviceRegistration deviceUpdate) { RegistrationDescription registration = null; switch (deviceUpdate.Platform) { case "mpns": registration = new MpnsRegistrationDescription(deviceUpdate.Handle); break; case "wns": registration = new WindowsRegistrationDescription(deviceUpdate.Handle); break; case "apns": registration = new AppleRegistrationDescription(deviceUpdate.Handle); break; case "fcm": registration = new FcmRegistrationDescription(deviceUpdate.Handle); break; default: throw new HttpResponseException(HttpStatusCode.BadRequest); } registration.RegistrationId = id; var username = HttpContext.Current.User.Identity.Name; // add check if user is allowed to add these tags registration.Tags = new HashSet<string>(deviceUpdate.Tags); registration.Tags.Add("username:" + username); try { await hub.CreateOrUpdateRegistrationAsync(registration); } catch (MessagingException e) { ReturnGoneIfHubResponseIsGone(e); } return Request.CreateResponse(HttpStatusCode.OK); } // DELETE api/register/5 public async Task<HttpResponseMessage> Delete(string id) { await hub.DeleteRegistrationAsync(id); return Request.CreateResponse(HttpStatusCode.OK); } private static void ReturnGoneIfHubResponseIsGone(MessagingException e) { var webex = e.InnerException as WebException; if (webex.Status == WebExceptionStatus.ProtocolError) { var response = (HttpWebResponse)webex.Response; if (response.StatusCode == HttpStatusCode.Gone) throw new HttpRequestException(HttpStatusCode.Gone.ToString()); } }
Enregistrez vos modifications.
Envoyer des notifications depuis le serveur principal WebAPI
Dans cette section, vous ajoutez un nouveau contrôleur qui montre aux appareils clients comment envoyer une notification. La notification se base sur la balise du nom d’utilisateur qui utilise la bibliothèque .NET du service d’Azure Notification Hubs dans le serveur principal WebAPI ASP.NET.
Créez un nouveau contrôleur nommé NotificationsController, de la même façon que vous avez créé RegisterController dans la section précédente.
Dans NotificationsController.cs, ajoutez les instructions
using
suivantes :using AppBackend.Models; using System.Threading.Tasks; using System.Web;
Ajoutez la méthode suivante à la classe NotificationsController :
Ce code envoie un type de notification basé sur le paramètre
pns
du service de notification de plateforme. La valeur deto_tag
permet de définir la balise username sur le message. Cette balise doit correspondre à une balise de nom d’utilisateur d’une inscription de hub de notification active. Le message de notification est extrait du corps de la demande POST et mis en forme pour le PNS cible.Selon le service Platform Notification Service (PNS) que vos appareils pris en charge utilisent pour recevoir des notifications, ces dernières sont prises en charge dans plusieurs formats. Par exemple sur des appareils Windows, vous pouvez utiliser une notification toast avec WNS qui n’est pas directement prise en charge par un autre service PNS. Dans une instance de ce type, votre serveur principal doit formater la notification dans un format pris en charge pour le service PNS des appareils que vous envisagez de prendre en charge. Utilisez ensuite l’API d’envoi appropriée sur la classe NotificationHubClient.
public async Task<HttpResponseMessage> Post(string pns, [FromBody]string message, string to_tag) { var user = HttpContext.Current.User.Identity.Name; string[] userTag = new string[2]; userTag[0] = "username:" + to_tag; userTag[1] = "from:" + user; Microsoft.Azure.NotificationHubs.NotificationOutcome outcome = null; HttpStatusCode ret = HttpStatusCode.InternalServerError; switch (pns.ToLower()) { case "wns": // Windows 8.1 / Windows Phone 8.1 var toast = @"<toast><visual><binding template=""ToastText01""><text id=""1"">" + "From " + user + ": " + message + "</text></binding></visual></toast>"; outcome = await Notifications.Instance.Hub.SendWindowsNativeNotificationAsync(toast, userTag); break; case "apns": // iOS var alert = "{\"aps\":{\"alert\":\"" + "From " + user + ": " + message + "\"}}"; outcome = await Notifications.Instance.Hub.SendAppleNativeNotificationAsync(alert, userTag); break; case "fcm": // Android var notif = "{ \"data\" : {\"message\":\"" + "From " + user + ": " + message + "\"}}"; outcome = await Notifications.Instance.Hub.SendFcmNativeNotificationAsync(notif, userTag); break; } if (outcome != null) { if (!((outcome.State == Microsoft.Azure.NotificationHubs.NotificationOutcomeState.Abandoned) || (outcome.State == Microsoft.Azure.NotificationHubs.NotificationOutcomeState.Unknown))) { ret = HttpStatusCode.OK; } } return Request.CreateResponse(ret); }
Appuyez sur la touche F5 pour exécuter l’application et vérifier le travail que vous avez accompli jusqu’à présent. L’application ouvre un navigateur web, qui s’affiche sur la page d’accueil ASP.NET.
Publication du nouveau serveur principal WebAPI
Ensuite, vous déployez l’application sur un site web Azure afin de la rendre accessible à tous les appareils.
Cliquez avec le bouton droit sur le projet AppBackend, puis sélectionnez Publier.
Sélectionnez Microsoft Azure App Service comme cible de publication, puis cliquez sur \*\*Publier. La fenêtre Créer App Service s’ouvre. Vous pouvez créer toutes les ressources Azure nécessaires pour exécuter l’application web ASP.NET dans Azure.
Dans la fenêtre Créer App Service, sélectionnez votre compte Azure. Sélectionnez Modifier le type>Application web. Conservez le nom de l’application web par défaut et sélectionnez l’abonnement, le groupe de ressources et le plan App Service.
Sélectionnez Create (Créer).
Notez la valeur de la propriété URL du site dans la section Résumé. Cette URL constitue le point de terminaison de votre serveur principal plus loin dans ce didacticiel.
Sélectionnez Publier.
Après en avoir terminé avec l’Assistant, il publie l’application web ASP.NET dans Azure, puis ouvre l’application dans le navigateur par défaut. Votre application est visible dans Azure App Services.
L’URL utilise le nom de l’application web que vous avez spécifié précédemment, au format http://<app_name>.azurewebsites.net.
Création du projet Android
L’étape suivante consiste à mettre à jour l’application Android créée dans le Tutoriel : Notifications Push vers des appareils Android à l’aide d’Azure Notification Hubs et de Firebase Cloud Messaging.
Ouvrez votre fichier
res/layout/activity_main.xml
, remplacez les définitions de contenu suivantes :Cette opération ajoute de nouveaux contrôles EditText pour la connexion en tant qu'utilisateur. Un champ est également ajouté pour une balise de nom d'utilisateur qui fera partie des notifications que vous enverrez :
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <EditText android:id="@+id/usernameText" android:layout_width="match_parent" android:layout_height="wrap_content" android:ems="10" android:hint="@string/usernameHint" android:layout_above="@+id/passwordText" android:layout_alignParentEnd="true" /> <EditText android:id="@+id/passwordText" android:layout_width="match_parent" android:layout_height="wrap_content" android:ems="10" android:hint="@string/passwordHint" android:inputType="textPassword" android:layout_above="@+id/buttonLogin" android:layout_alignParentEnd="true" /> <Button android:id="@+id/buttonLogin" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/loginButton" android:onClick="login" android:layout_above="@+id/toggleButtonFCM" android:layout_centerHorizontal="true" android:layout_marginBottom="24dp" /> <ToggleButton android:layout_width="wrap_content" android:layout_height="wrap_content" android:textOn="WNS on" android:textOff="WNS off" android:id="@+id/toggleButtonWNS" android:layout_toLeftOf="@id/toggleButtonFCM" android:layout_centerVertical="true" /> <ToggleButton android:layout_width="wrap_content" android:layout_height="wrap_content" android:textOn="FCM on" android:textOff="FCM off" android:id="@+id/toggleButtonFCM" android:checked="true" android:layout_centerHorizontal="true" android:layout_centerVertical="true" /> <ToggleButton android:layout_width="wrap_content" android:layout_height="wrap_content" android:textOn="APNS on" android:textOff="APNS off" android:id="@+id/toggleButtonAPNS" android:layout_toRightOf="@id/toggleButtonFCM" android:layout_centerVertical="true" /> <EditText android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/editTextNotificationMessageTag" android:layout_below="@id/toggleButtonFCM" android:layout_centerHorizontal="true" android:hint="@string/notification_message_tag_hint" /> <EditText android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/editTextNotificationMessage" android:layout_below="@+id/editTextNotificationMessageTag" android:layout_centerHorizontal="true" android:hint="@string/notification_message_hint" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/send_button" android:id="@+id/sendbutton" android:onClick="sendNotificationButtonOnClick" android:layout_below="@+id/editTextNotificationMessage" android:layout_centerHorizontal="true" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Hello World!" android:id="@+id/text_hello" /> </RelativeLayout>
Ouvrez votre fichier
res/values/strings.xml
et remplacez la définitionsend_button
par les lignes suivantes qui redéfinissent la chaîne dusend_button
et ajoutent des chaînes pour les autres contrôles :<string name="usernameHint">Username</string> <string name="passwordHint">Password</string> <string name="loginButton">1. Sign in</string> <string name="send_button">2. Send Notification</string> <string name="notification_message_hint">Notification message</string> <string name="notification_message_tag_hint">Recipient username</string>
La présentation graphique de votre fichier
main_activity.xml
doit maintenant ressembler à l’image suivante :Créez une classe nommée
RegisterClient
dans le même package que votre classeMainActivity
. Utilisez le code ci-dessous pour le nouveau fichier de classe.import java.io.IOException; import java.io.UnsupportedEncodingException; import java.util.Set; import org.apache.http.HttpResponse; import org.apache.http.HttpStatus; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpPost; import org.apache.http.client.methods.HttpPut; import org.apache.http.client.methods.HttpUriRequest; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.util.EntityUtils; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import android.content.Context; import android.content.SharedPreferences; import android.util.Log; public class RegisterClient { private static final String PREFS_NAME = "ANHSettings"; private static final String REGID_SETTING_NAME = "ANHRegistrationId"; private String Backend_Endpoint; SharedPreferences settings; protected HttpClient httpClient; private String authorizationHeader; public RegisterClient(Context context, String backendEndpoint) { super(); this.settings = context.getSharedPreferences(PREFS_NAME, 0); httpClient = new DefaultHttpClient(); Backend_Endpoint = backendEndpoint + "/api/register"; } public String getAuthorizationHeader() { return authorizationHeader; } public void setAuthorizationHeader(String authorizationHeader) { this.authorizationHeader = authorizationHeader; } public void register(String handle, Set<String> tags) throws ClientProtocolException, IOException, JSONException { String registrationId = retrieveRegistrationIdOrRequestNewOne(handle); JSONObject deviceInfo = new JSONObject(); deviceInfo.put("Platform", "fcm"); deviceInfo.put("Handle", handle); deviceInfo.put("Tags", new JSONArray(tags)); int statusCode = upsertRegistration(registrationId, deviceInfo); if (statusCode == HttpStatus.SC_OK) { return; } else if (statusCode == HttpStatus.SC_GONE){ settings.edit().remove(REGID_SETTING_NAME).commit(); registrationId = retrieveRegistrationIdOrRequestNewOne(handle); statusCode = upsertRegistration(registrationId, deviceInfo); if (statusCode != HttpStatus.SC_OK) { Log.e("RegisterClient", "Error upserting registration: " + statusCode); throw new RuntimeException("Error upserting registration"); } } else { Log.e("RegisterClient", "Error upserting registration: " + statusCode); throw new RuntimeException("Error upserting registration"); } } private int upsertRegistration(String registrationId, JSONObject deviceInfo) throws UnsupportedEncodingException, IOException, ClientProtocolException { HttpPut request = new HttpPut(Backend_Endpoint+"/"+registrationId); request.setEntity(new StringEntity(deviceInfo.toString())); request.addHeader("Authorization", "Basic "+authorizationHeader); request.addHeader("Content-Type", "application/json"); HttpResponse response = httpClient.execute(request); int statusCode = response.getStatusLine().getStatusCode(); return statusCode; } private String retrieveRegistrationIdOrRequestNewOne(String handle) throws ClientProtocolException, IOException { if (settings.contains(REGID_SETTING_NAME)) return settings.getString(REGID_SETTING_NAME, null); HttpUriRequest request = new HttpPost(Backend_Endpoint+"?handle="+handle); request.addHeader("Authorization", "Basic "+authorizationHeader); HttpResponse response = httpClient.execute(request); if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) { Log.e("RegisterClient", "Error creating registrationId: " + response.getStatusLine().getStatusCode()); throw new RuntimeException("Error creating Notification Hubs registrationId"); } String registrationId = EntityUtils.toString(response.getEntity()); registrationId = registrationId.substring(1, registrationId.length()-1); settings.edit().putString(REGID_SETTING_NAME, registrationId).commit(); return registrationId; } }
Ce composant met en œuvre les appels REST nécessaires pour contacter le backend de l’application et inscrire cette dernière pour les notifications Push. Il enregistre également en local les informations registrationIds créées par le hub de notification, comme expliqué dans la rubrique Inscription auprès du serveur principal de votre application. Elle utilise un jeton d’autorisation stocké dans le stockage local lorsque vous cliquez sur le bouton Se connecter.
Dans votre classe
MainActivity
, ajoutez un champ pour la classeRegisterClient
et une chaîne pour le point de terminaison de votre backend ASP.NET. Remplacez bien<Enter Your Backend Endpoint>
par le point de terminaison réel de votre serveur principal, obtenu précédemment. Par exemple :http://mybackend.azurewebsites.net
.private RegisterClient registerClient; private static final String BACKEND_ENDPOINT = "<Enter Your Backend Endpoint>"; FirebaseInstanceId fcm; String FCM_token = null;
Dans votre classe
MainActivity
, dans la méthodeonCreate
, supprimez ou commentez l'initialisation du champhub
et l'appel à la méthoderegisterWithNotificationHubs
. Ensuite, ajoutez du code pour initialiser une instance de la classeRegisterClient
. La méthode doit contenir les lignes qui suivent :@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mainActivity = this; FirebaseService.createChannelAndHandleNotifications(getApplicationContext()); fcm = FirebaseInstanceId.getInstance(); registerClient = new RegisterClient(this, BACKEND_ENDPOINT); setContentView(R.layout.activity_main); }
Ajoutez les instructions
import
suivantes à votre fichierMainActivity.java
.import android.util.Base64; import android.view.View; import android.widget.EditText; import android.widget.Button; import android.widget.ToggleButton; import java.io.UnsupportedEncodingException; import android.content.Context; import java.util.HashSet; import android.widget.Toast; import org.apache.http.client.ClientProtocolException; import java.io.IOException; import org.apache.http.HttpStatus; import android.os.AsyncTask; import org.apache.http.HttpResponse; import org.apache.http.client.methods.HttpPost; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.DefaultHttpClient; import android.app.AlertDialog; import android.content.DialogInterface; import com.google.firebase.iid.FirebaseInstanceId; import com.google.firebase.iid.InstanceIdResult; import com.google.android.gms.tasks.OnSuccessListener; import java.util.concurrent.TimeUnit;
Remplacez le code dans la méthode onStart par le code suivant :
super.onStart(); Button sendPush = (Button) findViewById(R.id.sendbutton); sendPush.setEnabled(false);
Ensuite, ajoutez les méthodes suivantes pour gérer l’événement de clic sur le bouton Se connecter et l’envoi de notifications Push.
public void login(View view) throws UnsupportedEncodingException { this.registerClient.setAuthorizationHeader(getAuthorizationHeader()); final Context context = this; new AsyncTask<Object, Object, Object>() { @Override protected Object doInBackground(Object... params) { try { FirebaseInstanceId.getInstance().getInstanceId().addOnSuccessListener(new OnSuccessListener<InstanceIdResult>() { @Override public void onSuccess(InstanceIdResult instanceIdResult) { FCM_token = instanceIdResult.getToken(); Log.d(TAG, "FCM Registration Token: " + FCM_token); } }); TimeUnit.SECONDS.sleep(1); registerClient.register(FCM_token, new HashSet<String>()); } catch (Exception e) { DialogNotify("MainActivity - Failed to register", e.getMessage()); return e; } return null; } protected void onPostExecute(Object result) { Button sendPush = (Button) findViewById(R.id.sendbutton); sendPush.setEnabled(true); Toast.makeText(context, "Signed in and registered.", Toast.LENGTH_LONG).show(); } }.execute(null, null, null); } private String getAuthorizationHeader() throws UnsupportedEncodingException { EditText username = (EditText) findViewById(R.id.usernameText); EditText password = (EditText) findViewById(R.id.passwordText); String basicAuthHeader = username.getText().toString()+":"+password.getText().toString(); basicAuthHeader = Base64.encodeToString(basicAuthHeader.getBytes("UTF-8"), Base64.NO_WRAP); return basicAuthHeader; } /** * This method calls the ASP.NET WebAPI backend to send the notification message * to the platform notification service based on the pns parameter. * * @param pns The platform notification service to send the notification message to. Must * be one of the following ("wns", "fcm", "apns"). * @param userTag The tag for the user who will receive the notification message. This string * must not contain spaces or special characters. * @param message The notification message string. This string must include the double quotes * to be used as JSON content. */ public void sendPush(final String pns, final String userTag, final String message) throws ClientProtocolException, IOException { new AsyncTask<Object, Object, Object>() { @Override protected Object doInBackground(Object... params) { try { String uri = BACKEND_ENDPOINT + "/api/notifications"; uri += "?pns=" + pns; uri += "&to_tag=" + userTag; HttpPost request = new HttpPost(uri); request.addHeader("Authorization", "Basic "+ getAuthorizationHeader()); request.setEntity(new StringEntity(message)); request.addHeader("Content-Type", "application/json"); HttpResponse response = new DefaultHttpClient().execute(request); if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) { DialogNotify("MainActivity - Error sending " + pns + " notification", response.getStatusLine().toString()); throw new RuntimeException("Error sending notification"); } } catch (Exception e) { DialogNotify("MainActivity - Failed to send " + pns + " notification ", e.getMessage()); return e; } return null; } }.execute(null, null, null); }
Le gestionnaire
login
pour le bouton Se connecter génère une utilisation du jeton d'authentification de base sur l’entrée de nom d’utilisateur et de mot de passe (qui représente n’importe quel jeton utilisé par votre schéma d’authentification), puis il utiliseRegisterClient
pour appeler le principal et s’inscrire.La méthode
sendPush
appelle le serveur principal pour déclencher une notification sécurisée pour l'utilisateur basée sur la balise d'utilisateur. Le service de notification de la plateforme ciblé parsendPush
varie selon la chaînepns
passée.Ajoutez la méthode
DialogNotify
suivante à la classeMainActivity
.protected void DialogNotify(String title, String message) { AlertDialog alertDialog = new AlertDialog.Builder(MainActivity.this).create(); alertDialog.setTitle(title); alertDialog.setMessage(message); alertDialog.setButton(AlertDialog.BUTTON_NEUTRAL, "OK", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); } }); alertDialog.show(); }
Dans votre classe
MainActivity
, mettez à jour la méthodesendNotificationButtonOnClick
pour appeler la méthodesendPush
avec les services de notification de plateforme sélectionnés par l'utilisateur, comme suit./** * Send Notification button click handler. This method sends the push notification * message to each platform selected. * * @param v The view */ public void sendNotificationButtonOnClick(View v) throws ClientProtocolException, IOException { String nhMessageTag = ((EditText) findViewById(R.id.editTextNotificationMessageTag)) .getText().toString(); String nhMessage = ((EditText) findViewById(R.id.editTextNotificationMessage)) .getText().toString(); // JSON String nhMessage = "\"" + nhMessage + "\""; if (((ToggleButton)findViewById(R.id.toggleButtonWNS)).isChecked()) { sendPush("wns", nhMessageTag, nhMessage); } if (((ToggleButton)findViewById(R.id.toggleButtonFCM)).isChecked()) { sendPush("fcm", nhMessageTag, nhMessage); } if (((ToggleButton)findViewById(R.id.toggleButtonAPNS)).isChecked()) { sendPush("apns", nhMessageTag, nhMessage); } }
Dans le fichier
build.gradle
, ajoutez la ligne suivante à la sectionandroid
après la sectionbuildTypes
.useLibrary 'org.apache.http.legacy'
Si votre application cible le niveau d’API 28 (Android 9.0) ou supérieur, incluez la déclaration suivante dans l’élément
<application>
deAndroidManifest.xml
.<uses-library android:name="org.apache.http.legacy" android:required="false" />
Créez le projet.
Test de l'application
Exécutez l'application sur un appareil ou un émulateur à l'aide d'Android Studio.
Dans l'application Android, entrez un nom d'utilisateur et un mot de passe. Ils doivent représenter la même valeur de chaîne et ne pas contenir d'espaces ou de caractères spéciaux.
Dans l’application Android, cliquez sur Se connecter. Attendez que s’affiche un message indiquant Signed in and registered (Connecté et inscrit). Le bouton Send Notification est alors activé.
Cliquez sur les boutons bascule pour activer toutes les plateformes où vous avez exécuté l'application et inscrit un utilisateur.
Entrez le nom de l'utilisateur qui reçoit le message de notification. Cet utilisateur doit être inscrit pour les notifications sur les appareils cibles.
Entrez le message que l'utilisateur recevra sous la forme d'un message de notification Push.
Cliquez sur Send Notification. Chaque appareil doté d'une inscription avec la balise de nom d'utilisateur correspondante reçoit la notification Push.
Étapes suivantes
Dans ce tutoriel, vous avez appris à envoyer des notifications Push à des utilisateurs spécifiques ayant des balises associées à leurs enregistrements. Pour savoir comment envoyer des notifications basées sur l’emplacement, passez au tutoriel suivant :