今天要实现一个需求,当用户触摸HOME键,将应用切换到后台时,启动自动备份的任务。这涉及到ios的后台任务处理,本文简单总结一下

首先,ios app有5种状态,分别是:not running, inactive, active, background, suspended,详情请看官方的guide:

apple guide

机制

如果应用处于background状态,又希望它继续做一些事的话,ios提供了几种途径:

推送

苹果提供的PUSH机制,叫APNS。腾讯的QQ和微信就是使用这种方式。实际上,使用长连接会更好,但是苹果不支持。我理解其实应用已经suspended,但是当接收到push的数据以后,会短暂地回到background进行处理,处理完毕以后又回到suspended状态

从ios7开始,分为local push和remote push,我们应用现在还没用到,暂不深究

智能调度

太玄乎了,不太了解

特定的多任务

某些特定的任务可以在后台长时间运行,比如VOIP,location service等,只有特定类型的任务,才能用这种方式,适用性不强

后台上传下载

类似于特定多任务,只有特殊的任务才能用

task completion

这种方式的适用性比较强,我最后也是采取这种方式来实现的。因此本文重点介绍这种

通常情况下,应用在进入background之后,很快就会转到suspended状态。但是,如果应用有需要的话(比如我们这个需求),可以向系统申请一点额外的时间来完成当前的任务

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
- (void)applicationDidEnterBackground:(UIApplication *)application
{
    __block UIBackgroundTaskIdentifier bgTask;// 后台任务标识
     
    // 结束后台任务
    void (^endBackgroundTask)() = ^(){
        [application endBackgroundTask:bgTask];
        bgTask = UIBackgroundTaskInvalid;
    };
     
    bgTask = [application beginBackgroundTaskWithExpirationHandler:^{
        endBackgroundTask();
    }];
     
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
         
        double start_time = application.backgroundTimeRemaining;// 记录后台任务开始时间
         
        BOOL networkAvailable = [YLSGlobalUtils isNetworkAvailable];
        if(!networkAvailable){
            NSLog(@"网络不可用,取消自动备份");
            endBackgroundTask();
            return;
        }
         
        BOOL need = [backupService checkNeedBackup];
        if(!need){
            NSLog(@"无需备份");
            endBackgroundTask();
            return;
        }
         
        [backupService doBackupProcessHandler:^(float done, float total){
            // nothing to do with progress
        } CompletionHandler:^(NSError* error, NSArray* statistics){
            double done_time = application.backgroundTimeRemaining;
            double spent_time = start_time - done_time;
            NSLog(@"后台备份完成,耗时: %f秒", spent_time);
            endBackgroundTask();
        }];
    });
}

核心是这个方法:

1
- (UIBackgroundTaskIdentifier)beginBackgroundTaskWithExpirationHandler:(void(^)(void))handler

注册一个后台任务,这个任务最多只有10分钟时间,如果超时,则会调用参数中的block,在此block中,必须调用这个方法:

1
- (void)endBackgroundTask:(UIBackgroundTaskIdentifier)identifier

否则,应用会crash。只要调用了beginBackgroundTaskWithExpirationHandler:方法,就必须在handler里相应地调用endBackgroundTask:方法

实际的逻辑,在下面的block里完成,这里没什么特别的,只是如果提前结束了任务,也调用一次endBackgroundTask:方法,这样就不会超时,前面的expirationHandler就不会被执行

另外,通过UIApplication的backgroundTimeRemaining属性,可以获取此后台任务还剩余的时间(当此值变成0,expirationHandler就被执行)

使用时机

这段代码,是写在ApplicationDelegate的生命周期方法里:

1
- (void)applicationDidEnterBackground:(UIApplication *)application

这主要是因为,我们就是希望仅当应用被切换到后台时才开始自动备份。但是后台任务并不是只能在这种情况下启动,如果应用中有一些关键性的任务,希望即使被切换到后台也要先完成再suspend,就可以随时调用

1
- (UIBackgroundTaskIdentifier)beginBackgroundTaskWithExpirationHandler:(void(^)(void))handler

以确保此任务完成,写法只要参考上面的代码就行了

ios background task的更多相关文章

  1. 与众不同 windows phone (13) - Background Task(后台任务)之后台文件传输(上传和下载)

    原文:与众不同 windows phone (13) - Background Task(后台任务)之后台文件传输(上传和下载) [索引页][源码下载] 与众不同 windows phone (13) ...

  2. 与众不同 windows phone (12) - Background Task(后台任务)之 PeriodicTask(周期任务)和 ResourceIntensiveTask(资源密集型任务)

    原文:与众不同 windows phone (12) - Background Task(后台任务)之 PeriodicTask(周期任务)和 ResourceIntensiveTask(资源密集型任 ...

  3. 与众不同 windows phone (11) - Background Task(后台任务)之警报(Alarm)和提醒(Reminder)

    原文:与众不同 windows phone (11) - Background Task(后台任务)之警报(Alarm)和提醒(Reminder) [索引页][源码下载] 与众不同 windows p ...

  4. running a background task over ssh

    原文: Why does running a background task over ssh fail if a pseudo-tty is allocated? 问题: I've recently ...

  5. UWP -- Background Task 深入解析

    原文:UWP -- Background Task 深入解析 1. 重点 锁屏问题 从 Windows 10 开始,用户无须再将你的应用添加到锁屏界面,即可利用后台任务,通用 Windows 应用必须 ...

  6. IOS Background 之 Background Fetch

    http://www.ithao123.cn/content-1363653.html 定期更新数据的app,比如及时通信类,微博等app. 定期后台获取,等打开后获取的快一些. 30分钟后打开手,获 ...

  7. how to run a continuous background task on OpenShift

    https://stackoverflow.com/questions/27152438/best-way-to-run-rails-background-jobs-with-openshift ht ...

  8. Executing a Finite-Length Task in the Background

    [Executing a Finite-Length Task in the Background] Apps that are transitioning to the background can ...

  9. iOS 后台处理

    iOS 后台处理的常见用途 1.进入后台时候删除资源:应用处于挂起状态的时候所占用的资源越少,该应用被iOS终止的风险就越低.通过从内存中清理那些易于重新创建的资源,可以增加应用驻留内存的机会,因此可 ...

随机推荐

  1. 高级I/O

    1.阻塞问题的几种解决模型 1.1 非阻塞模型:类似于死循环,需要适当加休眠,防止cpu占用太高:效率较低 1.2 线程异步:效率最高的一种解决方案 1.3 I/O多路转接与复用  select(低) ...

  2. signal——信号集

    1.信号集  每个进程都有一个信号屏蔽字,它规定了当前要阻塞递送到该进程的信号集.对于每种可能的信号,该屏蔽字中都有一bit位与之对应.信号数可能会超过一个整型数所包含的二进制位数,因此POSIX.1 ...

  3. pycharm2018后版本执行Flask app.run()深坑

    在2018年以前的版本,以上配置在app.run()里面的内置方法

  4. IDEA Maven项目中添加tomcat没有无artifact选项

    IntelliJ使用 ##使用IntelliJ IDEA配置web项目时,选择Edit Configration部署Tomcat的Deployment可能会出现以下情况: 导致新手部署过程中摸不着头脑 ...

  5. F5 BIG-IP之一前期随笔(应用交付网络产品)

    ADN:应用交付网络 TMOS:  Traffic  managment  operation  system  (流量管理系统) 一个实时的全应用代理流量管理操作系统             PVA ...

  6. C#结构体的使用

    C#结构体的使用 结构体:相当于是我们自己定义的一种复杂的类型. 常见简单类型:int... double float bool char string 常见复杂类型:DateTime 数组类型 生活 ...

  7. 常用的mysql操作

    总结一下常用的mysql操作,避免下次遇到类似情况重复地去百度. 方法不是唯一的,但记录一种可行的方法就可以了. 遇到新的问题再继续补充. 1.增加一个列 ALTER TABLE 表名 ADD COL ...

  8. JQ主页图片划动切换效果

    .wrapper { width: 726px; float: left; } #jiao_dian { width: 980px; *height: 292px; margin-top: 10px; ...

  9. CF-1114C-Trailing Loves (or L'oeufs?)

    题意: 输入n和m,求n!转换成m进制之后末尾有多少个0: 思路: 转换一下题意就可以看成,将n表示成x * (m ^ y),求y的最大值.^表示次方而不是异或: 这就比较好想了,将m分解质因数,对于 ...

  10. Java IO: 异常处理

    原文链接 作者:Jakob Jenkov 译者: 李璟(jlee381344197@gmail.com) 流与Reader和Writer在结束使用的时候,需要正确地关闭它们.通过调用close()方法 ...