Verbinden von Geräten über Remotesitzungen

Mit dem Remotesitzungsfeature kann eine App über eine Sitzung eine Verbindung mit anderen Geräten herstellen, entweder für explizites App-Messaging oder für den vermittelten Austausch von vom System verwalteten Daten, z. B. den SpatialEntityStore für die holografische Freigabe zwischen Windows Holographic-Geräten.

Remotesitzungen können von jedem Windows-Gerät erstellt werden, und jedes Windows-Gerät kann die Teilnahme anfordern (obwohl Sitzungen nur die Sichtbarkeit von Einladungen haben können), einschließlich der von anderen Benutzern angemeldeten Geräte. Dieses Handbuch enthält grundlegenden Beispielcode für alle wichtigen Szenarien, die Remotesitzungen verwenden. Dieser Code kann bei Bedarf in ein vorhandenes App-Projekt integriert und geändert werden. Eine End-to-End-Implementierung finden Sie in der Quizspiel-Beispiel-App).

Vorläufige Einstellungen

Hinzufügen der RemoteSystem-Funktion

Damit Ihre App eine App auf einem Remotegerät starten kann, müssen Sie dem App-Paketmanifest die remoteSystem Funktion hinzufügen. Sie können den Paketmanifest-Designer verwenden, um es hinzuzufügen, indem Sie remote system auf der Registerkarte "Funktionen" auswählen, oder Sie können die folgende Zeile manuell zur Datei "Package.appxmanifest" Ihres Projekts hinzufügen.

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

Aktivieren der benutzerübergreifenden Erkennung auf dem Gerät

Remotesitzungen sind darauf ausgerichtet, mehrere verschiedene Benutzer zu verbinden, sodass die beteiligten Geräte die benutzerübergreifende Freigabe aktiviert haben müssen. Dies ist eine Systemeinstellung, die mit einer statischen Methode in der RemoteSystem-Klasse abgefragt werden kann:

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

Um diese Einstellung zu ändern, muss der Benutzer die Einstellungs-App öffnen. Im Menü "Gemeinsame Gerätefreigabe>" gibt es ein Dropdownfeld, in dem der Benutzer angeben kann, für welche Geräte sein System freigegeben werden kann.>

Seite

Einschließen der erforderlichen Namespaces

Um alle Codeausschnitte in diesem Leitfaden zu verwenden, benötigen Sie die folgenden using Anweisungen in Ihren Klassendateien.

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

Erstellen einer Remotesitzung

Um eine Remotesitzungsinstanz zu erstellen, müssen Sie mit einem RemoteSystemSessionController-Objekt beginnen. Verwenden Sie das folgende Framework, um eine neue Sitzung zu erstellen und Join-Anforderungen von anderen Geräten zu verarbeiten.

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

Erstellen einer Nur-Remotesitzung

Wenn Sie ihre Remotesitzung daran hindern möchten, öffentlich auffindbar zu sein, können Sie sie nur einladen. Nur die Geräte, die eine Einladung erhalten, können Beitrittsanfragen senden.

Die Prozedur ist größtenteils identisch mit oben, aber beim Erstellen der RemoteSystemSessionController-Instanz übergeben Sie ein konfiguriertes RemoteSystemSessionOptions-Objekt.

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

//...

Um eine Einladung zu senden, benötigen Sie einen Verweis auf das empfangende Remotesystem (erworben über normale Remotesystemermittlung). Übergeben Sie diesen Verweis einfach an die SendInvitationAsync-Methode des Sitzungsobjekts. Alle Teilnehmer in einer Sitzung haben einen Verweis auf die Remotesitzung (siehe nächster Abschnitt), damit jeder Teilnehmer eine Einladung senden kann.

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

Entdecken und Teilnehmen an einer Remotesitzung

Der Prozess der Ermittlung von Remotesitzungen wird von der RemoteSystemSessionWatcher-Klasse behandelt und ähnelt der Ermittlung einzelner Remotesysteme.

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

Wenn eine RemoteSystemSessionInfo-Instanz abgerufen wird, kann sie verwendet werden, um eine Beitrittsanforderung an das Gerät ausstellen, das die entsprechende Sitzung steuert. Eine Akzeptierte Join-Anforderung gibt asynchron ein RemoteSystemSessionJoinResult - Objekt zurück, das einen Verweis auf die verknüpfte Sitzung enthält.

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

Ein Gerät kann gleichzeitig mit mehreren Sitzungen verbunden werden. Aus diesem Grund kann es wünschenswert sein, die Verknüpfungsfunktionalität von der tatsächlichen Interaktion mit jeder Sitzung zu trennen. Solange ein Verweis auf die RemoteSystemSession-Instanz in der App beibehalten wird, kann die Kommunikation über diese Sitzung versucht werden.

Freigeben von Nachrichten und Daten über eine Remotesitzung

Empfangen von Nachrichten

Sie können Nachrichten und Daten mit anderen Teilnehmergeräten in der Sitzung austauschen, indem Sie eine RemoteSystemSessionMessageChannel-Instanz verwenden, die einen einzelnen sitzungsweiten Kommunikationskanal darstellt. Sobald sie initialisiert wird, beginnt sie mit der Überwachung eingehender Nachrichten.

Hinweis

Nachrichten müssen beim Senden und Empfangen von Bytearrays serialisiert und deserialisiert werden. Diese Funktionalität ist in den folgenden Beispielen enthalten, kann jedoch separat implementiert werden, um die Modularität des Codes zu verbessern. Ein Beispiel hierfür finden Sie in der Beispiel-App.

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
        //...
    };
}

Senden von Nachrichten

Wenn der Kanal eingerichtet wird, ist das Senden einer Nachricht an alle Sitzungsteilnehmer einfach.

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

Um eine Nachricht nur an bestimmte Teilnehmer zu senden, müssen Sie zuerst einen Ermittlungsprozess initiieren, um Verweise auf die Remotesysteme zu erhalten, die an der Sitzung teilnehmen. Dies ähnelt dem Ermittlungsprozess von Remotesystemen außerhalb einer Sitzung. Verwenden Sie eine RemoteSystemSessionParticipantWatcher-Instanz , um die Teilnehmergeräte einer Sitzung zu finden.

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

Wenn eine Liste von Verweisen auf Sitzungsteilnehmer abgerufen wird, können Sie eine Nachricht an eine beliebige Gruppe senden.

Um eine Nachricht an einen einzelnen Teilnehmer zu senden (idealerweise vom Benutzer auf dem Bildschirm ausgewählt), übergeben Sie einfach den Verweis an eine Methode wie die folgende.

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

Um eine Nachricht an mehrere Teilnehmer zu senden (idealerweise vom Benutzer auf dem Bildschirm ausgewählt), fügen Sie sie zu einem Listenobjekt hinzu und übergeben die Liste an eine Methode wie die folgende.

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