【发布时间】:2014-07-03 04:59:28
【问题描述】:
主要问题,如何在 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(这里放不下)
显然,我收到的主要是关于 API 不适用于 iOS 的错误,但令我困惑的是其他人如何能够成功地使用 IOSurface 在 iOS 7+ 上捕获屏幕截图。
【问题讨论】:
标签: ios iphone objective-c ios7