在手机上,使用后台,不像电脑上那么随意,准确地讲嘛,在移动平台上,后台任务都有严格的限制。至于说为什么会有这么多限制,我估计初衷很明显——保证系统的性能不受某个或某几个应用的负面影响;另外就是出于安全性考虑。

毕竟手机设备不同于电脑,一旦后台程序泛滥成灾,是很难进行管理的,要防止这些不可预知的事件,只能从源头上杜绝。因此,当初在RT应用上就是:允许后台任务,但你得按规矩做人。

无规矩不成方圆,没有限制就会乱象横生,无法控制,现在某手机系统就深陷这一问题无法自拨,WP没有必要重蹈这一覆辙。

好,前面废话了那么多,就是要告诉大家,在开发的时候一定要想清楚,到底该不该使用后台任务,使用后台任务的话,一定要自己亲测一下,是否会明显消耗电量,是否会产生庞大的网络流量。大家一定要养成一个好习惯——以做流氓程序为耻。说到这里,不得不鄙视一下国内的某些公司。

既然后台任务是有限制的,那么,官方是通过什么方式来限制的呢?

触发器:后台任务必须通过触发器来执行。这个触发器,可以理解为类似生物的条件反射。清单文件给出的触发类型有:后台音频、计时器、系统维护等。记得前面我写过博客,弄了一个在点亮屏幕时播放音乐,虽然这种做法不尽合理,但也作为一种参考吧。那个示例就是通过系统触发器中的UserPresent类型触发的,就是当用户把手机屏幕点亮这一行为发生后就会执行后台任务。

比如,比较常用的还有计时器,这个应该会用得较多,比如每隔一段时间提取一批新闻列表等,如每30分钟就执行一次。当然这计时器是有限制的,常规要求是至少15分钟。不然的话,一些人品不端正的开发者弄个每分钟触发一次,那还得了,如果它是提取广告的话,那不断地弹广告就会把用户弹傻了。大家千万别干这种事,你要干这种事,我只能说你太没出息。

凡是实现了IBackgroundTrigger接口的都是触发器,常以“Trigger”结尾,并不是所有触发器都能用,有些是需要申请的,比如ChatMessageNotificationTrigger,这也是防止恶意程序的做法。

执行条件:这个主要由SystemCondition类表示。执行条件与触发器不同,触发器是表明在什么事实发生后执行后台任务,而执行条件是在什么情况下才能执行后台任务。你听起来好像意思接近,实际上是不同的。比如,如果你的后台任务需要从网络上获取数据,而且触发器为每25分钟一次的计时器,于是在注册后台任务时,你可以考虑增加一个执行条件:在有网络连接的前提下执行。虽然计时器的时间到了,但正好这个时候,由于用户的手机卡欠下4G流量费8622000元,被停机了,没法上网,那么系统检测到不存在有效的网络连接,就不执行后台任务了(可以考虑用WiFi)。

如何使用后台任务

前面扯了一堆臊话,主要是让朋友们对后台任务有个大致的了解,现在向大家介绍如何用后台。

代表后台任务的代码通常应该写在一个独立的组件中,这样做也比较科学的,有些朋友在开发程序时,喜欢把所有功能都塞到一个主程序里,许多人在开发桌面程序时就喜欢这样,把所有功能都塞进一个exe中,连.dll都不舍得多用一个,我不喜欢这样做的,一般我是一个功能模板用一个独立的.dll,至于.exe用来放UI或者一些核心处理。

因此,第一步是向解决方案中添加一个Windows运行时组件,看清楚,是运行时组件,最后会生成.wimd文件,如果是类库就会生成.dll文件。后台任务都应写在Windows运行时组件中。这个应该会了吧,就是在“解决方案资源管理器”中新建项目,然后选Windows运行时组件,输入项目名字就可以了,如果你不会这个,我只能告诉你:基础不扎实,举步艰难。

然后在新建的运行时组件中定义一个类,一定要是public的,不要问我为什么(请复习程序集的可访问性),这个类要实现IBackgroundTask接口,表示它用于执行后台任务。

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

重点是实现Run方法,当后台任务执行时,就是调用这个方法的,你的后台任务要做什么就写在Run里面。
注意到有个IBackgroundTaskInstance类型的参数,是个接口,我们不用管它哪个类实现,这个在系统调用时会自动赋值,只关心它有哪些成员即可。

一定要明白GetDeferral方法的作用,它可以返回一个BackgroundTaskDeferral对象,这个对象的作用,说简单一点就是用来拖延时间的,就是拖延后台任务的时间,当你觉得后台任务已经完成了,就调用用BackgroundTaskDeferral的Complete方法,告诉系统:任务做完了,系统收到报告后,就可以清理该任务了。

现在我们来实现一下这个任务。

        public void Run ( IBackgroundTaskInstance taskInstance )
{
var def = taskInstance.GetDeferral();
// 获取XML模板
XmlDocument docx = ToastNotificationManager.GetTemplateContent(ToastTemplateType.ToastText02);
// 修改XML
var eles = docx.GetElementsByTagName("text");
if (eles.Count < )
{
def.Complete();
return;
}
XmlElement text01 = (XmlElement)eles[];
text01.AppendChild(docx.CreateTextNode("示例"));
XmlElement text02 = (XmlElement)eles[];
text02.AppendChild(docx.CreateTextNode("后台任务执行了。")); // 产生Toast通知
ToastNotification notification = new ToastNotification(docx);
// 显示通知
ToastNotificationManager.CreateToastNotifier().Show(notification); // 报告任务完成
def.Complete();
}

这个任务,不复杂,就是向用户发一条Toast通知。

好,后台任务已经写好了,现在要在主项目中对它进行引用,一定不要忘了,只有引用了上面写的Windows运行时组件才能访问它,这和以前.net项目一样。

这个后台任务,我打算让它每40分钟执行一次,所以触发器应选用TimeTrigger。下面先简单设计一下UI。

    <StackPanel>
<Button Content="注册后台任务" Click="开始注册"/>
<Button Content="取消后台任务" Click="取消注册"/>
<TextBlock x:Name="tb" FontSize="" TextWrapping="Wrap"/>
</StackPanel>

界面简单,你看得懂的,其实事件处理的方法名是可以用中文的,在VS里面,类型名、命名空间名、成员名、参数名都可以用中文的,如果你不喜欢英文名字,可以用中文。

通常,注册后台任务需要准备以下证件:

1、个人身份证,即后台任务的名字,这个名字必须唯一,不能与现有的任务重复。

2、户口本。即入口点,指的是我们前面在Windows运行时组件中定义的那个类的类名,就是那个实现IBackgroundTask接口以及Run方法的类。

为了在输入代码时不容易输入,最好先将这些内容声明为常量。

        /// <summary>
/// 任务的唯一名称
/// </summary>
const string TASK_NAME = "haha_task";
/// <summary>
/// 入口点
/// </summary>
const string ENTRY_POINT = "BackTest.DemoTask";

注意,入口点的名字是要包含命名空间名字的。

好,前期手续基本办完,现在可以正式注册了。下面代码分别用于注册和取消注册后台任务。

        private async void 开始注册 ( object sender, RoutedEventArgs e )
{
var res = await BackgroundExecutionManager.RequestAccessAsync();
if (res != BackgroundAccessStatus.AllowedMayUseActiveRealTimeConnectivity)
return; // 注册
BackgroundTaskBuilder bd = new BackgroundTaskBuilder();
bd.Name = TASK_NAME; //任务名
bd.TaskEntryPoint = ENTRY_POINT; //入口点
// 设置触发器为计时器
bd.SetTrigger(new TimeTrigger(, false));
try
{
BackgroundTaskRegistration reg = bd.Register();
// 注册成功,显示结果
tb.Text = string.Format("任务名:{0}\n任务ID:{1}", reg.Name, reg.TaskId);
}
catch (Exception ex)
{
tb.Text = ex.Message;
}
} private void 取消注册 ( object sender, RoutedEventArgs e )
{
// 先查找一下是否已经注册了任务
var task = BackgroundTaskRegistration.AllTasks.Values.FirstOrDefault(t => t.Name == TASK_NAME);
if (task != null)
{
// 取消
task.Unregister(true);
}
}

1、在注册之前一定要调用BackgroundExecutionManager.RequestAccessAsync方法,是然不会弹出任何提示,但不要忘了,不调用是不能注册的。

2、BackgroundTaskBuilder类,顾名思义,就是用来注册后台任务的。

3、TimeTrigger触发器的构造函数的第二个参数如果为true,那后台任务只运行一次,这里我希望它每40分钟运行一次,所以为false。

现在,离成果不远了,但是还有一步很关键,那就是配置清单文件。

打开Package.appxmanifest文件,切换到“声明”选项页,在可用的声明列表中选“后台任务”,然后点击添加按钮。

在右边的页面中,按实际情况勾选,我这个例子是计时的,所以选计时器,然后在下面再填写一下入口点,这个入口点和注册后台任务时用的入口点是一样的,可以直接从刚才的代码中复制过来。

因为本例要用到Toast通知,所以要让应用支持Toast。切换到“应用程序”选项卡,在下面有关通知设置的地方,将支持Toast通知设置为“是”。

最后,保存并关闭清单文件。

如何调试后台任务

像我这个例子,要等40分钟才执行的,难道我在干等不成? 非也,我们不用在那里苦等40分钟,VS会帮助我们进行调试的。

首先,运行应用程序,然后点页面上的注册按钮,确保后台任务已经成功注册。

然后回到VS,在“调试位置”工具上,点击“生命周期事件”按钮右边的下拉箭头,从下拉菜单中你会看到有后台任务的名字。如下图。

如果看不到,你可以稍等一下,如果一直不出现,你可以重复上面的步骤。只要后台任务注册成功的,肯定会显示的(后台音频和推送通知除外)。

所以,现在你调试后台任务就很方便,直从“调试位置”工具栏的下拉菜单中选中后台任务,后台任务就会执行了。

OK,相信通过这篇破文,初学者能够初步认识后台任务。

示例源码:http://files.cnblogs.com/tcjiaan/SampleAppBackTask.zip

【WP8.1开发】认识后台任务的更多相关文章

  1. C# Windows Phone 8 WP8 高级开发,制作不循环 Pivot ,图片(Gallery)导览不求人! 内附图文教学!!

    原文:C# Windows Phone 8 WP8 高级开发,制作不循环 Pivot ,图片(Gallery)导览不求人! 内附图文教学!! 一般我们在开发Winodws Phone APP 的时候往 ...

  2. WP8.1开发:简单天气预报应用(转)

    今天小梦给大家分享一个简单的天气预报应用源码:调用的是百度API.整个应用都没有什么难点.只是一个简单的网络请求和json数据处理.在WP8.1有小娜的情况下,天气预报应用还有意义吗?我认为还是有点意 ...

  3. WP8.1开发:简单的天气预报应用

    今天小梦给大家分享一个简单的天气预报应用源码:调用的是百度API.整个应用都没有什么难点.只是一个简单的网络请求和json数据处理.在WP8.1有小娜的情况下,天气预报应用还有意义吗?我认为还是有点意 ...

  4. WP8.1开发:后台任务详解(求推荐)

    小梦今天给大家分享一下windows phone 8.1中的后台任务如何实现,许多应用都会用到后台任务,所以我们必须得掌握. 新建后台任务类: 首先我们先新建一个windows phone 8.1空白 ...

  5. 1_1准备工作[wp8特色开发与编程技巧]

    1准备工作 大家好,我是徐文康,今天我要开始带大家玩转windowsphone8 app的开发 在这一套视频中,我将带大家从零开始学习编程.在互联网时代熟悉编程是非常有必要的.差异化竞争将变成趋势,那 ...

  6. 质问微软 WP8.1开发HTTPS 真费劲

    本人用C#多年,WPF2年,一直想做点应用为WP生态贡献一点力量,最近终于有机会接触了 家里的本子是2年前的低压I3,不支持虚拟化,一直没有真机.最近同事妈妈换下来一个820给我拿来做开发用,非常感谢 ...

  7. (wp8.1开发)触摸键从推出变返回

    ---恢复内容开始--- 今天开发wp8.1,遇到这样一个问题,从第一个页面跳到第二个页面,在第二个页面按返回,结果程序退出了.原来是系统把返回键定义成退出了. 解决办法: 在第一个页面加入如下代码 ...

  8. wp8.1 Study15:后台任务

    一.介绍 1.多任务处理 什么是多任务处理?它意味着当App被挂起时,它仍然可以完成一些开发者设定的任务,比如更新tiles和toasts.预定toast和提醒.后台任务等. 2.后台任务 App可以 ...

  9. 4_1 wp8数据绑定与独立存储空间[wp8特色开发与编程技巧]

    Wp8数据绑定与独立存储空间 数据绑定为基于 Silverlight 的应用程序提供了一种显示数据并与数据进行交互的简便方法. 数据的显示方式独立于数据的管理. UI 和数据对象之间的连接或绑定使数据 ...

随机推荐

  1. Codeforces #380 div2 D(729D) Sea Battle

    D. Sea Battle time limit per test 1 second memory limit per test 256 megabytes input standard input ...

  2. [UE4][Custom Animation Graph Node]Evaluate Pose by Curve

    目的:根据曲线值获得当前动作帧.用于实现各种通过曲线同步的功能. 方法:继承FAnimNode_Base创建自定义动画节点.重写Evaluate部分.创建相应的AnimGraphNode.可参考前一篇 ...

  3. Java 用自带dom解析器遍历叶子节点内容

    一.XML文件config.xml,内容如下: <?xml version="1.0" encoding="UTF-8" standalone=" ...

  4. C++查找指定目录下所以指定类型的文件

    /*************************************************************** 函数名称:FindFile 查找指定目录下指定文件 输入:fileNa ...

  5. CXF实现webservice

    虽然网上有很多cxf的教程,但还是要自己写写, “好记性不如烂笔头” 1.服务端 1.1  DEMO,用于测试传递对象 package com.xq.model; import javax.persi ...

  6. FileInputStream和BufferedInputStream的区别

    FileInputStream 属于数据源 BufferedInputStream 属于FileInputStream的一个装饰 BufferedInputStream 有个内部缓冲区当read时会先 ...

  7. Oracle基本数据字典:v$database、v$instance、v$version、dba_objects

    v$database: 视图结构: SQL> desc v$database; Name                                      Null?    Type - ...

  8. SQLSERVER中如何忽略索引提示

    SQLSERVER中如何忽略索引提示 当我们想让某条查询语句利用某个索引的时候,我们一般会在查询语句里加索引提示,就像这样 当在生产环境里面,由于这个索引提示的原因,优化器一般不会再去考虑其他的索引, ...

  9. Android 各层调用的方式

    所有的android的app启动都有三种深入启动的方式: ①app——Runtime Service——Lib 这种启动方式是: Ⅰapp程序中启动application framework 层中Ru ...

  10. 【腾讯Bugly干货分享】iOS黑客技术大揭秘

    本文来自于腾讯bugly开发者社区,非经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/5791da152168f2690e72daa4 “8小时内拼工作,8小时外拼成长 ...