リモート セッション機能を使用すると、明示的なアプリ メッセージングや、Windows Holographic デバイス間のホログラフィック共有のための SpatialEntityStore などのシステムマネージド データの仲介型交換のために、セッションを介して他のデバイスに接続できます。
リモート セッションは任意の Windows デバイスで作成でき、他のユーザーがサインインしたデバイスも含め、任意の Windows デバイスが参加を要求できます (ただし、セッションには招待専用の可視性を持つことができます)。 このガイドでは、リモート セッションを利用するすべての主要なシナリオの基本的なサンプル コードを提供します。 このコードは、既存のアプリ プロジェクトに組み込み、必要に応じて変更できます。 エンド ツー エンドの実装については、Quiz Game サンプル アプリのを参照してください。
準備中のセットアップ
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.
}
}
1 つのデバイスを同時に複数のセッションに参加させることができます。 このため、結合機能を各セッションとの実際の対話から分離することが望ましい場合があります。 RemoteSystemSession インスタンスへの参照がアプリで維持されている限り、そのセッションで通信を試みることができます。
リモート セッションを介してメッセージとデータを共有する
メッセージを受信する
1 つのセッション全体の通信チャネルを表す 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();
}
セッション参加者への参照の一覧が取得されたら、任意のセットにメッセージを送信できます。
1 人の参加者にメッセージを送信するには (ユーザーが画面上で選択するのが理想的です)、次のようなメソッドに参照を渡すだけです。
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);
}
関連トピック
- 接続されたアプリとデバイス (Project Rome)
- リモート システム API リファレンス