主要问题是,如何在跳板作为背景/背景下拍摄iOS 7+屏幕截图?
我正在尝试开发一个应用程序,以便在后台记录iOS设备的屏幕。只有在有可能的情况下,使用 private 或 public API才让我担心。我已经进行了一些有关通过编程在iOS设备上拍摄屏幕快照的研究。我发现的第一个“解决方案”已被弃用或无法对当前 Activity 屏幕进行截图,仅显示了可在应用程序内查看的内容(无状态栏,通知中心,通知或控制中心)。
我最终遇到了似乎是iOS 7.0-7.1.x上唯一使用IOSurface的工作方法。根据我的研究,如果安装了10.6 Xcode iOS 4 SDK,IOSurface是OSX 10.6中公开可用的框架。 (/系统/库/框架/IOSurface.framework/标头/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+上捕获屏幕截图。
最佳答案
这实际上是IOSurfaceBase.h文件而不是IOSurfaceAPI.h文件的错误。也可能是您在IOSurface框架中没有IOSurfaceBase.h文件。您必须确保在IOSurfaceBase.h文件中声明了#define IOSFC_AVAILABLE_STARTING(_mac,_iphone)
。或者,如果您正在使用theos头文件https://github.com/rpetrich/iphoneheaders,则应该已经在IOSurface.h中声明了它,然后您所要做的就是将Mac OS X系统中的IOSurfaceAPI.h文件复制到其他IOSurface头文件,然后添加依次转到SDK文件夹,PrivateFrameworks和IOSurface.framework,将其添加到项目中。在其中创建一个新文件夹,并将其命名为“Headers”。将所有IOSurface文件复制到新创建的标头文件夹中,然后应该可以清除错误!
关于ios - 在iOS 7-7.1.x上截屏,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/23666502/