App Service 是一种背景工作运行的服务,提供给其他Apps 使用就像Web Service。它本身无使用介面(UI-less),允许Apps 在同一个设备被引用,甚至Windows 10 1607 开始允许remote devices 使用它。

[ 重点观念 ]

Windows 10, version 1607 开始, App Service 支持新模式:
可以与host App 运行在相同的process;(一般属于Background Task 执行在不同的process)
支援从App呼叫Remote Devices中的App Service;
想要App Service每次被启动都是新的instance,在Package.appmanifest加入宣告;uap4:SupportsMultipleInstances="true";但需要Windows 10, version 15063以上才支援
App Service 的生命周期,因为Process 有所不同:
后台任务(进程外):
当它被建立时会进入Run(),随着Run()执行完毕就会被结束
它被启动后,基本会维持活着约有30秒,可搭配呼叫GetDeferral()多加5秒来完成任务
In-app process model:生命周期则跟着呼叫者一起共存,让两个Apps 之间更容易沟通,不用再分成两份code 来串联与维护
App Service 的OnTaskCancel() 被触发有几个原因:
Client app释放AppServiceConnection
Client app 被 suspended
系统关闭或睡眠
系统执行该Task 用过高的资源
大略有概念之后,接着介绍怎么做基本的App Service (two process),再介绍怎么整合到App 的process 里面;

  • 如何建立App service 并使用它:

分成两个App 做说明:一个是拥有App Service 的Host App;一个是使用App Service 的Client App;

1建立一个Windows Runtime Component,并且加入AppServiceConnection 的处理逻辑:

public sealed class ServiceTask : IBackgroundTask
{
private BackgroundTaskDeferral backgroundTaskDeferral;
private AppServiceConnection appServiceconnection; public void Run(IBackgroundTaskInstance taskInstance)
{
// Background Task 被建立時,取得 deferral 拉長生命周期,避免被結束
this.backgroundTaskDeferral = taskInstance.GetDeferral(); // 一定要註冊處理 Canceled 事件來正確釋放用到的資源
taskInstance.Canceled += OnTaskCanceled; // 根據被啓動的 Instance 類型,建立 App Service Connection,並註冊 Request 事件.
var details = taskInstance.TriggerDetails as AppServiceTriggerDetails;
appServiceconnection = details.AppServiceConnection;
appServiceconnection.RequestReceived += OnRequestReceived;
} private void OnTaskCanceled(IBackgroundTaskInstance sender, BackgroundTaskCancellationReason reason)
{
if (this.backgroundTaskDeferral != null)
{
// Complete the service deferral.
this.backgroundTaskDeferral.Complete();
}
} private async void OnRequestReceived(AppServiceConnection sender, AppServiceRequestReceivedEventArgs args)
{
// 當 App Service 收到請求時,該 method 就會被觸發
// 先要求取得 取得 deferral 拉長生命周期
var requestDeferral = args.GetDeferral(); ValueSet message = args.Request.Message;
string cmd = message["cmd"] as string;
string id = message["id"] as string; ValueSet responseMsg = new ValueSet(); switch (cmd)
{
case "Query":
responseMsg.Add("id", "123456");
responseMsg.Add("name", "pou");
responseMsg.Add("status", "OK");
var result = await args.Request.SendResponseAsync(responseMsg);
break;
} requestDeferral.Complete();
}
}

2在Host App 的Package.manifest 宣告App Service 并设定Entry Point,记得把App Service 的专案加入到Host App 的专案参考:

<Applications>
<Application Id="App" Executable="$targetnametoken$.exe" EntryPoint="ServiceHost.App">
<uap:VisualElements />
<Extensions>
<uap:Extension Category="windows.appService" EntryPoint="MyAppService.ServiceTask">
<uap:AppService Name="com.pou.MyApService" />
</uap:Extension>
</Extensions>
</Application>
</Applications>

加入专案参考这样在Host App被安装的时候才会一并加入App Service。利用Windows.ApplicationModel.Package.Current.Id.FamilyName在Host App拿到package family name,准备交给Client App。
3在 Client App 利用 AppServiceConnection 呼叫 App Service:

private async void MainPage_Loaded(object sender, RoutedEventArgs e)
{
AppServiceConnection connection = new AppServiceConnection();
connection.AppServiceName = "com.pou.MyApService";
connection.PackageFamilyName = "f9842749-e4c8-4c15-bac8-bc018db1b2ea_s1mb6h805jdtj"; var status = await connection.OpenAsync(); if (status != AppServiceConnectionStatus.Success)
{
Debug.WriteLine("Failed to connect");
return;
} var message = new ValueSet();
message.Add("cmd", "Query");
message.Add("id", "1234"); AppServiceResponse response = await connection.SendMessageAsync(message);
string result = ""; if (response.Status == AppServiceResponseStatus.Success)
{
if (response.Message["status"] as string == "OK")
{
result = response.Message["name"] as string;
}
}
}

上面介绍的App Service 是比较一般的用法, 把App Service 放到Background Task 的架构。

  • 把App Service 合并到App.xaml.cs 里面,作为Same Process:

AppServiceConnection允许其他App叫醒在背景中自己的App并传入指令。它与上方的out-of-process最大不同有两个:

1Package.manifest 宣告 <uap:Extension Category="windows.appService"> 不用 Entry Point,改用 OnBackgroundActivated()。

<Package>
<Applications>
<Application>
<Extensions>
<uap:Extension Category="windows.appService">
<uap:AppService Name="com.pou.MyApService" />
</uap:Extension>
</Extensions>
</Application>
</Applications>

2在App.xaml.cs加入OnBackgroundActivated()的处理逻辑。

sealed partial class App : Application
{
private AppServiceConnection appServiceConnection;
private BackgroundTaskDeferral appServiceDeferral; protected override void OnBackgroundActivated(BackgroundActivatedEventArgs args)
{
base.OnBackgroundActivated(args); AppServiceTriggerDetails appService = args.TaskInstance.TriggerDetails as AppServiceTriggerDetails; if (appService ==null)
{
return;
} args.TaskInstance.Canceled += OnAppServicesCanceled; // appServiceDeferral 與 appServiceConnection 需要變成公用變數
// 因爲其他時間需要用到,已維持連線的一致性
appServiceDeferral = args.TaskInstance.GetDeferral();
appServiceConnection = appService.AppServiceConnection; appServiceConnection.RequestReceived += AppServiceConnection_RequestReceived;
appServiceConnection.ServiceClosed += AppServiceConnection_ServiceClosed;
} private async void AppServiceConnection_RequestReceived(AppServiceConnection sender, AppServiceRequestReceivedEventArgs args)
{
// 當 App Service 收到請求時,該 method 就會被觸發 // 先要求取得 取得 deferral 拉長生命周期
var requestDeferral = args.GetDeferral(); ValueSet message = args.Request.Message; string cmd = message["cmd"] as string;
string id = message["id"] as string; ValueSet responseMsg = new ValueSet(); switch (cmd)
{
case "Query":
responseMsg.Add("id", "123456");
responseMsg.Add("name", "pou");
responseMsg.Add("status", "OK");
var result = await args.Request.SendResponseAsync(responseMsg);
break;
} requestDeferral.Complete();
} private void AppServiceConnection_ServiceClosed(AppServiceConnection sender, AppServiceClosedEventArgs args)
{
appServiceDeferral?.Complete();
appServiceConnection?.Dispose();
} private void OnAppServicesCanceled(IBackgroundTaskInstance sender, BackgroundTaskCancellationReason reason)
{
appServiceDeferral?.Complete();
appServiceConnection?.Dispose();
}
}

要支援in-process model就是这样简单,而且让原本的App Service逻辑回到App本身,让逻辑更干净。OnBackgroundActivated()负责处理App Service的启用,并储存Deferral保持服务的生命周期,详细可以参考Windows 10通用Windows平台(UWP) app周期。

最新文章

  1. 【随笔】MQTT简介
  2. Delphi字符串与字符数组之间的转换(初始化的重要性)
  3. Codeforce - Travelling Salesman
  4. [CoreOS 转载] CoreOS实践指南(七):Docker容器管理服务
  5. Yii2提示信息设置方法
  6. Hadoop-eclipse-plugin插件安装
  7. PANGU---Planet and Asteroid Natural scene Generation Utility
  8. Linux主要发行版本介绍
  9. Sublime Text 3:3114的安装(目前最新),插件emmet的安装
  10. 《Javascript高级程序设计》读书笔记之闭包
  11. Windows Azure Virtual Machine (34) 保护Azure虚拟机
  12. ubuntu14.04下安装有道词典
  13. JAVA个人理解
  14. robotframework的学习笔记(十三)------Robot Framework常用库简介
  15. asp.net -mvc框架复习(6)-基于MVC实现简单计算器
  16. JAR包结构,META-INF/MANIFEST.MF文件详细说明[全部属性][打包][JDK]
  17. oracle中查询用户表/索引/视图创建语句
  18. 剑指offer例题——二维数组中的查找
  19. javascript的基础知识整理
  20. php71 gdnz

热门文章

  1. c语言:getchar() getch()回显
  2. [WPF] 使用 Visual Studio App Center 持续监视应用使用情况和问题
  3. 高校表白App-团队冲刺第八天
  4. Hive——元数据表含义
  5. springboot-1-入门
  6. JAVA基础(代码)练习题61~90
  7. 去掉返回的json中特殊字符
  8. K8S系列第三篇(Docker网络)
  9. 第四篇 -- Go语言string转其他类型
  10. QLabel的使用