iOS系统后台运行机制研究

众所周知,iOS操作系统上的App,不仅仅是外形美,同时其也是以流畅著称,可以说是极端的流畅。在流畅的外表下,是操作系统对于程序的调度、前后台的切换、内存的管理都达到了极致。

在日常的iOS开发中,不免会遇到需要App在被切到后台之后,仍然需要运行一个进程完成某些特殊的操作,一般后台运行进程作用有以下几类:

  • 后台更新数据、同步刷新UI
  • 与服务端通信,发送心跳,如“XMPP”类App
  • 获取用户地理信息数据(GPS),如新“高德地图”
  • 多媒体App用来继续播放音乐,如“酷狗音乐”
  • 网络电话类App(VoIP)

要完成上述操作,有以下集中解决方案,每种方案各有优劣,适用于不同情况:


一、VoIP

优势:

  • 永远不会被后台进程强杀
  • 实现起来简单

劣势:

  • 只能限定于VoIP类App使用。如无这VoIP功能,如果将App上传到AppStore,则会被拒绝。(虽然看起来没有问题,但是苹果就是这么“吹毛求疵”)

听名字就知道,这个方案是Apple专门为VoIP类App量身定制的。如果你的App并没有VoIP相关功能,在提交AppStore时会被拒绝,但是如果你只是企业内部分发,并不提交AppStore审核的话,就没有啥问题了。使用方法如下:

步骤一、在XCode中为你的Ap工程打开Background Modles,并勾选Voiceover IP选项,等于告诉iOS操作系统你需要此项功能,系统不能在后台强制杀掉我的进程,因为我要在后台进行一些操作。


同时,也可以在工程的plist文件中加入如下选项:

Key:Required background modes

Value:App provides Voice over IP services


步骤二、在需要后台运行的地方执行操作

    [[UIApplication sharedApplication] setKeepAliveTimeout:600 handler:^{
       //干活
    }];

这个函数会以设定的时间间隔被调用,不仅仅在后台,App在前台时候,这个函数一样能够被调用。所以可以把它当作一个横跨前后台的NSTimer来使用。

注意:

1、间隔时长必须大于600s,适合和服务器保持通讯,保证用户登录状态。

2、复活后,执行时间只有10s,之后又继续挂起。

3、 使用clearKeepAliveTimeout来取消唤醒

4、app必须是能和VoIP功能相关的内容,否则提交App Store会被拒绝。


二、Background fetch方式:

优势:

  • 是官方推荐的后台数据刷新方法
  • 实现比较简单

劣势:

  • 程序被唤醒执行的时间不可控
  • 被唤醒后执行时长有限制

步骤一、设置Background fetch:



步骤二、设置被唤醒最小时间间隔

[applicationsetMinimumBackgroundFetchInterval:1.0f];


步骤二、需要执行的代码片段

 - (void)application:(UIApplication *)applicationperformFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler

 

注意:

1、代码被执行的时间间隔不可控,操作系统会以科学的方式来调用。

2、设置的时间只是最小时间间隔、操作系统只能保证在最小时间间隔内不会被调用,但是至于是1m还是1h还是多长时间调用,与操作系统当前的状态、用户打开App的频率有关系。

3、被操作系统唤醒后,只能有30s的时间执行你的任务,30s后,将被再次挂起。按说以国内的网络环境来说,基本上30s都能解决问题了。

 

三、播放空白声音配合“backgroundTask”进行后台运行

优势:

  • 适用于需要进行后台播放音乐,记录地理位置变化等功能的App
  • 可以用来进行一些简单的后台操作(如保活),而不被AppStore的审核人员拒绝,比较隐蔽
  •  唤醒时间间隔可控

劣势:

  • 实现相对于其他几种方案都要麻烦

步骤一:在Info.plist中,添加"Required background modes"键,value为:App plays audio,申明你需要使用后台播放音频的功能。

 

步骤二:调节音频会话的特性:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
    // Override point for customization after application launch.
    NSError *setCategoryErr = nil;
    NSError *activationErr  = nil;
    [[AVAudioSession sharedInstance]
     setCategory: AVAudioSessionCategoryPlayback
     error: &setCategoryErr];
    [[AVAudioSession sharedInstance]
     setActive: YES
     error: &activationErr];
    self.window.backgroundColor = [UIColor whiteColor];
    [self.window makeKeyAndVisible];
    return YES;
} 

步骤三、将以下 代码添加到appDelegate文件中的- (void)applicationDidEnterBackground:(UIApplication *)application函数,也可添加到在具体类中注册的应用进入后台后的通知方法
- (void)applicationDidEnterBackground:(UIApplication *)application{
    UIApplication*   app = [UIApplication sharedApplication];
    __block    UIBackgroundTaskIdentifier bgTask;
    bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
        dispatch_async(dispatch_get_main_queue(), ^{
            if (bgTask != UIBackgroundTaskInvalid)
            {
                bgTask = UIBackgroundTaskInvalid;
            }
        });
    }];
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        dispatch_async(dispatch_get_main_queue(), ^{
            if (bgTask != UIBackgroundTaskInvalid)
            {
                bgTask = UIBackgroundTaskInvalid;
            }
        });
    });
}

这样,就可以在你需要重复执行的地方,实现一个NSTimer,有了上面的步骤之后,你的NSTimer就能不论前台后台都可以运行了。


注意:

和前三个不一样,前三个解决方案是程序被挂起之后又被唤醒,但是,这个解决方案是程序一直在后台运行,会非常耗内存,需要开发者关注。


四、远程消息推送,激活

优点:

  • 实现简单
  • 唤醒时间可控,由后台控制

缺点:

  • 需要后台编码,跑服务进行App唤醒

步骤一、服务端设置推送的消息中加上“content-available”:

{
     "aps" : {
          "content-available" : 1
     },
     "content-id" : 42
}


步骤二、在接收消息的地方,进行唤醒后需要的操作



五、利用NSURLSession进行background transfer task


这种解决方案详见参考资料: http://www.starming.com/index.php?v=index&view=69
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值