透過遠端工作階段連接裝置
遠端工作階段功能可讓應用程式透過工作階段連線到其他裝置,無論是用於明確應用程式傳訊,還是系統管理資料的代理交換,例如 Windows Holographic 裝置之間用於全像共用的 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);
}