Desenvolvimento do Windows 10 - Serviços

Neste capítulo, aprenderemos como os aplicativos UWP podem ajudar ou fornecer serviços para outros aplicativos da Plataforma Universal do Windows (UWP). Na verdade, este capítulo é uma extensão do capítuloBackground execution e é um caso especial disso.

  • No Windows 10, um serviço de aplicativo é uma forma ou mecanismo de um aplicativo fornecer serviços a outros aplicativos.

  • Um serviço de aplicativo funciona na forma de uma tarefa em segundo plano.

  • Os aplicativos em primeiro plano podem chamar um serviço de aplicativo em outro aplicativo para realizar tarefas em segundo plano.

Os serviços de aplicativos são como os serviços da Web, mas os serviços de aplicativos são usados ​​no dispositivo Windows 10.

Os aplicativos da Plataforma Universal do Windows (UWP) podem interagir com outro aplicativo UWP de várias maneiras -

  • Associação de URI usando LaunchUriAsync
  • Associação de arquivo usando LaunchFileAsync
  • Lance para resultados usando LaunchUriForResultsAsync
  • Serviços de aplicativos

As três primeiras maneiras são usadas quando ambos os aplicativos estão em primeiro plano, mas os serviços de aplicativos são usados ​​em background task e, nesse caso, o aplicativo cliente deve estar em primeiro plano e disponível para usar o serviço de aplicativo.

Os serviços de aplicativos são muito benéficos em aplicativos onde serviços não visuais são fornecidos, por exemplo, um leitor de código de barras no qual um aplicativo em primeiro plano obtém a imagem e envia esses bytes aos serviços de aplicativo para identificar o código de barras.

Para entender todos esses conceitos, vamos criar um novo projeto UWP com o nome AppServiceProvider no Microsoft Visual Studio 2015.

Agora no Package.appmenifest arquivo, adicione as seguintes informações.

Para criar um serviço de aplicativo, que pode ser invocado por aplicativos em primeiro plano, vamos adicionar um novo Windows Runtime Projeto de componente para a solução com MyAppService nome, porque os serviços de aplicativo são implementados como uma tarefa em segundo plano.

Adicione uma referência ao MyAppService projeto no AppServiceProvider projeto.

Agora exclua o class1.cs arquivo de MyAppService projeto e adicionar uma nova classe com o nome do inventário, que irá implementar o IBackgrounTask interface.

o IBackgrounTask interface tem apenas um método “Run” que precisa ser implementado para a tarefa em segundo plano.

public sealed class Inventory : IBackgroundTask { 
   public void Run(IBackgroundTaskInstance taskInstance) { 
      
   } 
}

Quando a tarefa em segundo plano é criada, Run() methodé chamado e quando o método Run é concluído, as tarefas em segundo plano são encerradas. Para ficar atento a uma tarefa em segundo plano, para atender a solicitações, o código leva um adiamento.

O código de serviços do aplicativo está em OnRequestedReceived(). Neste exemplo, um índice para um item de estoque passa para o serviço, para recuperar o nome e o preço do item de estoque especificado.

private async void OnRequestReceived(AppServiceConnection sender, 
   AppServiceRequestReceivedEventArgs args) {
      // Get a deferral because we use an awaitable API below to respond to the message 
}

A seguir está a implementação completa da classe Inventory em 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(); 
            } 
      } 
   } 
}

Vamos criar um aplicativo cliente adicionando um novo projeto UWP em branco ClientApp e adicione um botão, uma caixa de texto e dois blocos de texto, conforme mostrado abaixo no arquivo 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>

A seguir, está a implementação do evento de clique de botão em que os serviços de aplicativo são solicitados.

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

Para executar este aplicativo, você precisará definir o ClientApp projeto para ser o projeto de inicialização no Solution Explorer e, em seguida, implantar esta solução de Build > Deploy Solução.

Quando o código acima for compilado e executado, você verá a seguinte janela. Nos serviços de aplicativos, acabamos de adicionar informações de dois itens. Portanto, você pode inserir 0 ou 1 para obter informações sobre esses itens.

Quando você insere 0 e clica no botão, ele executa o serviço de aplicativo como tarefa em segundo plano e mostra as informações do item no textblock.