Apple 一直在逐步放大 App 后台运行的权限,到今天为止,已知的 iOS App 后台运行场景有:

Background Task

通常情况下,App 一旦进入后台,只有数秒的时间继续执行代码,之后就会被系统 Suspend。除非 App 显示的调用 beginBackgroundTaskWithExpirationHandler API,能延迟 App 在后台运行代码的时间,iOS 7 之前是 10 分钟,iOS 7 之后缩减至 3 分钟。一旦时间期限到,系统依旧会 Suspend 进程。

Suspend 进程意味着系统会中断 App 的一切代码逻辑,比如所有线程会暂停,内存读写会暂停,文件访问也会中断,比如 sqlite 读写操作即使写至一半,也会进入暂停状态。理解这一点,能更好的分析我们 App 在后台的行为。

对于大部分 App 来说,都会利用 Background Task 机制来延长后台运行时间,不过一旦 App 体量增大,业务场景增加,我们很难保证所有的代码在进入后台之后,都会被封装到 Background Task 之中执行,很难确保 Background Task 一旦 expire,App 会主动暂停所有内部逻辑,做一个 iOS 系统遵法守纪的好公民。

想象下,App 在 Background Task 里发送一个网络请求,由于延迟较大,后台运行 3 分钟即将超时 response 才回来,进而触发一些列代码逻辑,比如写数据库,此时由于后台时间额度已用完,iOS 系统会强行终止进程,App 的状态会变得不可预知。

虽然 Apple 建议 App 在进入后台后应该运行尽可能少的关键任务,但这种规范对于业务类型复杂的 App 很难遵循,我们能做的,就是在进入后台 3 分钟之内,尽可能完成核心任务,而且不触发新的代码流程。

Background Mode

开启这种模式的 App 可以一直在后台运行,像早期的 VOIP 类应用,导航类 App,支持后台播放音乐的 App 以及一些蓝牙类 App 都需要这种 Background Mode 来正常运行核心功能。开启这种模式的副作用是审核严苛,而且耗电严重,用户会比较敏感。

Background Fetch

这是 Apple 提供的,在系统指定的时间段唤醒 App 并执行少量逻辑的机制,限制较多,唤醒并不可靠,比如被用户强杀的 App 无法唤醒,比如有些用户为了省电考虑,会在系统设置里强行关闭所有的 background fetch。

Silent Push

这是通过 APN 里设置特定字段来唤醒 App 的机制,同 Background fetch 限制较多,在强杀时无法唤醒。

PushKit

PushKit 是用来替代 VOIP 后台运行模式的新机制,在收到语音或者视频电话时,可以通过 PushKit 的通知来唤醒 App,从而避免 App 在后台一直运行。通过 PushKit 唤醒来唤醒 App 非常可靠,基本上具备 VOIP 功能的 App 都会使用这一机制来提升 App 体验。

PushKit 的后台运行模式非常有趣,据我观察,一般情况下,后台唤醒后有 30 秒(并不精准,只是大致接近)的运行时间,如果唤醒后开启 Background Task 能将运行时间延长至 40 秒。

如果 30 秒内连续收到两个 PushKit 通知,那么 App 总共的后台运行时间加起来还是 30 秒,如果 30 秒之后被 Suspend,再收到第二个 Push,那么又可以获得额外的 30 秒。有点类似 Session 的概念,每次收到 Push 可以启动一个 30 秒的 Session,一个 Session 可以处理多个 Push,一旦 Session 结束就被系统 Suspend,再次收到 Push 时可以启动一个新的 Session。

Background Crash 调查

以上是 iOS App 后台运行的现有机制的简单介绍,最近在调查一个 background crash,需要用到上述的后台运行机制。

用户抱怨 App 的 cold start 非常频繁,导致耗电严重。

起初怀疑是 background crash,问题是,开发人员检查了后台日志,发现并无相关的 crash 记录。那么有可能是 BOOM,但 BOOM 发生的概率一般来说比较低。

后来在拿到问题手机之后,查看 analytics 日志,发现如下 crash report:

image.png

很显然 App 是在后台时被系统强杀,原因是在后台运行时还持有某个 db 文件的锁。code 为 0xdead10cc,搜索 Apple 官方文档:

The exception code 0xdead10cc indicates that an application has been terminated by iOS because it held on to a system resource (like the address book database) while running in the background.

原因有了大致方向,接下来时分析具体 Crash 场景。通过仔细查看 App 的运行日志之后,分析出以下行为:

App 在后台首先通过 PushKit 被唤醒,获得 30 秒的运行时间,在 30 秒即将结束的时候,收到新的 PushKit 通知,进而触发一些列流程,比如 sqlite 读写,而因为 30 秒后台时间已用完,系统会强行 suspend App 进程。

系统在 suspend 进程之前,会多做一道检查,如果 App 此时持有 sqlite db 文件的锁(比如正在进行写操作),而且所访问的 sqlite db 文件是位于 shared container 目录下,系统会强杀进程,并生成一个类似上面的 Crash Report。

系统为什么要这么做?很简单,如果 sqlite db 文件是位于 shared container,意味着该文件会同时被 App 和 Extension 访问,假设 App 的写操作在执行中途被 suspend 暂停,Extension 唤醒后也对同一个 db 文件执行写操作,那么当 App 被重新唤醒继续之前写操作时,写操作和 db 文件就会处于一个不可预知的状态,有可能造成写操作失败或者 db 文件损坏,所以系统选择强杀 App。

即使明白了 Crash 过程,要修复却并不简单。原因就像文章开头提到的,一个大体量的 App 在进入后台之后,其代码的执行场景会变得十分复杂,我们并没有简单的机制来确保,进入后台后的流程都能在系统限制的时间内完成,只能通过日志一个个模块排查,简化 App 进入后台之后的行为。

其他收获

另外值得一提的是,从这次 Crash 调查可以看出,并不是所有的 Crash 都能通过 App 内部的 Crash 收集工具获得日志,已知的至少有这几类 Crash 是无法被 App 捕获的:

前台主线程卡死,App 被 Watchdog 强杀

App 在前台或者后台使用过多的内存,被系统强杀,分别为 FOOM 和 BOOM。

App 在后台被 suspend 之后,由于违反 Apple 的某个 policy,而被系统强杀。

所以你的 App 即使有了成熟的 Crash 采集工具和后台,有时候还是需要登陆 Itunes Connect 后台去查看下日志,或者通过 Xcode 直接查看,因为有些系统强杀并不会通知 App,只有系统能生成和获取日志。这些日记也可以通过用户手机查看,位于 Settings->Privacy->Analytics->Analytics Data。

Ios android crash report,iOS App 后台 Crash 调查相关推荐

  1. webdav ios android,iWork(iOS 版):使用 WebDAV 服务

    如果您有权访问 WebDAV 服务器,则可通过 iOS 设备传输 iWork(iOS 版)文稿,例如将类似文稿拷贝到 WebDAV 服务器,或从该服务器拷贝类似文稿.按照以下步骤执行此操作. 在 iW ...

  2. Android借助Application重写App的Crash(简易版)

    MainActivity如下: package cn.testcrash; import android.app.Activity; import android.os.Bundle; /*** De ...

  3. 国内用户ios android比例,国内iOS、Android系统的设备总量已达到了2亿

    首先,在2012年第三季度时,国内iOS.Android系统的设备总量已达到了2亿.在今年3月的时候,这一指标只有8700万,也就是说设备在半年内增长了125%.而在设备量大增的同时,用户也变得依赖移 ...

  4. ios android md5加密,iOS中使用MD5加密

    在iOS中使用MD5加密较简单,需要引入头文件CommonCrypto/CommonDigest.h,我们单独新建一个用于MD5加密的类Encryption,此类继承NSObject. Encrypt ...

  5. ios android 手柄,升级至iOS 13系统iPhone现已支持Xbox手柄

    今天(9月20日)iOS 13系统正式推送上线,更新至iOS 13系统的iPhone设备现已可通过蓝牙支持Xbox手柄.PS4手柄.iOS设备支持Xbox手柄对于iOS平台游戏.Apple Arcad ...

  6. 潮人篮球ios android,潮人篮球ios怎么在电脑上玩?潮人篮球ios电脑版玩法教程!...

    潮人篮球ios怎么在电脑上玩呢?现在有很多小伙伴都在玩潮人篮球手游,不过相对于传统的在手机上进行游戏,很多人都倾向于新玩法,就是在电脑上玩潮人篮球.下面小编就给亲们介绍下潮人篮球ios电脑版玩法教程哈 ...

  7. 了解和分析iOS Crash Report

    翻译自苹果官方文档:Understanding and Analyzing Application Crash Reports nimo: 这篇长达1w多字的文章,大概前后翻译了一个月,"写 ...

  8. h5和ios/android交互

    我们的App项目属于混合式开发,ios/Android负责打包,app里面点击时通过地址跳入我们的h5页面. 问题1:ios调用h5方法并传参 //ios调用h5方法,必须将事件暴露在window中供 ...

  9. 处理、分析iOS App的Crash Reports

    分析Crash report Apple的官方文档:Understanding and Analyzing iOS Application Crash Reports iOS设备上,当app崩溃时会创 ...

  10. android极光推送在app开启后,在ios上,app后台运行时,如何在极光消息推送过来时,运行一段自定义的代码(请求,语音播报等)...

    通常情况下,app在ios上后台运行时,发送的推送无法被app监听,并执行自定义操作. 这个时候,需要发起Remote Notifications(ios7开始支持后台) ios7和ios6对比: 可 ...

最新文章

  1. 利用Flume将MySQL表数据准实时抽取到HDFS
  2. LDAP落地实战(三):GitLab集成OpenLDAP认证
  3. java 正则首位8或者9的8位数字_Python 正则表达式re最完整的操作教程
  4. Java 集合系列07之 Stack详细介绍(源码解析)和使用示例
  5. LeetCode 1865. 找出和为指定值的下标对(哈希)
  6. Linux Shell脚本入门教程系列之(十四) Shell Select教程
  7. PHP面向对象中new self( )和 new static( ) 的区别
  8. finallshell使用_Finalshell软件安装使用
  9. 基于Bokeh库,手把手教你制作“子弹图“和“瀑布图“!
  10. Pop3_解决PKIX:unable to find valid certification path to requested target 的问题
  11. html语言考点,HTML知识点
  12. ue4是什么意思_UE4 C++基础教程 - 资源常见名词解释
  13. 局域网文件共享服务器软件,局域网文件夹加密工具哪个好?文件共享服务器软件介绍...
  14. webservice接口开发学习笔记(一)
  15. 骑士人才系统后台用户名密码重设工具源码
  16. 如何下载无水印的抖音视频?
  17. 函数9:生成器和 yield 语句
  18. git 加速代理设置,单仓库设置代理,指定仓库设置单独代理
  19. 13.JVM-垃圾回收相关概念
  20. [Chrome] 超级好用的网页保存插件

热门文章

  1. Michael喜欢滑雪百这并不奇怪(记忆化搜索)
  2. 【论文阅读】DeepIM: Deep Iterative Matching for 6D Pose Estimation
  3. RN实现手机摇一摇功能
  4. JavaScript中的作用域及作用域链
  5. mysql8远程连接报错_远程连接MYSQL8.0服务器问题
  6. codewars练习(javascript)-2021/2/5
  7. Windows系统文件共享
  8. 荣耀4a android art,荣耀4A拆机图解·看真相
  9. Biometric Framework overview (生物识别框架概述)
  10. 前端插件:雪碧图(多图压缩为一张)