后台机制的不同,算是iOS 和 Android的一大区别了,最近发布的iOS7又对后台处理做了一定的更改,找时间总结一下编码上的区别,先做个记录。
先看看iOS的把,首先需要仔细阅读一下Apple的官方文档 iOS App Programming Guide中的App States and Multitasking,其中的Background Execution and Multitasking部分要仔细阅读。
ios的程序有5种状态,not running,inactive, active, background,suspended.其中,符合“标准的后台运行”的,只有background这个状态。但是这个状态的时间是有限制的,ios6最长约10分钟,ios7最长约3分钟。在这段时间内,即使系统锁屏也不会对程序的执行产生影响。To request background execution time, call the beginBackgroundTaskWithName:expirationHandler: method of the UIApplication class. 这种task也被称作Finite-Length Background Task。
与Finite-Length Background Task 相对的,有Long-Running Background Tasks,这种task在表现上就是在后台运行的任务,但是,它的类型是有限制的,并且需要在xcode中注册,导入对应的framework。现在支持的类型有,听音频,录音,获得地理位置,网络电话,下载数据,获得传感器数据。感觉上,下载数据可能是用处比较多。
Xcode mode |
UIBackgroundModes value |
Description |
---|---|---|
Audio |
|
The app plays audible content to the user or records audio while in the background. (This content includes streaming audio or video content using AirPlay.) |
Location updates |
|
The app keeps users informed of their location, even while it is running in the background. |
Voice over IP |
|
The app provides the ability for the user to make phone calls using an Internet connection. |
Newsstand downloads |
|
The app is a Newsstand app that downloads and processes magazine or newspaper content in the background. |
External accessory communication |
|
The app works with a hardware accessory that needs to deliver updates on a regular schedule through the External Accessory framework. |
Bluetooth networking |
|
The app works with a Bluetooth accessory that needs to deliver updates on a regular schedule through the Core Bluetooth framework. |
Bluetooth data sharing |
|
The app supports Bluetooth communication in peripheral mode through the Core Bluetooth framework. Using this mode requires user authorization; for more information, see “Best Practices for Maintaining User Privacy.” |
Background fetch |
|
The app regularly downloads and processes small amounts of content from the network. |
Remote notifications |
|
The app’s response to a push notification includes optionally downloading content related to the notification. The purpose of downloading the content in the background is to incorporate it and be able to present it immediately when the user responds to the push notification. |
根据不同的类型,后台的表现也不太一致。
1.Background fetch
采用Background fetch 类型时,系统会根据情况自动去调用- (void)application:(UIApplication *)application performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler 方法,但是经过我用ipad测试,我发现这个方法调用的频率并不高,如果你想利用这个函数做一些频率高的检测工作,恐怕是不行了!以下是我测试一小时的数据(我的设置 [[UIApplication sharedApplication] setMinimumBackgroundFetchInterval:UIApplicationBackgroundFetchIntervalMinimum];)
2014-03-02 22:08:02.353 BackgroundTest[2259:60b] performFetchWithCompletionHandler 2014-03-02 22:25:49.829 BackgroundTest[2259:60b] performFetchWithCompletionHandler 2014-03-02 22:38:48.132 BackgroundTest[2259:60b] performFetchWithCompletionHandler 2014-03-02 23:05:01.594 BackgroundTest[2259:60b] performFetchWithCompletionHandler
从22.38开始,我开始使用了其他的应用,系统一直保持运行,结果到了11.05我不再使用,快待机前,系统才掉用了performFetchWithCompletionHandler函数,间隔几乎是30分钟!如果你一直运行占用系统资源较多的程序,我怀疑这个方法会不会一直不被调用。所以正如官方说明的,这个方法是用来下载一些小的数据的,目的是提前下载好资料,不需要用户等待数据下载,提高用户体验。如果你的程序按照这个标准去利用这个方法,那么当performFetchWithCompletionHandler不被系统调用时,也不会产生任何问题----用户只是在进入程序时需要多等待一会儿,去下载数据。然而,如果你打算利用这个方法去做一些特别的后台操作,就很有可能因为performFetchWithCompletionHandler不被系统及时调用而产生各种bug。
2 Remote notifications
ios7 前,一个远程的通知不具备在后台调用代码的功能。ios7中加入了这个功能。When this value is present and a push notification arrives on a device, the system sends the notification to your app (launching it if needed) and gives it a few moments to process the notification before displaying anything to the user. You can use those few moments to download content related to the push notification and be ready to display it to the user.
另外需要注意下列问题!
As soon as you finish processing the notification, you must call the block in the handler parameter or your app will be terminated. Your app has up to 30 seconds of wall-clock time to process the notification and call the specified completion handler block. In practice, you should call the handler block as soon as you are done processing the notification. The system tracks the elapsed time, power usage, and data costs for your app’s background downloads. Apps that use significant amounts of power when processing remote notifications may not always be woken up early to process future notifications.
从这里看出我们应该尽快调用completionHandler,防止系统组织程序的后台运行。但是如果我们故意立即调用completionHandler,而事实上还继续执行代码会怎么样呢?
//请参阅下面的文档,文档原地址为
http://docs.jpush.cn/display/dev/iOS+7+Background+Remote+Notification
为了防止原链接失效,拷贝如下:
简介
本次iOS 7在推送方面最大的变化就是允许,应用收到通知后在后台(background)状态下运行一段代码,可用于从服务器获取内容更新。功能使用场景:(多媒体)聊天,Email更新,基于通知的订阅内容同步等功能,提升了终端用户的体验。
Remote Notifications 与之前版本的对比可以参考下面两张 Apple 官方的图片便可一目了然。
如果只携带content-available: 1 不携带任何badge,sound 和消息内容等参数,则可以不打扰用户的情况下进行内容更新等操作即为“Silent Remote Notifications”。
客户端设置
开启Remote notifications
需要在Xcode 中修改应用的 Capabilities 开启Remote notifications,请参考下图:
修改通知处理函数
当注册了Backgroud Modes -> Remote notifications 后,notification 处理函数一律切换到下面函数,后台推送代码也在此函数中调用。
- ( void )application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:( void (^)(UIBackgroundFetchResult))completionHandler; |
服务端推送设置
推送消息携带 content-available: 1 是Background 运行的必须参数,如果不携带此字段则与iOS7 之前版本的普通推送一样。
(这里是重中之重!以前测试时,就是因为没有设定这个参数,导致无法出发后台执行效果,还以为是ios的bug!)
使用Web Portal 推送
在“可选设置内”选择对应的参数。
使用 API 推送
只需在 Push API v2 的 n_extras->ios 内附加content-available":1 字段即可
{ "n_content" : "通知内容" , "n_extras" :{ "ios" :{ "content-available" : 1 , "badge" : 88 , "sound" : "happy" }, "user_param_1" : "value1" , "user_param_2" : "value2" }} |
限制与注意
- “Silent Remote Notifications”是在 Apple 的限制下有一定的频率控制,但具体频率不详。所以并不是所有的 “Silent Remote Notifications” 都能按照预期到达客户端触发函数。
- “Background”下提供给应用的运行时间窗是有限制的,如果需要下载较大的文件请参考 Apple 的 NSURLSession 的介绍。
- “Background Remote Notification” 的前提是要求客户端处于Background 或 Suspended 状态,如果用户通过 App Switcher 将应用从后台 Kill 掉应用将不会唤醒应用处理 background 代码。
更详细的说明资料请查阅 Apple 官方的 iOS 开发文档。
3 .newsstand downloads
再看看Android,Android中的Service就可以实现真正的后台运行。A Service
is an application component that can perform long-running operations in the background and does not provide a user interface. Another application component can start a service and it will continue to run in the background even if the user switches to another application.
什么时候一个service会被强制结束呢?The Android system will force-stop a service only when memory is low and it must recover system resources for the activity that has user focus. If the service is bound to an activity that has user focus, then it's less likely to be killed, and if the service is declared to run in the foreground (discussed later), then it will almost never be killed.