Guide pratique : Intégration à la fonctionnalité Notifications Graph (Android)
Les notifications Graph permettent à votre application d’envoyer et de gérer des notifications ciblant l’utilisateur sur plusieurs appareils.
Avec le SDK côté client Projet Rome sur Android, votre application Android peut s’inscrire pour recevoir des notifications publiées à partir de votre serveur d’applications ciblant un utilisateur connecté. Le SDK permet au client d’application de recevoir les nouvelles charges utiles de notification entrante, gérer l’état des notifications existantes et récupérer l’historique des notifications. Pour plus d’informations sur la fonctionnalité Notifications et la façon dont elle permet la remise de notifications centrées sur la personne, consultez Vue d’ensemble des notifications Microsoft Graph.
Toutes les fonctionnalités du SDK Projet Rome, notamment Notifications Graph, reposent sur une plateforme sous-jacente appelée « Plateforme d’appareils connectés ». Ce guide est conçu de façon à vous guider tout au long des étapes nécessaires pour commencer à utiliser la Plateforme d’appareils connectés et à expliquer comment utiliser les API du SDK afin d’implémenter des fonctionnalités spécifiques aux notifications Graph.
Consultez la page Informations de référence sur les API pour obtenir des liens vers la documentation de référence pertinente pour les scénarios de notification.
Les étapes ci-dessous font référence à du code tiré de l’exemple d’application Android du projet Rome.
Pour toutes les fonctionnalités d’Appareils connectés, vous aurez besoin d’un IDE de développement d’application Android et d’un appareil Android doté d’une architecture prise en charge (armeabi-v7a, arm64-v8a, x86 ou x86_64) ou d’un émulateur. Le système doit exécuter Android version 4.4.2 ou ultérieure.
Configuration préliminaire pour la Plateforme d’appareils connectés et les notifications
Avant d’implémenter la connectivité à distance, vous devez effectuer plusieurs étapes pour permettre à votre application Android de se connecter à des appareils distants mais aussi d’envoyer et recevoir des notifications.
Inscrire votre application
L’authentification de compte Microsoft (MSA) ou Azure Active Directory (AAD) est nécessaire pour pratiquement toutes les fonctionnalités du SDK du projet Rome (les API de partage de proximité étant l’exception). Si vous ne disposez pas déjà d’un compte MSA et que souhaitez en utiliser un, inscrivez-vous sur account.microsoft.com.
Notes
Les comptes Azure Active Directory (AAD) ne sont pas pris en charge avec les API de relais d’appareils.
En utilisant la méthode d’authentification de votre choix, vous devez inscrire votre application auprès de Microsoft en suivant les instructions qui se trouvent sur le portail d’inscription des applications. Si vous n’avez pas de compte de développeur Microsoft, vous devrez en créer un.
Quand vous inscrivez une application à l’aide d’un compte MSA, vous devez recevoir une chaîne d’ID client. Enregistrez-la pour plus tard. Elle permettra à votre application d’accéder aux ressources de la Plateforme d’appareils connectés de Microsoft. Si vous utilisez AAD, consultez Bibliothèques d’authentification d’Azure Active Directory pour savoir comment obtenir la chaîne d’ID client.
Ajouter le kit SDK
Insérez les références de référentiel ci-dessous dans le fichier build.gradle à la racine de votre projet.
allprojects {
repositories {
jcenter()
}
}
Insérez ensuite la dépendance suivante dans le fichier build.gradle qui se trouve dans le dossier de votre projet.
dependencies {
...
implementation 'com.microsoft.connecteddevices:connecteddevices-sdk:+'
}
Dans le fichier AndroidManifest.xml de votre projet, ajoutez les autorisations suivantes à l’intérieur de l’élément <manifest>
(si elles ne s’y trouvent pas déjà). Cela donne à votre application l’autorisation de se connecter à Internet et d’activer la découverte Bluetooth sur votre appareil.
Notez que les autorisations liées à Bluetooth servent uniquement à la découverte Bluetooth ; elles n’ont pas d’utilité pour les autres fonctionnalités de la Plateforme d’appareils connectés. Par ailleurs, ACCESS_COARSE_LOCATION
est nécessaire uniquement pour les SDK Android version 21 et ultérieure. Sur les kits SDK Android version 23 et ultérieure, le développeur doit aussi demander à l’utilisateur d’accorder l’accès à l’emplacement au moment de l’exécution.
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
Ensuite, accédez aux classes d’activité dans lesquelles vous voulez activer la fonctionnalité Appareils connectés. Importez les packages suivants.
import com.microsoft.connecteddevices;
import com.microsoft.connecteddevices.remotesystems;
import com.microsoft.connecteddevices.remotesystems.commanding;
Configuration de l’authentification et de la gestion des comptes
La Plateforme d’appareils connectés exige l’utilisation d’un jeton OAuth pendant l’inscription. Vous pouvez générer et gérer les jetons OAuth en employant la méthode qui vous convient le mieux. Cependant, pour aider les développeurs à commencer à utiliser la plateforme, nous avons inclus un fournisseur d’authentification dans l’exemple d’application Android qui génère et gère des jetons d’actualisation dans votre application pour vous faciliter la tâche.
Si vous souhaitez implémenter l’interface ConnectedDevicesAccountManager par vous-même, tenez compte des points suivants :
Si vous utilisez un compte MSA, vous devez inclure les étendues suivantes dans votre demande de connexion : "wl.offline_access"
, "ccs.ReadWrite"
, "dds.read"
, "dds.register"
, "wns.connect"
, "asimovrome.telemetry"
et "https://activity.windows.com/UserActivity.ReadWrite.CreatedByApp"
.
Si vous utilisez un compte AAD, vous devrez demander les audiences suivantes : "https://cdpcs.access.microsoft.com"
, "https://cs.dds.microsoft.com"
, "https://wns.windows.com/"
et "https://activity.microsoft.com"
.
Notes
Les comptes Azure Active Directory (AAD) ne sont pas pris en charge avec les API de relais d’appareils.
Que vous utilisiez l’implémentation ConnectedDevicesAccountManager fournie ou non, si vous utilisez AAD, vous devrez spécifier les autorisations suivantes dans l’inscription de votre application sur le portail Azure (portal.azure.com > Azure Active Directory > Inscriptions des applications) :
- Service de flux d’activités Microsoft
- Remettez et modifiez les notifications utilisateur pour cette application
- Lisez et écrivez l’activité de l’application dans le flux d’activités des utilisateurs
- Services de notifications Windows
- Connectez votre appareil au service de notification Windows
- Service d’annuaire d’appareils Microsoft
- Consultez votre liste d’appareils
- Faites-vous ajouter à votre liste d’appareils et d’applications
- Service de commande Microsoft
- Communiquez avec les appareils utilisateur
- Lisez les appareils utilisateur
Inscription de votre application pour les notifications Push
Pour bénéficier d’une prise en charge de Firebase Cloud Messaging, inscrivez votre application auprès de Google. Veillez à noter l’ID d’expéditeur et la clé serveur que vous recevez ; vous en aurez besoin par la suite.
Une fois l’inscription effectuée, vous devez associer la fonctionnalité de notification Push à la Plateforme d’appareils connectés dans votre application.
mNotificationRegistration = new ConnectedDevicesNotificationRegistration();
mNotificationRegistration.setType(ConnectedDevicesNotificationType.FCM);
mNotificationRegistration.setToken(token);
mNotificationRegistration.setAppId(Secrets.FCM_SENDER_ID);
mNotificationRegistration.setAppDisplayName("SampleApp");
Inscrire votre application dans le Centre de développement Microsoft pour des expériences inter-appareils
Important
Cette étape n’est nécessaire que si vous souhaitez utiliser les fonctionnalités du projet Rome pour accéder à des données ou effectuer des demandes à partir d’appareils non Windows. Si vous ciblez uniquement des appareils Windows, vous n’avez pas besoin d’effectuer cette étape.
Dans le tableau de bord du Centre de développement, accédez à Expériences inter-appareils à partir du volet de navigation de gauche, puis choisissez de configurer une nouvelle application inter-appareils, comme illustré ci-dessous.
Le processus d’intégration du Centre de développement comprend les étapes suivantes :
Sélectionnez les plateformes prises en charge, à savoir celles sur lesquelles votre application sera présente et compatible avec les expériences inter-appareils. Dans le cas de l’intégration des notifications Graph, vous pouvez sélectionner Windows, Android et/ou iOS.
Fournissez des ID d’application pour chaque plateforme sur laquelle votre application est présente. Pour les applications Android, il s’agit du nom de package que vous avez attribué à votre application au moment de créer le projet. Vous trouverez le nom de package dans votre console Firebase sous Project Overview -> General. Vous pouvez ajouter des ID différents (jusqu’à dix) par plateforme. Cela peut être utile si vous disposez de plusieurs versions d’une même application, voire différentes applications, et que vous souhaitez qu’elles puissent recevoir les mêmes notifications envoyées par votre serveur d’applications ciblant le même utilisateur.
Fournissez ou sélectionnez les ID d’application à partir des inscriptions d’application MSA et/ou AAD. Ces ID clients correspondant à l’inscription d’application MSA ou AAD ont été obtenus aux étapes précédentes d’inscription d’application MSA/AAD.
Les notifications Graph et les autres fonctionnalités de la Plateforme d’appareils connectés tirent parti de chacune des principales plateformes de notification natives pour envoyer des notifications aux points de terminaison clients d’application, à savoir, WNS (pour Windows UWP), FCM (pour Android) et APNS (pour iOS). Fournissez vos informations d’identification pour ces plateformes de notification pour permettre aux notifications Graph de transmettre les notifications pour votre serveur d’applications, dans le cas où vous publiez des notifications ciblant l’utilisateur. Pour Android, l’activation du service Cloud Messaging est un prérequis pour l’utilisation les notifications Microsoft Graph. De même, notez que l’ID d’expéditeur exigé correspond à l’ID d’expéditeur Firebase Cloud Messaging et que la clé d’API correspond à la clé serveur héritée. Vous trouverez ces deux éléments dans Firebase Console -> Project -> Settings, sous l’onglet Cloud Messaging, comme le montre la capture d’écran.
La dernière étape consiste à vérifier votre domaine application inter-appareils, qui sert de processus de vérification pour prouver que votre application est propriétaire de ce domaine qui fait office d’identité d’application inter-appareils pour l’application que vous avez inscrite.
Initialiser un canal de notification Graph
Le SDK Projet Rome permet à votre application de vous abonner à différents canaux afin de recevoir et de gérer différents types de données utilisateur, notamment les notifications Graph, les activités de l’utilisateur, et bien plus encore. Ils sont tous stockés et synchronisés dans UserDataFeed. UserNotification est la classe et le type de données correspondant à une notification ciblée sur l’utilisateur qui est envoyée par le biais de la fonctionnalité Notifications Graph. Pour effectuer une intégration à la fonctionnalité Notification Graph et recevoir un UserNotification publié par votre serveur d’applications, vous devez d’abord initialiser le flux de données utilisateur en créant un UserNotificationChannel. Vous devez considérer cette opération comme l’étape d’initialisation de la plateforme ci-dessus : elle doit être vérifiée et éventuellement refaite chaque fois que l’application s’affiche au premier plan (mais pas avant l’initialisation de la plateforme).
Les méthodes suivantes initialisent un UserNotificationChannel.
private UserNotificationChannel mNotificationChannel;
private UserDataFeed mUserDataFeed;
// ...
/**
* Initializes the UserNotificationFeed.
*/
public void initializeUserNotificationFeed() {
// define what scope of data this app needs
SyncScope[] scopes = { UserNotificationChannel.getSyncScope() };
// Get a reference to the UserDataFeed. This method is defined below
mUserDataFeed = getUserDataFeed(scopes, new EventListener<UserDataFeed, Void>() {
@Override
public void onEvent(UserDataFeed userDataFeed, Void aVoid) {
if (userDataFeed.getSyncStatus() == UserDataSyncStatus.SYNCHRONIZED) {
// log synchronized.
} else {
// log synchronization not completed.
}
}
});
// this method is defined below
mNotificationChannel = getUserNotificationChannel();
}
// instantiate the UserDataFeed
private UserDataFeed getUserDataFeed(SyncScope[] scopes, EventListener<UserDataFeed, Void> listener) {
UserAccount[] accounts = AccountProviderBroker.getSignInHelper().getUserAccounts();
if (accounts.length <= 0) {
// notify the user that sign-in is required
return null;
}
// use the initialized Platform instance, along with the cross-device app ID.
UserDataFeed feed = UserDataFeed.getForAccount(accounts[0], PlatformBroker.getPlatform(), Secrets.APP_HOST_NAME);
feed.addSyncStatusChangedListener(listener);
feed.addSyncScopes(scopes);
// sync data with the server
feed.startSync();
return feed;
}
// use the UserDataFeed reference to create a UserActivityChannel
@Nullable
private UserNotificationChannel getUserNotificationChannel() {
UserNotificationChannel channel = null;
try {
// create a UserNotificationChannel for the signed in account
channel = new UserNotificationChannel(mUserDataFeed);
} catch (Exception e) {
e.printStackTrace();
// handle exception
}
return channel;
}
À ce stade, vous devez avoir une référence à UserNotificationChannel dans mNotificationChannel
.
Créer un UserNotificationReader pour recevoir des UserNotification entrants et accéder à l’historique des UserNotification
Comme nous l’avons montré précédemment, la notification Google Cloud Messaging initiale arrivant sur le client d’application contient uniquement un passage de relais, et vous devez transmettre cette charge utile en passage de relais à la Plateforme d’appareils connectés afin de déclencher le SDK pour effectuer une synchronisation complète avec le serveur d’appareils connectés, lequel contient tous les UserNotifications publiés par votre serveur d’applications. Cette opération extrait la charge utile de notification complète publiée par votre serveur d’applications correspondant à ce passage de relais (et dans le cas où des notifications précédentes ont été publiées mais pas reçues sur ce client d’application en raison de la connectivité des appareils ou d’autres problèmes, elles seront également extraites). Avec ces synchronisations en temps réel effectuées en permanence par le SDK, le client d’application est en mesure d’accéder à un cache local de ce flux de données UserNotification de l’utilisateur connecté. Dans ce cas, un UserNotificationReader permet au client d’application d’accéder à ce flux de données (pour recevoir la dernière charge utile de notification par le biais du détecteur d’événements ou accéder à la collection d’éléments UserNotification complète qui peut être utilisée comme modèle d’affichage de l’historique des notifications de l’utilisateur).
Réception de UserNotifications
Vous devez d’abord instancier un UserNotificationReader et obtenir tous les UserNotifications existants dans le lecteur si la consommation de ces informations pour l’expérience que vous essayez d’activer vous intéresse. Étant donné que ce point de terminaison d’appareil particulier n’est peut-être pas le seul ou le premier point de terminaison que l’utilisateur a installé sur votre application, nous pouvons toujours présumer sans risque que le serveur d’applications a déjà publié des notifications à cet utilisateur connecté.
private static UserNotificationReader mReader;
private static final ArrayList<UserNotification> mHistoricalNotifications = new ArrayList<>();
// Instantiate UserNotificationReader
UserNotificationReaderOptions options = new UserNotificationReaderOptions();
mReader = mNotificationChannel.createReaderWithOptions(options);
// Read any previously published UserNotifications that have not expired yet
mReader.readBatchAsync(Long.MAX_VALUE).thenAccept(new AsyncOperation.ResultConsumer<UserNotification[]>() {
@Override
public void accept(UserNotification[] userNotifications) throws Throwable {
synchronized (mHistoricalNotifications) {
for (UserNotification notification : userNotifications) {
if (notification.getReadState() == UserNotificationReadState.UNREAD) {
mHistoricalNotifications.add(notification);
}
}
}
if (RunnableManager.getHistoryUpdated() != null) {
activity.runOnUiThread(RunnableManager.getHistoryUpdated());
}
}
});
Maintenant, ajoutez un détecteur d’événements qui se déclenche quand la Plateforme d’appareils connectés effectue une synchronisation et qu’elle doit vous informer de nouveaux changements. Dans le cas de la fonctionnalité Notifications Graph, les nouveaux changements peuvent être de nouveaux UserNotifications entrants publiés par votre serveur d’applications, ou des mises à jour, suppressions et expirations d’éléments UserNotifcation qui se sont produits à partir du serveur ou à partir d’autres points de terminaison inscrits auxquels le même utilisateur s’est connecté.
Conseil
Ce détecteur d’événements est l’endroit où vous traitez la principale logique métier et où vous « consommez » le contenu de votre charge utile de notification en fonction de vos scénarios. Si vous utilisez actuellement un message de données de Google Cloud Messaging pour construire une notification visuelle dans la barre de notification au niveau du système d’exploitation, ou si vous utilisez le contenu de la notification pour mettre à jour une interface utilisateur dans l’application, c’est l’endroit approprié pour cela.
mReader.addDataChangedListener(new EventListener<UserNotificationReader, Void>() {
@Override
public void onEvent(UserNotificationReader userNotificationReader, Void aVoid) {
userNotificationReader.readBatchAsync(Long.MAX_VALUE).thenAccept(new AsyncOperation.ResultConsumer<UserNotification[]>() {
@Override
public void accept(UserNotification[] userNotifications) throws Throwable {
boolean updatedNew = false;
boolean updatedHistorical = false;
synchronized (sHistoricalNotifications) {
for (final UserNotification notification : userNotifications) {
if (notification.getStatus() == UserNotificationStatus.ACTIVE && notification.getReadState() == UserNotificationReadState.UNREAD) {
switch (notification.getUserActionState()) {
case NO_INTERACTION:
// Brand new notification
// Insert business logic to construct a new visual notification in Android notification tray for the user to see
// ...
case DISMISSED:
// Existing notification that is marked as dismissed
// An app client receive this type of changes because another app client logged in by the same user has marked the notification as dismissed and the change is fanned-out to everywhere
// This state sync across app clients on different devices enable universal dismiss of notifications and other scenarios across multiple devices owned by the same user
// Insert business logic to dismiss the corresponding visual notification inside Android system notification tray, to make sure users don’t have to deal with redundant information across devices, and potentially insert this notification in your app’s notification history view
// ...
default:
// Unexpected
}
} else {
// ...
}
}
}
}
});
}
});
Mettre à jour l’état d’un UserNotification existant
Dans la section précédente, nous avons mentionné qu’un changement de UserNotification reçu par le biais du lecteur peut parfois être une mise à jour d’état sur un UserNotification existant (qu’il soit marqué comme masqué ou marqué comme lu). Dans ce cas, le client d’application peut choisir les actions à entreprendre, comme l’activation du masquage universel en supprimant la notification visuelle correspondante sur cet appareil particulier. Si nous revenons un peu en arrière, votre client d’application est souvent celui qui a lancé, à partir d’un autre appareil, cette mise à jour de changement de UserNotification pour commencer. Vous pouvez choisir le moment où mettre à jour l’état de vos UserNotifications, mais en général, ils sont mis à jour quand la notification visuelle correspondante est traitée par l’utilisateur sur cet appareil, ou quand l’utilisateur poursuit le traitement de la notification dans une expérience interne à l’application que vous activez. Voici un exemple de ce à quoi devrait ressembler le flux : Votre serveur d’applications publie une notification ciblant l’utilisateur A. L’utilisateur A reçoit cette notification à la fois sur son PC et sur son téléphone où les clients d’application sont installés. L’utilisateur clique sur la notification sur le PC et parcourt l’application pour traiter la tâche correspondante. Le client d’application sur ce PC appelle alors le SDK de la Plateforme d’appareils connectés pour mettre à jour l’état du UserNotification correspondant afin que cette mise à jour synchronisée soit disponible sur tous les appareils de cet utilisateur. Quand les autres clients d’application reçoivent cette mise à jour d’état en temps réel, ils suppriment l’alerte visuelle/le message/la notification toast correspondant du centre de notifications/de la barre de notifications de l’appareil. Voici comment les notifications sont universellement masquées sur les appareils d’un utilisateur.
Conseil
La classe UserNotification fournit actuellement 2 types de mises à jour d’état : vous pouvez modifier le UserNotificationReadState ou le UserNotificationUserActionState, et définir votre propre logique sur ce qui doit se produire quand des notifications sont mises à jour. Par exemple, vous pouvez marquer UserActionState comme Activated (Activé) ou Dismissed (Masqué), et vous appuyer sur cette valeur pour implémenter le masquage universel. Alternativement ou simultanément, vous pouvez marquer ReadState comme Read (Lu) ou Unread (Non lu) et, en vous appuyant sur cette valeur, déterminez quelles notifications doivent apparaître dans l’affichage de l’historique des notifications internes à l’application. L’extrait de code ci-dessous montre comment marquer le UserNotificationUserActionState d’une notification comme Dismissed (Masqué).
public void dismissNotification(int position) {
final UserNotification notification = mNewNotifications.get(position);
notification.setUserActionState(UserNotificationUserActionState.DISMISSED);
notification.saveAsync();
}