需求
先简单介绍一下标题的含义。也许你看到iOS
、截屏
,觉得这有什么好长篇大论的,小菜一碟而已。可能你忽略了后台
这个关键词。
这里的关键就在于怎么在 App 切换到后台之后,仍然能够持续截取用户屏幕内容。解决了这点,剩下的就是把图片合成视频,有必要的话再加入声音。
另外,需要说明的是,实现后台截屏只能使用私有 API,而苹果是不允许这类 App 上架的,就算你用了一些技巧(比如动态加载私有 API 以绕过 App Store 的审核)而上架,假以时日苹果也会发现并且下架处理。Display Recorder 就是这么做并且被下架的,所以现在它发到越狱市场了。
作用
在 iOS 上录制全局屏幕,保存成一个视频,这么一个小众需求到底有什么作用?虽然一般用户都不会用到,不过它还是有点用的:
- 录制 App 使用的视频教程(而不是图片+文字、图片+文字、图片+文字);
- 如果 App 有个在某些用户机器上必现的 Bug,可以让他把操作记录下来,发给开发者(这样码农们就没办法再推脱:“在我这里是好的!肯定是你的打开方式不对!”);
- 如果你是游戏大神,玩得一手好手游,还可以把你在游戏中的神操作保存下来供日后回味(或者分享出去让小白们膜拜)。
实现
iOS 的系统封闭,API 变化无常,所以并没有一个可以全版本 iOS 系统通用的后台截屏方法。下面所列的方法都因系统版本而异,前提都是非越狱。
1. _UICreateScreenUIImage (< iOS 6)
_UICreateScreenUIImage 是 UIImage 的一个私有方法,在 iOS 6以前可以用于后台调用截屏,方法如下:
1 2 3 4 5 6 |
|
但是,在 iOS 6 以后,这个方法不允许在 App 切到后台的时候调用了,会在调试控制台输出不能调用的错误提示。
2. CARenderServerRenderDisplay (< iOS 7)
RecordMyScreen 用的就是这个方法,不过实测在 iOS 7以上,只能截到黑色的空白图片。网上说 RecordMyScreen 就是 Display Recorder 的开源版本。
其中涉及到后台截屏的代码如下:
1 2 3 4 5 6 7 8 9 10 11 |
|
但是,经过测试,在iOS 7和iOS 8上,这个方法没办法正确截屏,只能得到黑色的图片。而且,虽说 RecordMyScreen 是一个开源项目,但实际上它并不是一份完整可用的代码,开源到中途,作者发现有人在窃取他的项目源码,于是停止了开源。虽然如此,该项目中对于音视频的编码、合成部分的处理都是很值得参考的。
3. createScreenIOSurface(< iOS 7?)
ScreenRecorder 用了这个方法,但是实际上这个项目没办法在后台运行。
1 2 3 4 5 6 7 8 9 10 11 12 |
|
4. 终极方法 IOSurface (< iOS 9)
好吧,前面提到的几种方法在 iOS 7 以上版本都没啥卵用。现在说的这个方法是可以在 iOS 7 和 iOS 8 上使用的,只是 iOS 9 禁用了该方法。
与 RecordMyScreen 类似,还是基于 IOSurface 私有库,只是调用的方法不太一样:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
|
见:
- IOMobileFramebufferGetLayerDefaultSurface does not work on ios7 retina
- IOMobileFramebufferGetLayerDefaultSurface not working on iOS 9
合成
在 App 后台得到截图之后怎么处理成视频呢?其实在 RecordMyScreen 中有完整的代码可以参考,只是它里面截屏的方法需要替换为本文提到的第四种
实现,不赘述。
注意
- 需要修改 App 的 plist 文件,使其能在后台运行。
- 需要打开设备的 Access Touch 功能,否则对于 OpenGL 实现的游戏 App,会黑屏。
- iPad Retina 屏幕像素过大,处理起来很吃力,需要减小生成的图片大小。
原文作者: lslin
原文链接: http://blog.lessfun.com/blog/2015/12/25/ios-record-screen-in-background/
版权声明:自由转载-非商用-非衍生-保持署名 | Creative Commons BY-NC-ND 3.0