Phát triển Windows 10 - Dịch vụ

Trong chương này, chúng ta sẽ tìm hiểu về cách ứng dụng UWP có thể trợ giúp hoặc cung cấp dịch vụ cho các ứng dụng Nền tảng Windows chung (UWP) khác. Thực ra chương này là phần mở rộng của chươngBackground execution và là một trường hợp đặc biệt của nó.

  • Trong Windows 10, dịch vụ ứng dụng là một cách hoặc cơ chế để ứng dụng cung cấp dịch vụ cho các ứng dụng khác.

  • Dịch vụ ứng dụng hoạt động dưới dạng tác vụ nền.

  • Ứng dụng nền có thể gọi một dịch vụ ứng dụng trong một ứng dụng khác để thực hiện các tác vụ trong nền.

Dịch vụ ứng dụng giống như dịch vụ web nhưng dịch vụ ứng dụng được sử dụng trên thiết bị Windows 10.

Các ứng dụng Universal Windows Platform (UWP) có thể tương tác với một ứng dụng UWP khác theo nhiều cách khác nhau -

  • Liên kết URI sử dụng LaunchUriAsync
  • Liên kết tệp bằng LaunchFileAsync
  • Khởi chạy để biết kết quả bằng LaunchUriForResultsAsync
  • Dịch vụ ứng dụng

Ba cách đầu tiên được sử dụng khi cả hai ứng dụng đều ở nền trước, nhưng các dịch vụ Ứng dụng được sử dụng trong background task và trong trường hợp đó, ứng dụng khách phải ở nền trước và có sẵn để sử dụng dịch vụ Ứng dụng.

Dịch vụ ứng dụng rất có lợi trong các ứng dụng cung cấp các dịch vụ không trực quan, ví dụ như máy quét mã vạch, trong đó ứng dụng nền trước sẽ lấy hình ảnh và gửi các byte đó đến các dịch vụ ứng dụng để xác định mã vạch.

Để hiểu tất cả các khái niệm này, chúng ta hãy tạo một dự án UWP mới với tên AppServiceProvider trong Microsoft Visual Studio 2015.

Bây giờ trong Package.appmenifest tệp, thêm thông tin sau.

Để tạo một dịch vụ ứng dụng, có thể được gọi bởi các ứng dụng nền trước, hãy để chúng tôi thêm một Windows Runtime Dự án thành phần giải pháp với MyAppService vì các dịch vụ ứng dụng được triển khai dưới dạng tác vụ nền.

Thêm một tham chiếu đến MyAppService dự án trong AppServiceProvider dự án.

Bây giờ xóa class1.cs tập tin từ MyAppService dự án và thêm một lớp mới với tên khoảng không quảng cáo, lớp này sẽ triển khai IBackgrounTask giao diện.

Các IBackgrounTask giao diện chỉ có một phương pháp “Run” cần được triển khai cho Tác vụ nền.

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

Khi tác vụ nền được tạo, Run() methodđược gọi và khi phương thức Run hoàn thành, thì các tác vụ nền sẽ kết thúc. Để duy trì một tác vụ nền, để phục vụ các yêu cầu, mã sẽ được hoãn lại.

Mã dịch vụ ứng dụng có trong OnRequestedReceived(). Trong ví dụ này, một chỉ mục cho một mặt hàng tồn kho được chuyển đến dịch vụ, để truy xuất tên và giá của mặt hàng tồn kho được chỉ định.

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

Dưới đây là cách triển khai hoàn chỉnh của lớp Khoảng không quảng cáo trong 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(); 
            } 
      } 
   } 
}

Hãy để chúng tôi tạo một ứng dụng khách bằng cách thêm một dự án UWP trống mới ClientApp và thêm một nút, một hộp văn bản và hai khối văn bản như được hiển thị bên dưới trong tệp 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>

Dưới đây là triển khai sự kiện nhấp vào nút trong đó Dịch vụ ứng dụng được yêu cầu.

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

Để chạy ứng dụng này, bạn sẽ cần đặt ClientApp dự án trở thành dự án khởi động trong Trình khám phá giải pháp và sau đó Triển khai giải pháp này từ Build > Deploy Giải pháp.

Khi đoạn mã trên được biên dịch và thực thi, bạn sẽ thấy cửa sổ sau. Trong Dịch vụ ứng dụng, chúng tôi vừa thêm thông tin của hai mục. Vì vậy, bạn có thể nhập 0 hoặc 1 để lấy thông tin của các mục đó.

Khi bạn nhập 0 và nhấp vào nút, nó sẽ chạy Dịch vụ ứng dụng làm tác vụ nền và sẽ hiển thị thông tin mục trên textblock.