在iOS 7 - 7.1.x上截取屏幕截图

时间:2014-05-14 22:54:02

标签: ios iphone objective-c ios7

主要问题是,如何在跳板/跳板的情况下拍摄iOS 7+截图?

我正在尝试开发一个应用程序,以便在后台运行时录制iOS设备的屏幕。使用私有或公共API并不会让我担心,只有这样才有可能。我已经做了一些研究,通过编程在iOS设备上拍摄屏幕截图。第一个解决方案'我发现它已被弃用或无法截断当前活动屏幕,只能查看应用内可见的内容(无状态栏,通知中心,通知或控制中心)。

我最终遇到了似乎是iOS 7.0的唯一工作方法 - 7.1.x,它正在使用IOSurface。根据我的研究,如果您安装了10.6 Xcode iOS 4 SDK,IOSurface是OSX 10.6中公开提供的框架。 (/System/Library/Frameworks/IOSurface.framework/Headers/IOSurfaceAPI.h)

以下是有关Stack Overflow的几个问题,并解释说这些用户可以使用IOSurface:

Using IOSurface to take screenshot in iOS7 in games - 用户表示他在截取屏幕截图方面没有任何问题,只能查看游戏。

How to take screenshot for the entire screen no matter which app is at front most in iOS 7(Jailbroken)此用户希望使用此方法在越狱设备上截取屏幕截图,响应的用户已成功使用IOSurface,无需越狱。

https://stackoverflow.com/a/16505514/3139899用户myCodeHurts也取得了成功,所有代码都非常相似。

上述所有用户似乎都取得了成功,而不是一个人甚至提到需要IOSurface.framework。

我目前的代码:

-(void)SavePhoto
{
IOMobileFramebufferConnection connect;
kern_return_t result;
IOSurfaceRef screenSurface = NULL;

io_service_t framebufferService = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching("AppleH1CLCD"));
if(!framebufferService)
    framebufferService = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching("AppleM2CLCD"));
if(!framebufferService)
    framebufferService = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching("AppleCLCD"));

result = IOMobileFramebufferOpen(framebufferService, mach_task_self(), 0, &connect);

result = IOMobileFramebufferGetLayerDefaultSurface(connect, 0, &screenSurface);

uint32_t aseed;
IOSurfaceLock(screenSurface, kIOSurfaceLockReadOnly, &aseed);
uint32_t width = IOSurfaceGetWidth(screenSurface);
uint32_t height = IOSurfaceGetHeight(screenSurface);
//int m_width = 320;
//int m_height = 480;
CFMutableDictionaryRef dict;
int pitch = width*4, size = width*height*4;
int bPE=4;
char pixelFormat[4] = {'A','R','G','B'};
dict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
CFDictionarySetValue(dict, kIOSurfaceIsGlobal, kCFBooleanTrue);
CFDictionarySetValue(dict, kIOSurfaceBytesPerRow, CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &pitch));
CFDictionarySetValue(dict, kIOSurfaceBytesPerElement, CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &bPE));
CFDictionarySetValue(dict, kIOSurfaceWidth, CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &width));
CFDictionarySetValue(dict, kIOSurfaceHeight, CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &height));
CFDictionarySetValue(dict, kIOSurfacePixelFormat, CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, pixelFormat));
CFDictionarySetValue(dict, kIOSurfaceAllocSize, CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &size));

IOSurfaceRef destSurf = IOSurfaceCreate(dict);

void* outAcc;
IOSurfaceAcceleratorCreate(NULL, 0, &outAcc);

IOSurfaceAcceleratorTransferSurface(outAcc, screenSurface, destSurf, dict, NULL);

IOSurfaceUnlock(screenSurface, kIOSurfaceLockReadOnly, &aseed);
CFRelease(outAcc);

CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, IOSurfaceGetBaseAddress(destSurf), (width * height * 4), NULL);
CGImageRef cgImage=CGImageCreate(width, height, 8,
                                 8*4, IOSurfaceGetBytesPerRow(destSurf),
                                 CGColorSpaceCreateDeviceRGB(), kCGImageAlphaNoneSkipFirst |kCGBitmapByteOrder32Little,
                                 provider, NULL,
                                 YES, kCGRenderingIntentDefault);
UIImage *img = [UIImage imageWithCGImage:cgImage];
UIImageWriteToSavedPhotosAlbum(img, self, nil, nil);

// MOST RELEVANT PART OF CODE

//CVPixelBufferCreateWithBytes(NULL, width, height, kCVPixelFormatType_32BGRA, IOSurfaceGetBaseAddress(destSurf), IOSurfaceGetBytesPerRow(destSurf), NULL, NULL, NULL, &sampleBuffer);
}

这取自另一个问题的myCodeHurts'回答。

我已经尝试过,没有IOSurface的官方版本,以及我在互联网上找到的其他一些链接,所有这些在Xcode中构建时都会返回相同的错误:

http://pastie.org/9176533(太长了不适合这里)

我显然主要收到关于iOS不可用的API的错误,但令我困惑的是其他人如何能够成功使用IOSurface捕获iOS 7 +上的屏幕截图。

2 个答案:

答案 0 :(得分:1)

这实际上是IOSurfaceBase.h文件的错误,而不是IOSurfaceAPI.h文件。也可能是您在IOSurface框架中没有IOSurfaceBase.h文件。您必须确保在IOSurfaceBase.h文件中声明#define IOSFC_AVAILABLE_STARTING(_mac,_iphone)。或者,如果您正在使用theos标题https://github.com/rpetrich/iphoneheaders,这应该已在IOSurface.h中声明,然后您只需将IOSurfaceAPI.h文件从Mac OS X系统复制到另一个IOSurface标题,然后转到SDK文件夹,然后转到PrivateFrameworks,然后转到IOSurface.framework,将其添加到项目中。在那里创建一个新文件夹并将其命名为“Headers”。将所有IOSurface文件复制到新创建的头文件夹,然后清除错误!

答案 1 :(得分:0)

/ Users / justin / Desktop / iOS Development / Projects / iRec / iRec / ViewController.m:66:32:错误:'kIOSurfaceWidth'不可用:iOS上不可用

有点明显,不是吗? iOS需要kIOSurfaceWidth。