从iOS应用程序中进行屏幕截图 - 模拟Display Recorder(关于内部查询)

4
我需要创建一个iOS应用程序,可以作为实验的一部分截取其他应用程序、视频等的屏幕截图。由于我不会将该应用发布到应用商店,因此我可以使用私有API。我可以成功使用GetUIScreenImage()方法来截取当前屏幕(应用屏幕)的快照。
然而,由于沙盒限制,我无法在后台截取屏幕截图。我会收到错误提示 - “Cannot call CreateUIScreenImage() while the app is in background”。
我参考了这篇文章 - How does the iOS app Display Recorder record the screen without using private API?,建议使用IOMobileFramebuffer和IOSurface绕过沙盒限制,以及这个链接 - http://www.iphonesheep.com/2009/11/25/iphone%E2%80%99s-framebuffer-secrets-revealed/。但是我无法理解如何创建和传输表面。非常感谢对此话题的任何帮助。
另外,有没有办法在越狱设备的后台中调用UIGetScreenImage()?
更新: 我能够获取主屏幕表面并将其放在应用程序层上,但我的用例是能够打开其他应用程序并能够通过我创建的应用程序记录它们。我覆盖在我的应用程序层上的表面是静态的。
编辑: 这是我理解的-附加到主显示层的主屏幕表面需要放置在当前层上。这样做后,我应该能够浏览其他应用程序,从刚刚粘贴的表面打开它们。
这是代码(它将主屏幕表面放在应用程序层的顶部,但我无法使用该表面,即打开应用程序等):
IOMobileFramebufferConnection connect;
kern_return_t result;
CoreSurfacebufferRef screenSurface = NULL;
io_service_t framebufferService = IOServiceGetMatchingService (kIOMasterPortDefault, IOServiceMatching ("AppleH1CLCD"));
if(!framebufferService)
        io_service_t framebufferService = IOServiceGetMatchingService (kIOMasterPortDefault, IOServiceMatching ("AppleM2CLCD"));
if(!framebufferService)
        io_service_t framebufferService = IOServiceGetMatchingService (kIOMasterPortDefault, IOServiceMatching ("AppleCLCD"));
result = IOMobileFramebufferOpen( framebufferService, mach_task_self(), 0 , &connect);
result = IOMobileFramebufferGetLayerDefaultSurface(connect, 0, &screenSurface);

CALayer *Layer;
Layer = [CALayer layer];
[Layer setFrame: CGRectMake(0, 0, 768, 1024)];
[Layer setOpaque:YES];
IOSurfaceLock(screenSurface, 0, NULL);
[Layer setContents: (_bridge id)(screenSurface)];
IOSurfaceUnlock(screenSurface, 0, NULL);
[self.view.layer addSublayer:Layer];

我知道我可能遗漏了某些东西并且做错了一些事情。如果您能指出来,那将是很大的帮助。 更新
我认为我的基本假设可能是错误的。
1. 我的假设 -> 应用程序交换表面(或图层),以便用户现在可以在主屏幕上浏览。该应用程序从未移动到后台。
2. 更正确的做法 -> 应用程序移至后台。获取屏幕上的最顶层表面,创建其图像并保存。
请澄清。
1个回答

3
“get the flow of creating and transferring surface”究竟有什么问题?您能发布使用的代码并指出哪行不起作用吗?
对于越狱设备:
前往/Application/XCode/Content/Developer/Platforms并搜索“Cannot call CreateUIScreenImage() while the app is in background”。您会在某些框架(我假设是UIKit)中找到它。接下来,您可以对其进行反汇编,并找到一些需要在后台进行截屏的权限。
您可以在此处查看如何在越狱设备上使用ldid的授权: iOS How to use Entitlement.plist to specify property of my app

谢谢Victor。我已经放入了代码。我也会尝试另一种方法。 - Hrishikesh_Pardeshi
你能详细解释答案的第二部分“接下来,您可以对其进行反汇编,然后找到一些必须要求在后台截屏的授权”吗? - Hrishikesh_Pardeshi
一些API具有访问控制。因此,特权应用程序(例如Springboard)可以调用它们,而非特权应用程序则不能。这些特权在iOS中称为entitlements。某个代码会检查调用者的entitlements,并在没有entitlement时返回错误。因此,如果您找到了该字符串,请反汇编该框架并查看其使用位置,您将在该字符串的使用位置附近找到适当entitlement的检查。 - Victor Ronin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接