В этой главе мы узнаем о том, как приложения UWP могут помогать или предоставлять услуги другим приложениям универсальной платформы Windows (UWP). На самом деле, эта глава является расширением главы Фоновое выполнение и является ее частным случаем.
-
В Windows 10 служба приложений — это способ или механизм, позволяющий приложению предоставлять службы другим приложениям.
-
Служба приложения работает в виде фоновой задачи.
-
Приложения Foreground могут вызывать службу приложений в другом приложении для выполнения задач в фоновом режиме.
В Windows 10 служба приложений — это способ или механизм, позволяющий приложению предоставлять службы другим приложениям.
Служба приложения работает в виде фоновой задачи.
Приложения Foreground могут вызывать службу приложений в другом приложении для выполнения задач в фоновом режиме.
Сервисы приложений похожи на веб-сервисы, но сервисы приложений используются на устройстве с Windows 10.
Приложения универсальной платформы Windows (UWP) могут взаимодействовать с другим приложением UWP различными способами —
- Сопоставление URI с использованием LaunchUriAsync
- Связывание файлов с использованием LaunchFileAsync
- Запуск для результатов с помощью LaunchUriForResultsAsync
- Сервисы приложений
Первые три способа используются, когда оба приложения находятся на переднем плане, но службы приложений используются в фоновом режиме, и в этом случае клиентское приложение должно быть на переднем плане и доступно для использования службы приложений.
Сервисы приложений очень полезны в приложениях, где предоставляются невизуальные сервисы, например, сканер штрих-кода, в котором приложение на переднем плане берет изображение и отправляет эти байты сервисам приложения для идентификации штрих-кода.
Чтобы понять все эти концепции, давайте создадим новый проект UWP с именем AppServiceProvider в Microsoft Visual Studio 2015.
Теперь в файле Package.appmenifest добавьте следующую информацию.
Чтобы создать службу приложения, которая может вызываться приложениями переднего плана, добавим в решение новый проект компонента среды выполнения Windows с именем MyAppService , поскольку службы приложения реализованы в виде фоновой задачи.
Добавьте ссылку на проект MyAppService в проекте AppServiceProvider .
Теперь удалите файл class1.cs из проекта MyAppService и добавьте новый класс с именем инвентаря, который будет реализовывать интерфейс IBackgrounTask .
Интерфейс IBackgrounTask имеет только один метод «Выполнить», который необходимо реализовать для фоновой задачи.
public sealed class Inventory : IBackgroundTask { public void Run(IBackgroundTaskInstance taskInstance) { } }
При создании фоновой задачи вызывается метод Run (), а после завершения метода Run фоновые задачи завершаются. Чтобы не отставать от фоновой задачи, обслуживать запросы, код требует отсрочки.
Код служб приложения находится в OnRequestedReceived () . В этом примере индекс для элемента инвентаря передается службе, чтобы получить имя и цену указанного элемента инвентаря.
private async void OnRequestReceived(AppServiceConnection sender, AppServiceRequestReceivedEventArgs args) { // Get a deferral because we use an awaitable API below to respond to the message }
Ниже приведена полная реализация класса Inventory в C #.
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Windows.ApplicationModel.AppService; using Windows.ApplicationModel.Background; using Windows.Foundation.Collections; namespace MyAppService{ public sealed class Inventory : IBackgroundTask { private BackgroundTaskDeferral backgroundTaskDeferral; private AppServiceConnection appServiceconnection; private String[] inventoryItems = new string[] { "Robot vacuum", "Chair" }; private double[] inventoryPrices = new double[] { 129.99, 88.99 }; public void Run(IBackgroundTaskInstance taskInstance) { this.backgroundTaskDeferral = taskInstance.GetDeferral(); taskInstance.Canceled += OnTaskCanceled; var details = taskInstance.TriggerDetails as AppServiceTriggerDetails; appServiceconnection = details.AppServiceConnection; appServiceconnection.RequestReceived += OnRequestReceived; } private async void OnRequestReceived(AppServiceConnection sender, AppServiceRequestReceivedEventArgs args) { var messageDeferral = args.GetDeferral(); ValueSet message = args.Request.Message; ValueSet returnData = new ValueSet(); string command = message["Command"] as string; int? inventoryIndex = message["ID"] as int?; if (inventoryIndex.HasValue && inventoryIndex.Value >= 0 && inventoryIndex.Value < inventoryItems.GetLength(0)) { switch (command) { case "Price": { returnData.Add("Result", inventoryPrices[inventoryIndex.Value]); returnData.Add("Status", "OK"); break; } case "Item": { returnData.Add("Result", inventoryItems[inventoryIndex.Value]); returnData.Add("Status", "OK"); break; } default: { returnData.Add("Status", "Fail: unknown command"); break; } } else { returnData.Add("Status", "Fail: Index out of range"); } } await args.Request.SendResponseAsync(returnData); messageDeferral.Complete(); } private void OnTaskCanceled(IBackgroundTaskInstance sender, BackgroundTaskCancellationReason reason){ if (this.backgroundTaskDeferral != null) { // Complete the service deferral. this.backgroundTaskDeferral.Complete(); } } } }
Давайте создадим клиентское приложение, добавив новый пустой UWP-проект ClientApp и добавив одну кнопку, одно текстовое поле и два текстовых блока, как показано ниже в файле XAML.
<Page x:Class = "ClientApp.MainPage" xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local = "using:ClientApp" xmlns:d = "http://schemas.microsoft.com/expression/blend/2008" xmlns:mc = "http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable = "d"> <Grid Background = "{ThemeResource ApplicationPageBackgroundThemeBrush}"> <TextBlock HorizontalAlignment = "Left" Text = "Enter Item No." Margin = "52,40,0,0" TextWrapping = "Wrap" VerticalAlignment = "Top" Height = "32" Width = "268"/> <Button x:Name = "button" Content = "Get Info" HorizontalAlignment = "Left" Margin = "255,96,0,0" VerticalAlignment = "Top" Click = "button_Click"/> <TextBox x:Name = "textBox" HorizontalAlignment = "Left" Margin = "52,96,0,0" TextWrapping = "Wrap" VerticalAlignment = "Top" Width = "168"/> <TextBlock x:Name = "textBlock" HorizontalAlignment = "Left" Margin = "52,190,0,0" TextWrapping = "Wrap" VerticalAlignment = "Top" Height = "32" Width = "268"/> </Grid> </Page>
Ниже приведена реализация события нажатия кнопки, при которой запрашиваются службы приложения.
using System; using Windows.ApplicationModel.AppService; using Windows.Foundation.Collections; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; // The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x409 namespace ClientApp { /// <summary> /// An empty page that can be used on its own or navigated to within a Frame. /// </summary> public sealed partial class MainPage : Page { private AppServiceConnection inventoryService; public MainPage() { this.InitializeComponent(); } private async void button_Click(object sender, RoutedEventArgs e){ // Add the connection. if (this.inventoryService == null) { this.inventoryService = new AppServiceConnection(); this.inventoryService.AppServiceName = "com.microsoft.inventory"; this.inventoryService.PackageFamilyName = "bb1a8478-8005-46869923-e525ceaa26fc_4sz2ag3dcq60a"; var status = await this.inventoryService.OpenAsync(); if (status != AppServiceConnectionStatus.Success) { button.Content = "Failed to connect"; return; } } // Call the service. int idx = int.Parse(textBox.Text); var message = new ValueSet(); message.Add("Command", "Item"); message.Add("ID", idx); AppServiceResponse response = await this.inventoryService.SendMessageAsync(message); string result = ""; if (response.Status == AppServiceResponseStatus.Success) { // Get the data that the service sent to us. if (response.Message["Status"] as string == "OK") { result = response.Message["Result"] as string; } } message.Clear(); message.Add("Command", "Price"); message.Add("ID", idx); response = await this.inventoryService.SendMessageAsync(message); if (response.Status == AppServiceResponseStatus.Success){ // Get the data that the service sent to us. if (response.Message["Status"] as string == "OK") { result += " : Price = " + "$"+ response.Message["Result"] as string; } } textBlock.Text = result; } } }
Чтобы запустить это приложение, вам нужно установить проект ClientApp в качестве запускаемого проекта в обозревателе решений, а затем развернуть это решение из меню «Сборка»> «Развернуть решение».
Когда приведенный выше код скомпилирован и выполнен, вы увидите следующее окно. В сервисы приложений мы только что добавили информацию о двух элементах. Таким образом, вы можете ввести 0 или 1, чтобы получить информацию об этих элементах.
Когда вы вводите 0 и нажимаете кнопку, он запускает службу приложений в качестве фоновой задачи и отображает информацию об элементе в текстовом блоке .