Connecter des appareils par le biais de sessions à distanceConnect devices through remote sessions

La fonctionnalité sessions à distance permet à une application de se connecter à d’autres appareils par le biais d’une session, soit pour la messagerie d’application explicite, soit pour l’échange répartie de données gérées par le système, telles que le SpatialEntityStore pour le partage holographique entre des appareils Windows holographiques.The Remote Sessions feature allows an app to connect to other devices through a session, either for explicit app messaging or for brokered exchange of system-managed data, such as the SpatialEntityStore for holographic sharing between Windows Holographic devices.

Les sessions à distance peuvent être créées par n’importe quel appareil Windows, et tout appareil Windows peut demander à rejoindre (même si les sessions peuvent avoir une visibilité invitation uniquement), y compris les appareils connectés par d’autres utilisateurs.Remote sessions can be created by any Windows device, and any Windows device can request to join (although sessions can have invite-only visibility), including devices signed in by other users. Ce guide fournit un exemple de code de base pour tous les principaux scénarios qui utilisent des sessions à distance.This guide provides basic sample code for all of the major scenarios that make use of remote sessions. Ce code peut être incorporé dans un projet d’application existant et modifié en fonction des besoins.This code can be incorporated into an existing app project and modified as necessary. Pour une implémentation de bout en bout, consultez l' exemple d’application de jeu quiz.For an end-to-end implementation, see the Quiz Game sample app).

Installation préliminairePreliminary setup

Ajouter la fonctionnalité remoteSystemAdd the remoteSystem capability

Pour que votre application puisse lancer une application sur un appareil distant, vous devez ajouter la fonctionnalité remoteSystem dans le manifeste de votre package d’application.In order for your app to launch an app on a remote device, you must add the remoteSystem capability to your app package manifest. Vous pouvez utiliser le concepteur de manifeste de package pour l’ajouter en sélectionnant système distant sous l’onglet fonctionnalités , ou vous pouvez ajouter manuellement la ligne suivante au fichier Package. appxmanifest de votre projet.You can use the package manifest designer to add it by selecting Remote System on the Capabilities tab, or you can manually add the following line to your project's Package.appxmanifest file.

<Capabilities>
   <uap3:Capability Name="remoteSystem"/>
</Capabilities>

Activer la découverte des utilisateurs croisés sur l’appareilEnable cross-user discovering on the device

Les sessions à distance sont destinées à la connexion de plusieurs utilisateurs différents. par conséquent, les appareils concernés doivent avoir le partage entre utilisateurs activé.Remote Sessions is geared toward connecting multiple different users, so the devices involved will need to have Cross-User Sharing enabled. Il s’agit d’un paramètre système qui peut être interrogé à l’aide d’une méthode statique dans la classe RemoteSystem :This is a system setting that can be queried with a static method in the RemoteSystem class:

if (!RemoteSystem.IsAuthorizationKindEnabled(RemoteSystemAuthorizationKind.Anonymous)) {
    // The system is not authorized to connect to cross-user devices. 
    // Inform the user that they can discover more devices if they
    // update the setting to "Everyone nearby".
}

Pour modifier ce paramètre, l’utilisateur doit ouvrir l’application paramètres .To change this setting, the user must open the Settings app. Dans le Systemmenu Shared > ExperiencesShared from > Devices , il existe une zone de liste déroulante dans laquelle l’utilisateur peut spécifier les appareils avec lesquels il peut partager le système.In the System > Shared experiences > Share across devices menu, there is a drop-down box where the user can specify which devices their system can share with.

page des paramètres des expériences partagées

Inclure les espaces de noms nécessairesInclude the necessary namespaces

Pour utiliser tous les extraits de code de ce guide, vous aurez besoin des using instructions suivantes dans votre ou vos fichiers de classe.In order to use all of the code snippets in this guide, you will need the following using statements in your class file(s).

using System.Runtime.Serialization.Json;
using Windows.Foundation.Collections;
using Windows.System.RemoteSystems;

Créer une session à distanceCreate a remote session

Pour créer une instance de session distante, vous devez commencer par un objet RemoteSystemSessionController .To create a remote session instance, you must start with a RemoteSystemSessionController object. Utilisez l’infrastructure suivante pour créer une nouvelle session et gérer les demandes de jointure d’autres appareils.Use the following framework to create a new session and handle join requests from other devices.

public async void CreateSession() {
    
    // create a session controller
    RemoteSystemSessionController manager = new RemoteSystemSessionController("Bob’s Minecraft game");
    
    // register the following code to handle the JoinRequested event
    manager.JoinRequested += async (sender, args) => {
        // Get the deferral
        var deferral = args.GetDeferral();
        
        // display the participant (args.JoinRequest.Participant) on UI, giving the 
        // user an opportunity to respond
        // ...
        
        // If the user chooses "accept", accept this remote system as a participant
        args.JoinRequest.Accept();
    };
    
    // create and start the session
    RemoteSystemSessionCreationResult createResult = await manager.CreateSessionAsync();
    
    // handle the creation result
    if (createResult.Status == RemoteSystemSessionCreationStatus.Success) {
        // creation was successful, get a reference to the session
        RemoteSystemSession currentSession = createResult.Session;
        
        // optionally subscribe to the disconnection event
        currentSession.Disconnected += async (sender, args) => {
            // update the UI, using args.Reason
            //...
        };
    
        // Use session (see later section)
        //...
    
    } else if (createResult.Status == RemoteSystemSessionCreationStatus.SessionLimitsExceeded) {
        // creation failed. Optionally update UI to indicate that there are too many sessions in progress
    } else {
        // creation failed for an unknown reason. Optionally update UI
    }
}

Créer une invitation de session à distance uniquementMake a remote session invite-only

Si vous souhaitez que votre session à distance reste publiquement détectable, vous pouvez l’inviter uniquement.If you wish to keep your remote session from being publicly discoverable, you can make it invite-only. Seuls les appareils qui reçoivent une invitation peuvent envoyer des demandes de jointure.Only the devices that receive an invitation will be able to send join requests.

La procédure est essentiellement la même que ci-dessus, mais lors de la construction de l’instance RemoteSystemSessionController , vous transmettez un objet RemoteSystemSessionOptions configuré.The procedure is mostly the same as above, but when constructing the RemoteSystemSessionController instance, you will pass in a configured RemoteSystemSessionOptions object.

// define the session options with the invite-only designation
RemoteSystemSessionOptions sessionOptions = new RemoteSystemSessionOptions();
sessionOptions.IsInviteOnly = true;

// create the session controller
RemoteSystemSessionController manager = new RemoteSystemSessionController("Bob's Minecraft game", sessionOptions);

//...

Pour envoyer une invitation, vous devez disposer d’une référence au système distant récepteur (acquisition par le biais d’une découverte normale du système distant).To send an invitation, you must have a reference to the receiving remote system (acquired through normal remote system discovery). Transmettez simplement cette référence dans la méthode SendInvitationAsync de l’objet de session.Simply pass this reference into the session object's SendInvitationAsync method. Tous les participants d’une session ont une référence à la session à distance (voir la section suivante), de sorte que tout participant peut envoyer une invitation.All of the participants in a session have a reference to the remote session (see next section), so any participant can send an invitation.

// "currentSession" is a reference to a RemoteSystemSession.
// "guestSystem" is a previously discovered RemoteSystem instance
currentSession.SendInvitationAsync(guestSystem); 

Découvrir et rejoindre une session à distanceDiscover and join a remote session

Le processus de découverte des sessions à distance est géré par la classe RemoteSystemSessionWatcher et est semblable à la découverte de systèmes distants individuels.The process of discovering remote sessions is handled by the RemoteSystemSessionWatcher class and is similar to discovering individual remote systems.

public void DiscoverSessions() {
    
    // create a watcher for remote system sessions
    RemoteSystemSessionWatcher sessionWatcher = RemoteSystemSession.CreateWatcher();
    
    // register a handler for the "added" event
    sessionWatcher.Added += async (sender, args) => {
        
        // get a reference to the info about the discovered session
        RemoteSystemSessionInfo sessionInfo = args.SessionInfo;
        
        // Optionally update the UI with the sessionInfo.DisplayName and 
        // sessionInfo.ControllerDisplayName strings. 
        // Save a reference to this RemoteSystemSessionInfo to use when the
        // user selects this session from the UI
        //...
    };
    
    // Begin watching
    sessionWatcher.Start();
}

Lorsqu’une instance RemoteSystemSessionInfo est obtenue, elle peut être utilisée pour émettre une demande de jointure à l’appareil qui contrôle la session correspondante.When a RemoteSystemSessionInfo instance is obtained, it can be used to issue a join request to the device that controls the corresponding session. Une demande de jointure acceptée retourne de manière asynchrone un objet RemoteSystemSessionJoinResult qui contient une référence à la session jointe.An accepted join request will asynchronously return a RemoteSystemSessionJoinResult object that contains a reference to the joined session.

public async void JoinSession(RemoteSystemSessionInfo sessionInfo) {

    // issue a join request and wait for result.
    RemoteSystemSessionJoinResult joinResult = await sessionInfo.JoinAsync();
    if (joinResult.Status == RemoteSystemSessionJoinStatus.Success) {
        // Join request was approved

        // RemoteSystemSession instance "currentSession" was declared at class level.
        // Assign the value obtained from the join result.
        currentSession = joinResult.Session;
        
        // note connection and register to handle disconnection event
        bool isConnected = true;
        currentSession.Disconnected += async (sender, args) => {
            isConnected = false;

            // update the UI with args.Reason value
        };
        
        if (isConnected) {
            // optionally use the session here (see next section)
            //...
        }
    } else {
        // Join was unsuccessful.
        // Update the UI, using joinResult.Status value to show cause of failure.
    }
}

Un appareil peut être joint à plusieurs sessions en même temps.A device can be joined to multiple sessions at the same time. Pour cette raison, il peut être souhaitable de séparer la fonctionnalité de jointure de l’interaction réelle avec chaque session.For this reason, it may be desirable to separate the joining functionality from the actual interaction with each session. Tant qu’une référence à l’instance RemoteSystemSession est conservée dans l’application, la communication peut être tentée sur cette session.As long as a reference to the RemoteSystemSession instance is maintained in the app, communication can be attempted over that session.

Partager des messages et des données par le biais d’une session à distanceShare messages and data through a remote session

Recevoir des messagesReceive messages

Vous pouvez échanger des messages et des données avec d’autres appareils participants dans la session à l’aide d’une instance RemoteSystemSessionMessageChannel , qui représente un canal de communication unique à l’ensemble de la session.You can exchange messages and data with other participant devices in the session by using a RemoteSystemSessionMessageChannel instance, which represents a single session-wide communication channel. Dès qu’elle est initialisée, elle commence à écouter les messages entrants.As soon as it's initialized, it begins listening for incoming messages.

Notes

Les messages doivent être sérialisés et désérialisés à partir des tableaux d’octets lors de l’envoi et de la réception.Messages must be serialized and deserialized from byte arrays upon sending and receiving. Cette fonctionnalité est incluse dans les exemples suivants, mais elle peut être implémentée séparément pour une meilleure modularité du code.This functionality is included in the following examples, but it can be implemented separately for better code modularity. Pour obtenir un exemple, consultez l' exemple d’application).See the sample app) for an example of this.

public async void StartReceivingMessages() {
    
    // Initialize. The channel name must be known by all participant devices 
    // that will communicate over it.
    RemoteSystemSessionMessageChannel messageChannel = new RemoteSystemSessionMessageChannel(currentSession, 
        "Everyone in Bob's Minecraft game", 
        RemoteSystemSessionMessageChannelReliability.Reliable);
    
    // write the handler for incoming messages on this channel
    messageChannel.ValueSetReceived += async (sender, args) => {
        
        // Update UI: a message was received from the participant args.Sender
        
        // Deserialize the message 
        // (this app must know what key to use and what object type the value is expected to be)
        ValueSet receivedMessage = args.Message;
        object rawData = receivedMessage["appKey"]);
        object value = new ExpectedType(); // this must be whatever type is expected

        using (var stream = new MemoryStream((byte[])rawData)) {
            value = new DataContractJsonSerializer(value.GetType()).ReadObject(stream);
        }
        
        // do something with the "value" object
        //...
    };
}

Envoyer des messagesSend messages

Lorsque le canal est établi, l’envoi d’un message à tous les participants de session est simple.When the channel is established, sending a message to all of the session participants is straightforward.

public async void SendMessageToAllParticipantsAsync(RemoteSystemSessionMessageChannel messageChannel, object value){

    // define a ValueSet message to send
    ValueSet message = new ValueSet();
    
    // serialize the "value" object to send
    using (var stream = new MemoryStream()){
        new DataContractJsonSerializer(value.GetType()).WriteObject(stream, value);
        byte[] rawData = stream.ToArray();
            message["appKey"] = rawData;
    }
    
    // Send message to all participants. Ordering is not guaranteed.
    await messageChannel.BroadcastValueSetAsync(message);
}

Pour envoyer un message uniquement à certains participants, vous devez commencer par lancer un processus de découverte afin d’obtenir des références aux systèmes distants participant à la session.In order to send a message to only certain participant(s), you must first initiate a discovery process to acquire references to the remote systems participating in the session. Cela est similaire au processus de découverte de systèmes distants en dehors d’une session.This is similar to the process of discovering remote systems outside of a session. Utilisez une instance RemoteSystemSessionParticipantWatcher pour rechercher les appareils participants d’une session.Use a RemoteSystemSessionParticipantWatcher instance to find a session's participant devices.

public void WatchForParticipants() {
    // "currentSession" is a reference to a RemoteSystemSession.
    RemoteSystemSessionParticipantWatcher watcher = currentSession.CreateParticipantWatcher();

    watcher.Added += (sender, participant) => {
        // save a reference to "participant"
        // optionally update UI
    };   

    watcher.Removed += (sender, participant) => {
        // remove reference to "participant"
        // optionally update UI
    };

    watcher.EnumerationCompleted += (sender, args) => {
        // Apps can delay data model render up until this point if they wish.
    };

    // Begin watching for session participants
    watcher.Start();
}

Quand une liste de références à des participants de session est obtenue, vous pouvez envoyer un message à n’importe quel ensemble d’entre eux.When a list of references to session participants is obtained you can send a message to any set of them.

Pour envoyer un message à un seul participant (idéalement sélectionné à l’écran par l’utilisateur), transmettez simplement la référence dans une méthode comme suit.To send a message to a single participant (ideally selected on-screen by the user), simply pass the reference into a method like the following.

public async void SendMessageToParticipantAsync(RemoteSystemSessionMessageChannel messageChannel, RemoteSystemSessionParticipant participant, object value) {
    
    // define a ValueSet message to send
    ValueSet message = new ValueSet();
    
    // serialize the "value" object to send
    using (var stream = new MemoryStream()){
        new DataContractJsonSerializer(value.GetType()).WriteObject(stream, value);
        byte[] rawData = stream.ToArray();
            message["appKey"] = rawData;
    }

    // Send message to the participant
    await messageChannel.SendValueSetAsync(message,participant);
}

Pour envoyer un message à plusieurs participants (idéalement sélectionnés sur l’écran par l’utilisateur), ajoutez-les à un objet de liste, puis transmettez la liste dans une méthode similaire à la suivante.To send a message to multiple participants (ideally selected on-screen by the user), add them to a list object and pass the list into a method like the following.

public async void SendMessageToListAsync(RemoteSystemSessionMessageChannel messageChannel, IReadOnlyList<RemoteSystemSessionParticipant> myTeam, object value){

    // define a ValueSet message to send
    ValueSet message = new ValueSet();
    
    // serialize the "value" object to send
    using (var stream = new MemoryStream()){
        new DataContractJsonSerializer(value.GetType()).WriteObject(stream, value);
        byte[] rawData = stream.ToArray();
            message["appKey"] = rawData;
    }

    // Send message to specific participants. Ordering is not guaranteed.
    await messageChannel.SendValueSetToParticipantsAsync(message, myTeam);   
}