IOSurface - IOS 私有 API - 后台截取屏幕截图

8

我想从后台服务中截取屏幕截图。由于我不需要提交给应用商店,所以私有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);
1个回答

9

将来自两个地方的代码结合后,我成功地将照片保存到相册中(同时我的应用程序在后台运行)。

IOSurfaces - 视频中的伪像和无法抓取视频表面

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

你在iOS 7上搞定了吗?我在IOMobileFramebufferOpen上遇到了链接器错误。你能分享一下需要链接哪些框架/库以及从哪里获取头文件吗? - Frank
将以下的命令行添加以删除来自iOSurface的错误:
cd /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS7.0.sdk/System/Library/Frameworks/IOKit.framework sudo ln -s Versions/A/IOKit
- Dhekra Zaied
有人有一个iOS 8的工作演示项目吗?或者能告诉我如何使用这个框架/获取头文件吗? - Max
但是过一段时间后,它总是会给出旧的图像。但是当我们打开照片应用程序时,它会开始提供新的屏幕截图。为什么? - Nishith Shah

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