IOSurface – IOS私有API – 在后台捕获屏幕截图

我想从后台服务捕捉截图。 私有API是好的,因为我不需要提交到应用程序商店。 我已经尝试过UIGetScreenImage,它不能从后台应用程序工作。

我正在使用下面的代码,我从SO得到。 IOSurfaceCreate对我返回null。 任何帮助赞赏。

CFMutableDictionaryRef dict; IOSurfaceRef screenSurface = NULL; char pixelFormat[4] = {'A','R','G','B'}; dict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); uint32_t width ; uint32_t height; void *pitch; void *bPE; void *size; 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); IOSurfaceAcceleratorRef outAcc; IOSurfaceAcceleratorCreate(NULL, 0, &outAcc); CFDictionaryRef ed = (__bridge CFDictionaryRef)[NSDictionary dictionaryWithObjectsAndKeys: nil]; IOSurfaceAcceleratorTransferSurface(outAcc, screenSurface, destSurf, ed, NULL); uint32_t aseed; IOSurfaceUnlock(screenSurface, kIOSurfaceLockReadOnly, &aseed); 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 *image = [UIImage imageWithCGImage: cgImage]; UIImageWriteToSavedPhotosAlbum(image, self_object, nil, nil); CGImageRelease(cgImage); CFRelease(destSurf); 

结合2个地方的代码后,我可以保存照片到相册(我的应用程序在后台)。

IOSurfaces – video中的人为现象,无法抓取video表面

https://github.com/tomcool420/SMFramework/blob/master/SMFScreenCapture.m

请试试,让我知道,如果它适合你。

 -(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); }