启动远程设备上的应用Launch an app on a remote device

本文介绍了如何启动远程设备上的 Windows 应用。This article explains how to launch a Windows app on a remote device.

从 Windows 10 版本 1607 开始,UWP 应用可以远程启动另一台同样也运行 Windows 10 版本 1607 或更高版本的设备上的 UWP 应用或 Windows 桌面应用程序,只要这两台设备都使用相同的 Microsoft 帐户 (MSA) 登录。Starting in Windows 10, version 1607, a UWP app can launch a UWP app or Windows desktop application remotely on another device that is also running Windows 10, version 1607 or later, provided that both devices are signed on with the same Microsoft Account (MSA). 这是 Project Rome 最简单的用例。This is the simplest use case of Project Rome.

远程启动功能支持面向任务的用户体验,用户可以在一台设备上启动任务并在另一台设备上完成。The remote launch feature enables task-oriented user experiences; a user can start a task on one device and finish it on another. 例如,如果用户在他们的汽车里用手机听音乐,他们可以到家后在 Xbox One 上接着播放。For example, if the user is listening to music on their phone in their car, they could then hand playback functionality over to their Xbox One when they arrive at home. 远程启动允许应用将上下文数据传递给启动的远程应用,以便从任务结束的位置继续执行。Remote launch allows apps to pass contextual data to the remote app being launched, in order to pick up where the task was left off.

初步设置Preliminary setup

添加 RemoteSystem 功能Add the remoteSystem capability

为了让你的应用启动远程设备上的应用,必须将 remoteSystem 功能添加到应用包清单。In order for your app to launch an app on a remote device, you must add the remoteSystem capability to your app package manifest. 你可以使用包清单设计器通过选择 "功能" 选项卡上的 "远程系统" 来添加它,也可以手动将以下行添加到项目的_appxmanifest.xml_文件。You can use the package manifest designer to add it by selecting Remote System on the Capabilities tab, or you can manually add the following line to your project's Package.appxmanifest file.

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

启用跨设备共享Enable cross-device sharing

此外,客户端设备必须设置为允许跨设备共享。Additionally, the client device must be set to allow cross-device sharing. 此设置可以在设置系统 > 共享体验 > 跨设备共享中进行访问,默认情况下处于启用状态。This setting, which is accessed in Settings: System > Shared experiences > Share across devices, is enabled by default.

共享体验设置页面

查找远程设备Find a remote device

必须先查找要连接的设备。You must first find the device that you want to connect with. 发现远程设备详细讨论了如何执行此操作。Discover remote devices discusses how to do this in detail. 此处我们将使用简单的方法,将不按设备或连接类型进行筛选。We'll use a simple approach here that forgoes filtering by device or connectivity type. 我们将创建用于查找远程设备的远程系统观察程序,并编写处理程序,用于在发现或删除设备时引发的事件。We will create a remote system watcher that looks for remote devices, and write handlers for the events that are raised when devices are discovered or removed. 这将向我们提供远程设备集合。This will provide us with a collection of remote devices.

这些示例中的代码要求类文件中具有 using Windows.System.RemoteSystems 语句。The code in these examples requires that you have a using Windows.System.RemoteSystems statement in your class file(s).

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()The first thing you must do before making a remote launch is call RemoteSystem.RequestAccessAsync(). 检查返回值以确保你的应用可以访问远程设备。Check the return value to make sure your app is allowed to access remote devices. 此检查可能失败的原因之一是未将 remoteSystem 功能添加到应用。One reason this check could fail is if you haven't added the remoteSystem capability to your app.

当发现可以连接的设备或此类设备不再可用时,调用系统观察程序事件处理程序。The system watcher event handlers are called when a device that we can connect with is discovered or is no longer available. 我们将使用这些事件处理程序来保持可连接的设备更新列表。We will use these event handlers to keep an updated list of devices that we can connect to.

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

我们将使用字典按远程系统 ID 跟踪设备。We will track the devices by remote system ID using a Dictionary. ObservableCollection 用于保存我们可以枚举的设备列表。An ObservableCollection is used to hold the list of devices that we can enumerate. 借助 ObservableCollection,还可以轻松将设备列表绑定到 UI,不过在该示例中我们不会执行此操作。An ObservableCollection also makes it easy to bind the list of devices to UI, though we won't do that in this example.

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

尝试启动远程应用前,在应用启动代码中添加对 BuildDeviceList() 的调用。Add a call to BuildDeviceList() in your app startup code before you attempt to launch a remote app.

启动远程设备上的应用Launch an app on a remote device

通过将希望连接的设备传递给 RemoteLauncher.LaunchUriAsync API,远程启动应用。Launch an app remotely by passing the device you wish to connect with to the RemoteLauncher.LaunchUriAsync API. 此方法有三个重载。There are three overloads for this method. 最简单的重载(即该示例中所演示的重载)用于指定将激活远程设备上的应用的 URI。The simplest, which this example demonstrates, specifies the URI that will activate the app on the remote device. 在该示例中,URI 将打开远程计算机上具有三维太空针塔视图的“地图”应用。In this example the URI opens the Maps app on the remote machine with a 3D view of the Space Needle.

其他 RemoteLauncher.LaunchUriAsync 重载允许你指定网站 URI 之类的选项,以便查看是否没有合适的应用在远程设备上启动,以及可用于启动远程设备上 URI 的程序包系列名称的可选列表。Other RemoteLauncher.LaunchUriAsync overloads allow you to specify options such as the URI of the web site to view if no appropriate app can be launched on the remote device, and an optional list of package family names that could be used to launch the URI on the remote device. 也可以采用键/值对的形式提供数据。You can also provide data in the form of key/value pairs. 可以将数据传递给正在激活的应用,以便为远程应用提供上下文,例如将播放的歌曲名称,以及将播放从一台设备转移到另一台设备时的当前播放位置。You might pass data to the app you are activating to provide context to the remote app, such as the name of the song to play and the current playback location when you hand off playback from one device to another.

在实际情况下,可能会提供 UI 以选择你要面向的设备。In practical scenarios, you might provide UI to select the device you want to target. 但为了简化该示例,我们将只使用列表中的第一个远程设备。But to simplify this example, we'll just use the first remote device on the list.

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 对象提供有关远程启动是否成功以及失败原因(如果失败)的信息。The RemoteLaunchUriStatus object that is returned from RemoteLauncher.LaunchUriAsync() provides information about whether the remote launch succeeded, and if not, the reason why.

远程系统 API 参考Remote Systems API reference
已连接的应用和设备 (项目罗马) 概述Connected apps and devices (Project Rome) overview
发现远程设备Discover remote devices
远程系统示例演示了如何发现远程系统、在远程系统上启动应用,以及使用应用服务在运行在两个系统上的应用之间发送消息。Remote Systems sample demonstrates how to discover a remote system, launch an app on a remote system, and use app services to send messages between apps running on two systems.