共用方式為


透過遠端會話連接裝置

遠程會話功能可讓應用程式透過會話連接到其他裝置,無論是用於明確的應用程式傳訊,還是用於系統管理數據的代理交換,例如 Windows 全像裝置之間的 SpatialEntityStore 進行全像共享。

遠程會話可由任何 Windows 裝置建立,而任何 Windows 裝置都可以要求加入(雖然會話可以具有僅限邀請可見度),包括其他使用者登入的裝置。 本指南提供使用遠程會話之所有主要案例的基本範例程序代碼。 此程式代碼可以併入現有的應用程式專案,並視需要加以修改。 如需端對端實作,請參閱 測驗遊戲範例應用程式

初步設定

新增 remoteSystem 功能

為了讓應用程式在遠端裝置上啟動應用程式,您必須將 remoteSystem 功能新增至應用程式套件指令清單。 您可以使用套件指令清單設計工具,在 [功能] 標籤上選取 [遠端系統] 來新增它,或者,您也可以手動將以下行新增至專案的 Package.appxmanifest 檔案。

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

在裝置上啟用跨使用者探索

遠端會話適用於連線多個不同的使用者,因此涉及的裝置必須啟用跨用戶共用。 這是可以使用 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".
}

若要變更此設定,使用者必須開啟 [設定]。系統>共用體驗>跨裝置共用 選單,有一個下拉式方塊,使用者可以指定其系統可以共用的裝置。

共用體驗設定頁面

包含必要的命名空間

若要使用本指南中的所有代碼段,您需要類別檔案中的下列 using 語句。

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

建立遠端會話

若要建立遠程會話實例,您必須從 RemoteSystemSessionController 對象開始。 使用下列架構來建立新的會話,並處理來自其他裝置的聯結要求。

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

將遠端會話設為僅限受邀者

如果您希望防止遠端會話被他人公開發現,可以設為僅限邀請模式。 只有接收邀請的裝置才能傳送加入要求。

此程式大多與上述程式相同,但在建構 RemoteSystemSessionController 實例時,您會傳入已設定的 RemoteSystemSessionOptions 物件。

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

//...

若要發送邀請,您必須具有接收遠端系統的參考點(透過正常的遠端系統探索取得)。 只要將此參考傳遞至會話物件的 SendInvitationAsync 方法。 在一次會話中,所有參與者都有到這個遠端會話的連結(請參閱下一節),所以任何參與者都可以發送邀請。

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

探索並加入遠端會話

探索遠端會話的程式是由 RemoteSystemSessionWatcher 類別處理,類似於探索個別遠端系統。

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

取得 RemoteSystemSessionInfo 實例時,可用來對控制對應會話的裝置發出聯結要求。 接受的加入要求將以異步方式返回一個 RemoteSystemSessionJoinResult 物件,其中包含已加入會話的參考。

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

裝置可以同時加入多個會話。 基於這個理由,建議您將聯結功能與每個會話的實際互動區隔開。 只要在應用程式中維護 RemoteSystemSession 實例參考,就可以嘗試在該工作階段中進行通訊。

透過遠端會話共用訊息和數據

接收訊息

您可以使用 RemoteSystemSessionMessageChannel 實例,來與會話中的其他參與者裝置交換訊息和數據,此實例代表單一會話範圍的通道。 一旦初始化,就會開始接聽傳入訊息。

備註

訊息在傳送和接收時,必須從位元組陣列進行序列化和反序列化。 這項功能包含在下列範例中,但可以個別實作,以提升程式代碼模組化。 如需此範例,請參閱 範例應用程式

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

傳送訊息

建立通道時,傳送訊息給所有會話參與者很簡單。

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

若要只將訊息傳送給特定參與者,您必須先起始探索程式,以取得參與會話之遠端系統的參考。 這類似於在工作階段外發現遠端系統的過程。 使用 RemoteSystemSessionParticipantWatcher 實例來尋找會話的參與者裝置。

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

取得會話參與者參考清單後,您可以將訊息傳送至其中的任一組。

若要將訊息傳送給單一參與者(理想情況下由使用者在螢幕上選取),只要將參考傳遞至如下所示的方法即可。

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

若要將訊息傳送給多個參與者(理想情況下是由使用者在畫面上選取的參與者),請將這些參與者新增至清單物件,並將該清單傳入如下的方法。

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