啟用遠端系統上的應用

singhwong發表於2020-12-22

從build 14393版本開始,UWP應用將支援啟動遠端計算機系統上的應用。要啟動遠端系統上的應用,需要使用RemoteLauncher類,並通過URI來啟用遠端應用。

在呼叫遠端系統上的應用前,必須查詢可用的遠端系統。遠端系統相關的資訊由RemoteSystem類進行封裝。發現遠端系統可以有兩種方法:第一種方法是直接呼叫FindByHostNameAsync方法,通過指定的遠端計算機的名字來查詢;第二種方法是呼叫CreateWatcher方法,建立一個RemoteSystemWatcher例項,最終由該RemoteSystemWatcher例項負責監視遠端系統的連線情況,當有新的遠端系統連入,會發生RemoteSystemAdded事件,當某個已發現的遠端系統被刪除後會發生RemoteSystemRemoved事件。應用程式碼可以處理這些事件來獲取可用的遠端系統。

獲得某個可用的RemoteSystem後,就可以建立RemoteSystemConnectionRequest物件,再把這個RemoteSystemConnectionRequest物件例項傳遞給RemoteLauncher類的LauncherUriAsync方法,就可以啟用遠端系統上的指定應用了。

下面示例將演示這樣的功能:使用者在一臺裝置上(計算機、平板或者XBox等)上執行示例應用,如果介面上顯示可用的遠端裝置,則可以輸入一個URL,然後就可以在另一臺裝置(計算機、平板等)上啟動瀏覽器並開啟該URL所指向的網頁。

具體實現步驟如下:

(1) 新建一個應用程式專案。

(2) 應用介面佈局如下XAML程式碼所示:

    <Grid Margin="20">
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <ListView x:Name="lv" Margin="3" DisplayMemberPath="DisplayName"/>
        <Grid Grid.Row="1" Margin="2">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="auto"/>
                <ColumnDefinition/>
                <ColumnDefinition Width="auto"/>
            </Grid.ColumnDefinitions>
            <TextBlock Text="請輸入一個網址:" VerticalAlignment="Center"/>
            <TextBox x:Name="txtInputUri" Grid.Column="1" Height="30"/>
            <Button Content="在遠端系統上開啟網頁" Grid.Column="2" Margin="5,0,0,2" Tapped="Button_Tapped"/>
        </Grid>
    </Grid>

ListView控制元件負責顯示被發現的遠端系統列表,TextBox控制元件用於輸入要開啟的網頁地址。

(3) 在後臺程式碼中,在類級別宣告兩個私有欄位。

        ObservableCollection<RemoteSystem> remoteSystemCollection = null;
        RemoteSystemWatcher rmSysWatcher = null;

(4) 初始化ObservableCollection<RemoteSystem>集合,並與ListView控制元件進行繫結。

        public MainPage()
        {
            this.InitializeComponent();
            remoteSystemCollection = new ObservableCollection<RemoteSystem>();
            lv.ItemsSource = remoteSystemCollection;
        }

(5) 在查詢遠端系統之前,請必須呼叫一下RequestAccessAsync方法,以確認應用程式是否具有相關的許可權。

            var result = await RemoteSystem.RequestAccessAsync();
            if (result != RemoteSystemAccessStatus.Allowed)
            {
                Debug.WriteLine(result);
                return;
            }

(6) 建立RemoteSystemWatcher物件例項。

            //定義篩選條件
            List<IRemoteSystemFilter> filterList = new List<IRemoteSystemFilter>();
            //發現任何可用的裝置
            RemoteSystemDiscoveryTypeFilter filter1 = new RemoteSystemDiscoveryTypeFilter(RemoteSystemDiscoveryType.Any);
            filterList.Add(filter1);
            //僅發現基於桌面和平板平臺的裝置
            List<string> sysKids = new List<string>();
            sysKids.Add(RemoteSystemKinds.Desktop);
            sysKids.Add(RemoteSystemKinds.Laptop);
            sysKids.Add(RemoteSystemKinds.Phone);
            RemoteSystemKindFilter filter2 = new RemoteSystemKindFilter(sysKids);
            filterList.Add(filter2);
            //建立用於發現遠端系統的相關物件
            rmSysWatcher = RemoteSystem.CreateWatcher();
            rmSysWatcher.RemoteSystemAdded += OnRemoteSysAdded;
            rmSysWatcher.RemoteSystemRemoved += OnRemoteSysRemoved;
            rmSysWatcher.Start();

UWP提供了一些篩選器,可以在查詢遠端系統時進行過濾,主要有以下幾種:

  • RemoteSystemKindFilter 表示遠端系統型別,例如桌面(Desktop)、平板、XBox裝置等。
  • RemoteSystemDiscoveryTypeFilter 表示以發現範圍來查詢遠端系統,如Proximal為通過本地網路或藍芽連線來查詢。
  • RemoteSystemStatusTypeFilter 表示通過可用狀態來查詢,如Any表示查詢所有遠端系統,Available表示只查詢可以順利連線的遠端系統。

(7) 處理RemoteSystemWatcher例項的相關事件,以獲取被查詢到的遠端系統。

        async void OnRemoteSysAdded(RemoteSystemWatcher sender,RemoteSystemAddedEventArgs args)
        {
            await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal,()=>
            {
                //將新發現的遠端系統新增到列表中
                remoteSystemCollection.Add(args.RemoteSystem);
            });
        }
        async void OnRemoteSysRemoved(RemoteSystemWatcher sender,RemoteSystemRemovedEventArgs args)
        {
            await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal,()=>
            {
                //從列表中刪除遠端系統
                RemoteSystem rmsys = remoteSystemCollection.FirstOrDefault(r=>r.Id == args.RemoteSystemId);
                if (rmsys != null)
                {
                    remoteSystemCollection.Remove(rmsys);
                }
            });
        }

由於RemoteSystemWatcher物件是從非UI執行緒引發事件的,所以,在處理事件時,如果要訪問UI元素,必須通過CoreDispatcher類的RunAsync方法來間接執行。

(8) 呼叫Start方法就可以開始查詢遠端系統了。

            rmSysWatcher.Start();

(9) 下面程式碼將處理按鈕的Tapped事件來啟用遠端系統中的應用。

        private async void Button_Tapped(object sender, TappedRoutedEventArgs e)
        {
            RemoteSystem rmSystem = lv.SelectedItem as RemoteSystem;
            RemoteSystemConnectionRequest request = new RemoteSystemConnectionRequest(rmSystem);
            Uri targetUri = new Uri(txtInputUri.Text.Trim());
            var res = await RemoteLauncher.LaunchUriAsync(request,targetUri);
            if (res == RemoteLaunchUriStatus.Success)
            {
                // To do.
            }
            else
            {
                // To do.
            }
        }

呼叫RemoteLauncher.LauncherUriAsync方法之前,需要一個RemoteSystemConnectionRequest例項,而RemoteSystemConnectionRequest例項將根據所選定的RemoteSystem物件來建立。

(10) 開啟清單檔案,新增Remote System的功能宣告。具體的XML程式碼是在Package/Capabilities節點下新增以下元素:

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

uap3是一個XML名稱空間的字首,在Package節點上通過以下宣告來引入:

  xmlns:uap3="http://schemas.microsoft.com/appx/manifest/uap/windows10/3"

這個XML名稱空間必須引入,因為Name="remoteSystem"的Capability元素是在這個名稱空間下定義的,如果不引入會導致錯誤。新增remoteSystem功能宣告告訴作業系統,將允許應用程式訪問遠端系統上的應用程式。

要測試該示例,必須啟動另一臺執行了Windows 10作業系統的裝置,並且系統必須是build 14393或以上版本(代號為"紅石")。當示例成功執行後,會顯示查詢到的遠端裝置的名字。

選擇一臺遠端裝置,然後在文字框中輸入MSDN的主頁地址(MSDN),然後單擊按鈕。

隨後會在另一臺裝置上啟動瀏覽器,並導航到MSDN主頁。(由於本人沒有另一臺Win10裝置,該示例未測試)

 

相關文章