iOS系统后台运行机制研究
来源:互联网 发布:淘宝鹊桥活动怎么退出 编辑:程序博客网 时间:2024/06/05 18:21
众所周知,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;}
- (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
- iOS系统后台运行机制研究
- iOS后台运行机制
- IOS后台运行机制详解
- iOS后台运行机制1
- IOS后台运行机制 与 动作
- IOS后台运行机制 与 动作
- IOS后台运行机制详解(一)
- IOS后台运行机制详解(二)
- IOS后台运行机制详解(一)
- IOS后台运行机制详解(二)
- iOS开发-iOS7后台的运行机制
- IOS后台运行机制详解(一)
- IOS后台运行机制详解(二)
- iOS后台运行机制详解(一)
- iOS后台运行机制详解(二)
- IOS后台运行机制详解(一)
- IOS后台运行机制详解(二)
- iOS后台多任务研究
- weblogic启动失败:Could not obtain the localhost address 解决办法
- UIView的setNeedsLayout, layoutIfNeeded 和 layoutSubviews 方法之间的关系解释
- opencv notes
- matlab中的文件读写操作
- linux下重启weblogic(关闭和启动)nohup的使用
- iOS系统后台运行机制研究
- 在iOS开发中使用icon font的方法
- *LeetCode-Insert Interval
- 无法远程登录linux上weblogic控制台 防火墙查看和设置
- 通过sftp向阿里云服务器(linux)上传文件失败!
- LightOJ 1017 - Brush (III)【一般DP】
- AOJ 2450 Do use segment tree (树链剖分 + 线段树区间合并)
- Valid Parentheses Java
- {Effective Java} Chap 7 Methods