Delen via


Apparaten aansluiten via externe sessies

Met de functie Externe sessies kan een app via een sessie verbinding maken met andere apparaten, hetzij voor expliciete app-berichten of voor brokered uitwisseling van door het systeem beheerde gegevens, zoals de SpatialEntityStore- voor holografisch delen tussen Windows Holographic-apparaten.

Externe sessies kunnen worden gemaakt door elk Windows-apparaat en elk Windows-apparaat kan verzoeken om deel te nemen (hoewel sessies alleen zichtbaarheid van uitnodigingen kunnen hebben), inclusief apparaten die zijn aangemeld door andere gebruikers. Deze handleiding bevat eenvoudige voorbeeldcode voor alle belangrijke scenario's die gebruikmaken van externe sessies. Deze code kan worden opgenomen in een bestaand app-project en indien nodig worden gewijzigd. Zie de voorbeeld-app Quiz Game voor een end-to-end-implementatie.

Voorlopige installatie

De remoteSystem-mogelijkheid toevoegen

Als u wilt dat uw app een app op een extern apparaat start, moet u de remoteSystem mogelijkheid toevoegen aan uw app-pakketmanifest. U kunt de ontwerpfunctie voor pakketmanifest gebruiken om het toe te voegen door Remote System te selecteren op het tabblad Capabilities of u kunt de volgende regel handmatig toevoegen aan het package.appxmanifest-bestand van uw project.

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

Detectie door meerdere gebruikers op het apparaat inschakelen

Remote-sessies zijn bedoeld om verschillende gebruikers met elkaar te verbinden, dus moeten de betrokken apparaten de functie voor gebruikersdeling inschakelen. Dit is een systeeminstelling die kan worden opgevraagd met een statische methode in de klasse RemoteSystem:

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

Als u deze instelling wilt wijzigen, moet de gebruiker Instellingen openen. In het System>Shared experiences>Share across devices menu, is er een vervolgkeuzelijst waarin de gebruiker kan opgeven met welke apparaten het systeem kan delen.

pagina met instellingen voor gedeelde ervaringen

De benodigde naamruimten opnemen

Als u alle codefragmenten in deze handleiding wilt gebruiken, hebt u de volgende using instructies nodig in uw klassebestand(en).

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

Een externe sessie maken

Als u een instantie van een externe sessie wilt maken, moet u beginnen met een RemoteSystemSessionController-object. Gebruik het volgende framework om een nieuwe sessie te maken en joinaanvragen van andere apparaten af te handelen.

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

Maak een externe sessie alleen op uitnodiging toegankelijk

Als u wilt voorkomen dat uw externe sessie openbaar kan worden gedetecteerd, kunt u deze alleen uitnodigen. Alleen de apparaten die een uitnodiging ontvangen, kunnen joinaanvragen verzenden.

De procedure is meestal hetzelfde als hierboven, maar wanneer u het RemoteSystemSessionController-exemplaar maakt, geeft u een geconfigureerd RemoteSystemSessionOptions-object door.

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

//...

Als u een uitnodiging wilt verzenden, moet u een verwijzing hebben naar het ontvangende externe systeem (verkregen via normale externe systeemdetectie). Geef deze verwijzing door aan de methode SendInvitationAsync van het sessieobject. Alle deelnemers in een sessie hebben een verwijzing naar de externe sessie (zie de volgende sectie), zodat elke deelnemer een uitnodiging kan verzenden.

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

Een externe sessie detecteren en eraan deelnemen

Het proces van het detecteren van externe sessies wordt afgehandeld door de klasse RemoteSystemSessionWatcher en is vergelijkbaar met het detecteren van afzonderlijke externe systemen.

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

Wanneer een RemoteSystemSessionInfo-exemplaar wordt verkregen, kan deze worden gebruikt om een joinaanvraag uit te geven aan het apparaat dat de bijbehorende sessie beheert. Een geaccepteerde join-aanvraag retourneert asynchroon een RemoteSystemSessionJoinResult-object dat een verwijzing naar de gekoppelde sessie bevat.

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

Een apparaat kan tegelijkertijd aan meerdere sessies worden toegevoegd. Daarom kan het wenselijk zijn om de samenvoegfunctionaliteit te scheiden van de werkelijke interactie met elke sessie. Zolang een verwijzing naar de RemoteSystemSession exemplaar in de app wordt onderhouden, kan de communicatie via die sessie worden uitgevoerd.

Berichten en gegevens delen via een externe sessie

Berichten ontvangen

U kunt berichten en gegevens uitwisselen met andere deelnemersapparaten in de sessie met behulp van een RemoteSystemSessionMessageChannel-exemplaar , dat één communicatiekanaal voor de hele sessie vertegenwoordigt. Zodra deze is geïnitialiseerd, wordt geluisterd naar binnenkomende berichten.

Opmerking

Berichten moeten worden geserialiseerd en gedeserialiseerd van byte-arrays tijdens het verzenden en ontvangen. Deze functionaliteit is opgenomen in de volgende voorbeelden, maar kan afzonderlijk worden geïmplementeerd voor een betere modulariteit van code. Zie de voorbeeld-app) voor een voorbeeld hiervan.

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

Berichten verzenden

Wanneer het kanaal tot stand is gebracht, is het verzenden van een bericht naar alle sessiedeelnemers eenvoudig.

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

Als u een bericht wilt verzenden naar alleen bepaalde deelnemers, moet u eerst een detectieproces starten om verwijzingen te verkrijgen naar de externe systemen die deelnemen aan de sessie. Dit is vergelijkbaar met het proces van het detecteren van externe systemen buiten een sessie. Gebruik een RemoteSystemSessionParticipantWatcher-exemplaar om de deelnemersapparaten van een sessie te vinden.

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

Wanneer een lijst met verwijzingen naar sessiedeelnemers wordt verkregen, kunt u een bericht verzenden naar een willekeurige set deelnemers.

Als u een bericht wilt verzenden naar één deelnemer (idealiter door de gebruiker geselecteerd op het scherm), geeft u de verwijzing door aan een methode zoals hieronder.

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

Als u een bericht wilt verzenden naar meerdere deelnemers (idealiter door de gebruiker geselecteerd op het scherm), voegt u deze toe aan een lijstobject en geeft u de lijst door aan een methode zoals hieronder.

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