iOS 后台运行实现总结

作者: zhenby | 来源:发表于2015-10-19 10:01 被阅读18853次

    iOS 后台运行的规则

    应用的运行状态分为以下五种:
    Not running:应用还没有启动,或者应用正在运行但是途中被系统停止。
    Inactive:当前应用正在前台运行,但是并不接收事件(当前或许正在执行其它代码)。一般每当应用要从一个状态切换到另一个不同的状态时,中途过渡会短暂停留在此状态。唯一在此状态停留时间比较长的情况是:当用户锁屏时,或者系统提示用户去响应某些(诸如电话来电、有未读短信等)事件的时候。
    Active:当前应用正在前台运行,并且接收事件。这是应用正在前台运行时所处的正常状态
    Suspended:应用处在后台,并且已停止执行代码。系统自动的将应用移入此状态,且在此举之前不会对应用做任何通知。当处在此状态时,应用依然驻留内存但不执行任何程序代码。当系统发生低内存告警时,系统将会将处于 Suspended 状态的应用清除出内存以为正在前台运行的应用提供足够的内存。
    Background:应用处在后台,并且还在执行代码。一般的应用,都只会在这个状态短暂停留(最多十分钟),然后就会被系统强制进入 Suspended 状态。而 iOS 为了在某些情况下提供更好的体验,提供了一些选项,只要满足这些选项的条件,就可以在后台运行很长的一段时间,下面我们将重点讨论可以使应用在后台长时间运行的方法。

    iOS 应用状态切换示意图


    iOS 提供的后台运行方式

    iOS 提供的后台运行方式列表

    上图为 iOS 提供的后台运行方式列表,如果需要,可在 Xcode 的项目设置中开启对应的选项。App Store 的审核人员会检查应用中是否有必要开启该后台运行模式选项,如果应用中不需要,而又开启了这个选项,可能会被拒。        

    Audio, AirPlay and Picture in Picture

    此个选项包含四种场景,分别是:音频的播放,录音,AirPlay 及画中画的视频播放。
    音频的播放:在播放音频时,即使应用退到后台,只要一直有音频在播放,那应用就可以一直在后台运行。
    代码实现可参考:http://www.linuxidc.com/Linux/2012-08/68364.htm

    录音:应用可以请求使用麦克风,而当开启了此后台选项,应用在使用麦克风的时候,即使退到后台,也可以一直后台运行,通过查看微信安装包中的 plist 文件,微信的语音聊天,就是通过这种方式实现的。而当该类应用退到后台后,iOS 系统的状态栏会变成红色,并在状态栏中显示正在使用麦克风的应用的名称,如下图所示。

    正在使用麦克风提示

    AirPlay:AirPlay 是指将 iOS 设备,或者 Mac 设备上的音视频,同步到另一个设备中播放。举两个例子,第一个是把 iPhone 上的音乐通过蓝牙的方式在汽车的蓝牙音响播放,第二个是把 iPhone 上的视频,同步到智能电视屏幕上播放。此功能一般用于多端及多屏的交互。
    关于 AirPlay 的开发文档:http://nto.github.io/AirPlay.html

    画中画的视频播放:画中画是 iPad 版本的 iOS 9 新增加的功能,可以在 iOS 的桌面,或者其他应用的界面的上面播放视频,从而该视频区域所属的应用就可以后台运行了。此功能现在只在 iPad 应用中提供
    代码实现可参考:http://www.cocoachina.com/ios/20150714/12558.html

    Location updates

    一般用于导航应用中,开启此选项后,应用退到后台,还可以得到系统的定位更新,从而使得应用可以根据定位的变化做出不同的反应。
    代码实现可参考:https://github.com/voyage11/Location

    Voice over IP

    VOIP 类的应用允许用户使用网络而不是手机打电话,因此这一类的应用需要保持同它相关的服务的网络连接,用以收到来电事件和其他数据。iOS 不是通过一直让该应用处于激活状态来达到这个目的,而是同样也会将这类的应用挂起,但同时会在应用被挂起期间由系统接管它的 VOIP 的 Socket当这个 Socket 有数据通信时系统会再次唤醒处于挂起状态的应用,同时将 Socket 的控制权交还给该应用,以让其正常的处理来电事件和其他数据。 

    Newsstand downloads

    在 iOS 开发中,有一类叫报刊杂志类应用比较特别,在 iOS 9 之前的系统中,此类应用会统一收在系统内置的「报刊杂志」应用中,在 iOS 9 中则去掉了内置的「报刊杂志」应用,此类应用得以以单独的图标入口出现在桌面中。
    此后台运行的选项就是提供给报刊杂志类应用可以在后台下载及处理报刊杂志内容,而下载的过程需要使用 NewsstandKit 中的 NKAssetDownload 进行下载。需要注意的是,下载的过程中应用可能还是会被挂起甚至应用被退出,而 iOS 会在 Wi-Fi 环境下继续下载,直到下载完成。而一旦下载完成,如果应用只是被挂起,则 iOS 会唤醒对应的应用,回调对应的事件;如果应用已经退出则会启动应用,在启动参数中会带上对应的标识表示这次启动是因为下载报刊杂志内容完成。
    代码实现可参考:http://www.viggiosoft.com/blog/blog/2011/10/17/ios-newsstand-tutorial/ 

    External Accessory communication

    此选项提供给一些 MFi 外设通过蓝牙,或者 Lightning 接头等方式与 iOS 设备连接,从而可在外设发送消息时,唤醒已经被挂起的应用。而一旦被唤醒,一般情况下, 应用只有最多 10 秒钟的执行时间。
    MFi 外设:是指通过苹果 MFi 认证的设备,而 MFi 认证是对其授权配件厂商生产的外置配件的一种标识使用许可,是 Made for iOS 的英文缩写。

    Uses Bluetooth LE accessories

    此选项与 External Accessory communication 类似,只是此选项无需限制 MFi 外设,而需要的是 Bluetooth LE 设备。

    Acts as a Bluetooth LE accessory

    此选项是指 iOS 设备作为一个蓝牙外设连接时,对应的应用可以后台运行,但是使用此模式需要用户进行授权认证。

    Background fetch 

    iOS 7 新增加的一个选项,用于即使在后台,也需要频繁更新数据的应用。例如一个 PM2.5 的应用,需要几个小时更新一次数据,那么可以开启此选项,设置一个时间间隔,从而让 iOS 在间隔时间内在后台启动该应用,执行指定数据的获取工作,而此过程最多只能执行 30 秒钟。
    代码实现可参考:http://objccn.io/issue-5-5/

    Remote notifications

    iOS 7 新增加的一个选项,是一种静默推送,它有别于一般的推送,应用收到此类推送后,不会有任何的界面提示,而当应用退出或者挂起时收到此类推送,iOS 也会启动或者唤醒对应的应用。
    例如一个阅读应用,用户订阅的博客更新了,那么可以先发一个静默推送,应用收到此种推送后,可以先把用户订阅的博客内容都下载好,再通知用户,这样用户一打开应用就可以马上开始阅读。
    收到静默推送,会回调对应的回调方法,而此回调方法最多只能执行 30 秒钟。
    代码实现可参考:http://objccn.io/issue-5-5/

    基于 NSURLSession 的后台传输

    此为 iOS 7 新增加的特性,用于在后台下载或者上传大文件,步骤如下:创建后台传输用的 NSURLSession 对象;向这个对象中加入对应的传输的 NSURLSessionTask,并开始传输;在实现 AppDelegate 里实现 -application:handleEventsForBackgroundURLSession:completionHandler: 方法,以刷新 UI 及通知系统传输结束。
    一旦后台传输的状态发生变化(包括正常结束和失败)的时候,应用将被唤醒并运行 AppDelegate 中的回调。
    但是也有一些限制,后台传输只会通过 Wi-Fi 来进行。后台下载的时间与以前的关闭应用后X分钟的模式不一样,而是为了节省电力变为离散式的下载。
    代码实现可以参考:http://onevcat.com/2013/08/ios7-background-multitask/

    其他后台运行黑魔法

    一直循环播放一段没声音的音频

    可以在后台选项中选择「Audio, AirPlay and Picture in Picture」,而开始循环播放一段是没声音的音频,即在 Audio Unit 回调函数中使用 kAudioUnitRenderAction_OutputIsSilence 标志位,但是这种方式两个大的缺点:
    1. 苹果的审核人员如果发现,会被拒;
    2. 应用程序的 Audio Session 不能被打断。当应用执行在后台时,只要另一个应用使用 kAudioSessionCategory_RecordAndPlay (比如 Skype)或者 kAudioSessionCategory_SoloAmbientSound,那么该应用就会被立即打断。
    代码实现可参考:https://github.com/marcop/MMPDeepSleepPreventer

    越狱下开发 System 级别的应用

    一般的应用都是 Mobile 级别的,在越狱的情况下,可以开发一个 System 级别的应用,从而使得应用不受 iOS 一般应用的限制,实现真正的后台运行,但是缺点就是应用只能运行在越狱设备上,也不能上 App Store。
    代码实现可参考:http://www.cnblogs.com/doudouyoutang/p/4712331.html

    相关文章

      网友评论

      • 喔牛慢慢爬:楼主你好,基于 NSURLSession 的后台传输,进入后台下载可以继续下载,但大约超过10分钟再回到前台UI停止更新,NSURLSession的代理方法无法回调,暂停/恢复后可以继续下载。什么原因引起的这个问题?
      • 陈藩:我做的蓝牙项目,退到后台10min之后也不运行了,请问是为什么呢
      • jianshu小赵:非常赞 链接完备
      • 3ef656fe73b2:你好大神!我们现在研发app遇到一个难题:我们的app在后台可以接收iBeacon的信息推送,但我们需要在接受到iBeacon推送后,在后台执行一段计算,并随后向iBeacon发送指令。请问这能做到吗?就像ios自带的地图一样,当汽车一启动,立马弹出回家路线提示。
      • coding_Liu:我想问一下 我怎么能在我应用在运行时,不因为一个电话或短信而导致中断 没什么思路求大神指点一二
      • 3b8a70fdc4af:你好, 我想问一下

        App 客户端和服务端通过SIOSocket进行通讯, 服务器端发一个事件过来(附带图片下载链接), App 就开始下载并保存到系统相册. 这个在前台都没什么问题, 但是 App 切换到后台后, App 就接收不到 Socket 事件了.如果在后台也能实现这个功能, 请问应该怎么做?
      • imageURL:不错的文章,
      • guitarJason:iOS10之后,貌似后台都失效了,不管配置什么background mode都没有用,只要一点击Home键进入后台,代码就会立马停止执行了。请问你是这样的吗?
        74acb3e683ec:这个问题还有人再跟吗?我也是遇到IOS一进入后台就不执行代码了,应用未被杀死,安卓的确可以运行
        暮雨飞烟:@guitarJason 但是我觉得语音这个还是会留的.其他的功能也有的会留,反正socket是不行了,不知道层主的是什么不行了
        暮雨飞烟:@guitarJason 我的是这样的,看来只能PUSHKIT了
      • xuzhenhao:你好,我的应用在退到后台时,会显示红色的状态栏并一闪而过,请问是什么原因?
      • F麦子:你好,我想问你一个问题,公司需求是应用用定时器每隔两秒向服务器发送一次请求,返回一些字段,证明用户还在线,但是每当锁屏后定时器就停止了,不能发送请求了,如何在锁屏状态下继续发送请求。。谢谢
        42fbf29fd40d:@X堇色 哥们。问题解决了吗?
        zhenby:@X堇色 除非你的应用声明并在退到后台的时候使用了上面的任意一种后台运行方式,不然应用退到后台最多运行十分钟就会被挂起的。
        你可以根据应用的性质判断是否符合上面哪种后台的运行方式,也判断一下后台运行的必要性,如果没必要,建议就不专门搞后台运行了,如果服务器判断到用户不在线了,直接走推送就行了。
      • GodLoveNan:大神,您好, 我做地图轨迹这块,我想在后台记录他的轨迹,要后台长时间(超过10分中)运行不被杀死,怎么解决?
        a1e729580a0c:@GodLoveNan 楼主你的问题解决了吗请问,我做的和你类似也遇到这个问题了
        GodLoveNan:@zhenby 到时,到后台了,他里面的代码都不执行了啊
        zhenby:@GodLoveNan Location updates,一般用于导航应用中,开启此选项后,应用退到后台,还可以得到系统的定位更新,从而使得应用可以根据定位的变化做出不同的反应。
        代码实现可参考:https://github.com/voyage11/Location
      • ask_ME:你好,看到你的文章让我受益匪浅,写的很好,我想询问一下如果开启定时器无限借时间会怎么样??tks(我想实现无限后台,但是不实现相应功能,怎么办)
        我叫没名字啊:@拾忆Silence 你是用timer,然后创建scheduled事件么?要是这么的话,进后台确实不运行的,除非写个死循环,确实会一直输出,但也没啥意义了
        拾忆Silence:@zhenby 为什么我起个定时器,然后每秒打印一次,却可以一直打印呢?没有申请任何权限,完全是一个刚创建的project。
        zhenby:@ask_ME 要先有后台运行权限(Audio、VOIP、GPS 等),退到后台才可以无视最多十分钟的后台运行时间。开启了定时器,但是没有后台运行权限,也是只能最多后台运行十分钟。
      • L05T:您好,请问能否自定义后台挂起程序后状态来的样子吗,比如,颜色,文字等,类似滴滴打车正在打车时的样子,请问实现思路是怎样的呢?
      • b11c00f814f6:你好, 请问我需要做微信语音通话类型的推出程序状态栏变红, 具体做法是什么呢? 谢谢了
        zhenby:@呼了赛 勾上 Audio, AirPlay and Picture in Picture 这个后台选项,然后在应用中打开麦克风(第一次需要用户允许),这时把应用退到后台,状态栏就会有红色的「正在使用麦克风」的提示条了。
      • 622273fab944:楼主好,我用一直循环播放一段没声音的音频使app一直后台运行,可是提交审核被打回了 原因2.16
        谢衣丶:@zhenby 如果我只是做一个类似音频播放器的应用 开启这个 有被拒的可能吗?
        622273fab944:@zhenby 谢谢
        zhenby:@知尔饮清溪 如果被发现的话,确实是会被拒的,文章里面也说到了被拒的可能了。建议根据应用的使用场景来选择后台运行的方式。
      • 88dc77c46a87:你提到““此个选项包含四种场景,分别是:音频的播放,录音”,这里应该不包括录音吧?苹果文档中明确只指出支持音频播放(play audible content),
        74acb3e683ec:这个问题还有人再跟吗?我也是遇到IOS一进入后台就不执行代码了,应用未被杀死,安卓的确可以运行
        zhenby:@ikzjfr0 不单单是音频播放,文档写的是:The app plays audible content to the user or records audio while in the background. 里面有包括 records audio

      本文标题:iOS 后台运行实现总结

      本文链接:https://www.haomeiwen.com/subject/uzsacttx.html