リモート デバイスでのアプリの起動

この記事では、Windows アプリをリモート デバイスで起動する方法について説明します。

Windows 10 Version 1607 以降で実行される UWP アプリは、同じく Windows Version 1607 を実行し、同じ Microsoft アカウント (MSA) にサインオンしている別のデバイスの UWP アプリまたは Windows デスクトップ アプリケーションをリモートで起動できます。 これは Project Rome の最も簡単な使用例です。

このリモート起動機能を使うと、ユーザーが 1 台のデバイスでタスクを開始し、別のデバイスでそのタスクを完了するといった、タスク指向のユーザー エクスペリエンスが実現します。 たとえば、車を運転しながらスマートフォンで音楽を聴き、自宅に着いた後は、機器を Xbox One に切り替えて同じ音楽を引き続き再生することができます。 リモート起動では、中断した箇所からタスクを続行できるように、起動するリモート アプリにコンテキスト データを渡します。

準備段階のセットアップ

remoteSystem 機能を追加する

アプリでリモート デバイスのアプリを起動するには、remoteSystem 機能をアプリ パッケージ マニフェストに追加する必要があります。 これには、マニフェスト デザイナーで [機能] タブの [リモート システム] を選んで追加するか、プロジェクトの Package.appxmanifest ファイルに以下のコードを手動で追加します。

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

クロスデバイス共有を実現

さらに、クライアントデバイスは、デバイス間の共有を許可するように設定する必要があります。 この設定には [設定] : [システム]>[共有エクスペリエンス]>[デバイス間で共有します] でアクセスできます。既定で有効になっています。

[共有エクスペリエンス] 設定ページ

リモート デバイスを見つける

最初に、接続するデバイスを見つける必要があります。 この方法については、「リモート デバイスの検出」で詳しく説明されています。 ここでは、デバイスまたは接続の種類によるフィルタリングを避けた、シンプルなアプローチを使います。 つまり、リモート デバイスを探すリモート システム ウォッチャーを作成し、デバイスが検出または削除されたときに発生するイベントのハンドラーを記述します。 これにより、リモート デバイスのコレクションが提供されます。

この例のコードでは、クラス ファイルに using Windows.System.RemoteSystems ステートメントがあることを利用としています。

private async Task BuildDeviceList()
{
    RemoteSystemAccessStatus accessStatus = await RemoteSystem.RequestAccessAsync();

    if (accessStatus == RemoteSystemAccessStatus.Allowed)
    {
        m_remoteSystemWatcher = RemoteSystem.CreateWatcher();

        // Subscribing to the event raised when a new remote system is found by the watcher.
        m_remoteSystemWatcher.RemoteSystemAdded += RemoteSystemWatcher_RemoteSystemAdded;

        // Subscribing to the event raised when a previously found remote system is no longer available.
        m_remoteSystemWatcher.RemoteSystemRemoved += RemoteSystemWatcher_RemoteSystemRemoved;

        m_remoteSystemWatcher.Start();
    }
}

リモート起動を作成する前に、最初に RemoteSystem.RequestAccessAsync() を呼び出す必要があります。 戻り値を確認して、お使いのアプリがリモート デバイスにアクセスする許可を持っていることを確認してください。 このチェックが失敗する理由の 1 つは、アプリに remoteSystem 機能を追加していないことです。

システム ウォッチャーのイベント ハンドラーは、接続可能なデバイスが検出されたとき、または接続できなくなったときに呼び出されます。 これらのイベント ハンドラーを使用して、接続可能なデバイスの一覧を最新に保ちます。

private void RemoteSystemWatcher_RemoteSystemRemoved(
    RemoteSystemWatcher sender, RemoteSystemRemovedEventArgs args)
{
    if ( m_deviceMap.ContainsKey(args.RemoteSystemId))
    {
        m_deviceList.Remove(m_deviceMap[args.RemoteSystemId]);
        m_deviceMap.Remove(args.RemoteSystemId);
    }
}

private void RemoteSystemWatcher_RemoteSystemAdded(
    RemoteSystemWatcher sender, RemoteSystemAddedEventArgs args)
{
    m_deviceList.Add(args.RemoteSystem);
    m_deviceMap.Add(args.RemoteSystem.Id, args.RemoteSystem);
}

Dictionary を使って、リモート システム ID によってデバイスを追跡します。 ObservableCollection を使って、列挙可能なデバイスの一覧を保持します。 ObservableCollection ではデバイスの一覧を UI にバインドすることも簡単にできますが、この例では行いません。

private RemoteSystemWatcher m_remoteSystemWatcher;
private ObservableCollection<RemoteSystem> m_deviceList = new ObservableCollection<RemoteSystem>();
private Dictionary<string, RemoteSystem> m_deviceMap = new Dictionary<string, RemoteSystem>();

リモート アプリの起動を試みる前に、アプリのスタートアップ コードに BuildDeviceList() への呼び出しを追加します。

リモート デバイスでのアプリの起動

接続するデバイスを RemoteLauncher.LaunchUriAsync API に渡すことによって、アプリをリモートで起動します。 このメソッドには 3 つのオーバーロードがあります。 この例で示されている最も単純なオーバーロードでは、リモート デバイス上のアプリをアクティブ化する URI を指定します。 この例では、URI によって、リモート コンピューター上のマップ アプリがスペース ニードルの 3D ビューで開かれます。

その他の RemoteLauncher.LaunchUriAsync のオーバーロードでは、適切なアプリがリモート デバイスで起動できない場合に参照する Web サイトの URI などのオプションや、リモート デバイスでの URI の起動に使用できるパッケージ ファミリ名のオプションの一覧を指定できます。 キーと値のペアの形式でデータを提供することもできます。 音楽の再生をデバイスから別のデバイスへと切り替えるとき、アクティブ化しているアプリにデータを渡して、再生する曲名や現在の再生位置などのコンテキストをリモート アプリに提供する場合があります。

実際には、使用するデバイスを選ぶための UI を表示するのが普通です。 しかしこの例では単純にするために、一覧の最初のリモート デバイスのみを使います。

if ( m_deviceList.Count > 0)
{
    RemoteSystem SelectedDevice = m_deviceList[0];
    RemoteLaunchUriStatus launchUriStatus = 
        await RemoteLauncher.LaunchUriAsync(
            new RemoteSystemConnectionRequest(SelectedDevice), 
            new Uri("bingmaps:?cp=47.6204~-122.3491&sty=3d&rad=200&pit=75&hdg=165"));
}

RemoteLauncher.LaunchUriAsync() から返される RemoteLaunchUriStatus オブジェクトは、リモートの起動が成功したかどうか、さらに、失敗した場合はその理由についての情報を提供します。

リモート システムの API リファレンス
接続されるアプリやデバイス (Rome プロジェクト) の概要
リモート デバイスの検出
リモート システムのサンプルでは、リモート システムを検出する方法、リモート システムでアプリを起動する方法、アプリ サービスを使って 2 つのシステム上で実行しているアプリ間でメッセージを送信する方法が説明されています。