Sviluppo di Windows 10 - Servizi

In questo capitolo apprenderemo come le app UWP possono aiutare o fornire servizi ad altre applicazioni UWP (Universal Windows Platform). In realtà, questo capitolo è un'estensione del capitoloBackground execution ed è un caso speciale di esso.

  • In Windows 10, un servizio app è un modo o un meccanismo con cui un'app fornisce servizi ad altre app.

  • Un servizio app funziona sotto forma di un'attività in background.

  • Le app in primo piano possono chiamare un servizio app in un'altra app per eseguire attività in background.

I servizi app sono come i servizi Web, ma i servizi app vengono utilizzati sul dispositivo Windows 10.

Le applicazioni UWP (Universal Windows Platform) possono interagire con un'altra applicazione UWP in vari modi:

  • Associazione URI tramite LaunchUriAsync
  • Associazione di file tramite LaunchFileAsync
  • Avvia per i risultati utilizzando LaunchUriForResultsAsync
  • Servizi app

I primi tre modi vengono utilizzati quando entrambe le applicazioni sono in primo piano, ma i servizi app vengono utilizzati in background task e in tal caso l'applicazione client deve essere in primo piano e disponibile per utilizzare il servizio app.

I servizi di app sono molto utili nelle applicazioni in cui vengono forniti servizi non visivi, ad esempio uno scanner di codici a barre in cui un'app in primo piano acquisirà l'immagine e invierà quei byte ai servizi dell'app per identificare il codice a barre.

Per comprendere tutti questi concetti, creiamo un nuovo progetto UWP con il nome AppServiceProvider in Microsoft Visual Studio 2015.

Ora in Package.appmenifest file, aggiungere le seguenti informazioni.

Per creare un servizio app, che può essere richiamato dalle applicazioni in primo piano, aggiungiamo un nuovo Windows Runtime Progetto componente alla soluzione con MyAppService name, perché i servizi app vengono implementati come attività in background.

Aggiungi un riferimento al file MyAppService progetto in AppServiceProvider progetto.

Ora elimina il file class1.cs file da MyAppService progetto e aggiungi una nuova classe con il nome dell'inventario, che implementerà il IBackgrounTask interfaccia.

Il IBackgrounTask l'interfaccia ha un solo metodo “Run” che deve essere implementato per l'attività in background.

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

Quando viene creata l'attività in background, Run() methodviene chiamato e quando il metodo Run viene completato, le attività in background vengono terminate. Per mantenere un'attività in background, per soddisfare le richieste, il codice richiede un differimento.

Il codice dei servizi app è in OnRequestedReceived(). In questo esempio, un indice per un articolo di inventario passa al servizio, per recuperare il nome e il prezzo dell'articolo di inventario specificato.

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

Di seguito è riportata l'implementazione completa della classe Inventory in 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(); 
            } 
      } 
   } 
}

Creiamo un'app client aggiungendo un nuovo progetto UWP vuoto ClientApp e aggiungi un pulsante, una casella di testo e due blocchi di testo come mostrato di seguito nel file 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>

Di seguito è riportata l'implementazione dell'evento clic sul pulsante in cui vengono richiesti i servizi dell'app.

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

Per eseguire questa applicazione, sarà necessario impostare l'estensione ClientApp come progetto di avvio in Esplora soluzioni, quindi Distribuisci questa soluzione da Build > Deploy Soluzione.

Quando il codice sopra è stato compilato ed eseguito, vedrai la seguente finestra. Nei servizi app, abbiamo appena aggiunto le informazioni di due elementi. Quindi, puoi inserire 0 o 1 per ottenere informazioni su quegli elementi.

Quando si immette 0 e si fa clic sul pulsante, verrà eseguito il servizio app come attività in background e verranno visualizzate le informazioni sull'elemento nel file textblock.