在手机上,使用后台,不像电脑上那么随意,准确地讲嘛,在移动平台上,后台任务都有严格的限制。至于说为什么会有这么多限制,我估计初衷很明显——保证系统的性能不受某个或某几个应用的负面影响;另外就是出于安全性考虑。
毕竟手机设备不同于电脑,一旦后台程序泛滥成灾,是很难进行管理的,要防止这些不可预知的事件,只能从源头上杜绝。因此,当初在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开发】认识后台任务的更多相关文章
-
C# Windows Phone 8 WP8 高级开发,制作不循环 Pivot ,图片(Gallery)导览不求人! 内附图文教学!!
原文:C# Windows Phone 8 WP8 高级开发,制作不循环 Pivot ,图片(Gallery)导览不求人! 内附图文教学!! 一般我们在开发Winodws Phone APP 的时候往 ...
-
WP8.1开发:简单天气预报应用(转)
今天小梦给大家分享一个简单的天气预报应用源码:调用的是百度API.整个应用都没有什么难点.只是一个简单的网络请求和json数据处理.在WP8.1有小娜的情况下,天气预报应用还有意义吗?我认为还是有点意 ...
-
WP8.1开发:简单的天气预报应用
今天小梦给大家分享一个简单的天气预报应用源码:调用的是百度API.整个应用都没有什么难点.只是一个简单的网络请求和json数据处理.在WP8.1有小娜的情况下,天气预报应用还有意义吗?我认为还是有点意 ...
-
WP8.1开发:后台任务详解(求推荐)
小梦今天给大家分享一下windows phone 8.1中的后台任务如何实现,许多应用都会用到后台任务,所以我们必须得掌握. 新建后台任务类: 首先我们先新建一个windows phone 8.1空白 ...
-
1_1准备工作[wp8特色开发与编程技巧]
1准备工作 大家好,我是徐文康,今天我要开始带大家玩转windowsphone8 app的开发 在这一套视频中,我将带大家从零开始学习编程.在互联网时代熟悉编程是非常有必要的.差异化竞争将变成趋势,那 ...
-
质问微软 WP8.1开发HTTPS 真费劲
本人用C#多年,WPF2年,一直想做点应用为WP生态贡献一点力量,最近终于有机会接触了 家里的本子是2年前的低压I3,不支持虚拟化,一直没有真机.最近同事妈妈换下来一个820给我拿来做开发用,非常感谢 ...
-
(wp8.1开发)触摸键从推出变返回
---恢复内容开始--- 今天开发wp8.1,遇到这样一个问题,从第一个页面跳到第二个页面,在第二个页面按返回,结果程序退出了.原来是系统把返回键定义成退出了. 解决办法: 在第一个页面加入如下代码 ...
-
wp8.1 Study15:后台任务
一.介绍 1.多任务处理 什么是多任务处理?它意味着当App被挂起时,它仍然可以完成一些开发者设定的任务,比如更新tiles和toasts.预定toast和提醒.后台任务等. 2.后台任务 App可以 ...
-
4_1 wp8数据绑定与独立存储空间[wp8特色开发与编程技巧]
Wp8数据绑定与独立存储空间 数据绑定为基于 Silverlight 的应用程序提供了一种显示数据并与数据进行交互的简便方法. 数据的显示方式独立于数据的管理. UI 和数据对象之间的连接或绑定使数据 ...
随机推荐
-
给DOM生成的元素添加事件
问题:通过js给页面添加新元素,并给该元素添加绑定事件,但新添加的元素上却没有绑定任何事件. 常见例子:在处理表格的时候,每行行末有个删除按钮,如下图.点击删除按钮的时候删除这一行. //html部分 ...
-
如何用jenkins实现自动化构建新版本和二维码下载
最近公司开发了自己的app,研发过程中对于测试人员来说,经常会像开发的人员询问,有没有最新的包啊(apk打包后的新版本),以免你测试的时候,提交了一些缺陷,实际上人家已经解决了.当然你也可以说你们公司 ...
-
Android开发快速入门(环境配置、Android Studio安装)
Android是一种激动人心的开源移动平台,它像手机一样无处不在,得到了Google以及其他一些开放手机联盟成员(如三星.HTC.中国移动.Verizon和AT&T等)的支持,因而不能不加以学 ...
-
Ecological Premium
#include<bits/stdc++.h> using namespace std; int main() { int n,m; unsigned long long int a,b, ...
-
serialVersionUID作用
serialVersionUID适用于Java的序列化机制.简单来说,Java的序列化机制是通过判断类的serialVersionUID来验证版本一致性的.在进行反序列化时,JVM会把传来的字节流中的 ...
-
QT枚举类型与字符串类型相互转换
在QT中将枚举类型注册(QT_Q_ENUM或QT_Q_FLAG)后,就可以利用QT的元对象进行枚举类型与字符串类型转换了. 代码示例: #include <QtCore/QMetaEnum> ...
-
IOS动态自适应标签实现
先上效果图 设计要求 1.标签的宽度是按内容自适应的 2.一行显示的标签个数是动态的,放得下就放,放不下就换行 3.默认选中第一个 4.至少选中一个标签 实现思路 首先我们从这个效果上来看,这个标签是 ...
-
详解vue的数据binding原理
自从angular火了以后,各种mv*框架喷涌而出,angular虽然比较火,但是他的坑还是蛮多的,还有许多性能问题被人们吐槽.比如坑爹的脏检查机制,数据binding是受人喜爱的,脏检查就有点…性能 ...
-
原生js实现分页效果(带实例)
小小插件(静态分页) 效果图: 首先实现简单功能: <!DOCTYPE html> <html> <head> <meta http-equiv=" ...
-
2017乌鲁木齐区域赛D题Fence Building-平面图的欧拉公式
这个题B站上面有这题很完整的分析和证明,你实在不懂,可以看看这个视频 https://www.bilibili.com/video/av19849697?share_medium=android&a ...