IOS后台截取手机屏幕的实现(录屏)
来源:互联网 发布:电视点播软件 编辑:程序博客网 时间:2024/04/30 23:10
最近自己在搞全局截屏,抓取屏幕的方法很多,但是大多都是抓取UIView的,或者只能抓取应用window的,当程序进入后台的时候就没法抓取手机桌面的,搜了很多也没有抓取全局屏幕的,只有一个利用硬件缓冲区的方式来抓取全局屏幕的方法,需要用到苹果的私有API。主要是IOKIT IOMobileFramebuffer IOSurface 三个framework、因为需要修改一些地方才可以用使用。下面我就把我整理的代码写上来,供大家参考使用
#import <IOMobileFramebuffer.h>#import <IOKit/IOKitLib.h>#import <IOSurface/IOSurface.h>#import <QuartzCore/QuartzCore.h>
extern IOReturn IOSurfaceLock(IOSurfaceRef buffer, uint32_t options, uint32_t *seed);
extern IOReturn IOSurfaceUnlock(IOSurfaceRef buffer, uint32_t options, uint32_t *seed);
extern size_t IOSurfaceGetWidth(IOSurfaceRef buffer);
extern size_t IOSurfaceGetHeight(IOSurfaceRef buffer);
extern IOSurfaceRef IOSurfaceCreate(CFDictionaryRef properties);
extern void *IOSurfaceGetBaseAddress(IOSurfaceRef buffer);
extern size_t IOSurfaceGetBytesPerRow(IOSurfaceRef buffer);
extern const CFStringRef kIOSurfaceAllocSize;
extern const CFStringRef kIOSurfaceWidth;
extern const CFStringRef kIOSurfaceHeight;
extern const CFStringRef kIOSurfaceIsGlobal;
extern const CFStringRef kIOSurfaceBytesPerRow;
extern const CFStringRef kIOSurfaceBytesPerElement;
extern const CFStringRef kIOSurfacePixelFormat;
//enum
//{
// kIOSurfaceLockReadOnly =0x00000001,
// kIOSurfaceLockAvoidSync =0x00000002
//};
UIImage * screenshot(void);
UIImage * screenshot(){
IOMobileFramebufferConnection connect;
kern_return_t result;
CoreSurfaceBufferRef 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((IOSurfaceRef)screenSurface, 0x00000001, &aseed);
size_t width = IOSurfaceGetWidth((IOSurfaceRef)screenSurface);
size_t height = IOSurfaceGetHeight((IOSurfaceRef)screenSurface);
CFMutableDictionaryRef dict;
size_t 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);
IOSurfaceAcceleratorRef outAcc;
IOSurfaceAcceleratorCreate(NULL, 0, &outAcc);
IOSurfaceAcceleratorTransferSurface(outAcc, (IOSurfaceRef)screenSurface, destSurf, dict,NULL);
IOSurfaceUnlock((IOSurfaceRef)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 *image = [UIImage imageWithCGImage:cgImage];
return image;
}
上面的这段代码有个问题也许大家会发现,就是IOSurfaceRef(destSurf)的释放问题,这个东西释放早了录不下屏,晚了内存会在几秒内崩溃,所以需要在用完用
CFRelease立即释放。血的教训。
编译时你会发现,编译出错了,因为IOSurfaceAcceleratorRef这个定义和IOSurfaceAcceleratorCreate,IOSurfaceAcceleratorTransferSurface这个两个函数你找不到,是因为最初的编辑者少上传了一个头文件导致的,下面我就把这个头文件给贴上来://// IOSurfaceAccelerator.h//#ifndef _IOSURFACE_ACCELERATOR_H#define _IOSURFACE_ACCELERATOR_H 1#include <IOSurface/IOSurfaceAPI.h>#include <IOKit/IOReturn.h>#if __cplusplusextern "C" {#endiftypedef IOReturn IOSurfaceAcceleratorReturn;enum {kIOSurfaceAcceleratorSuccess = 0,};typedef struct __IOSurfaceAccelerator *IOSurfaceAcceleratorRef;IOSurfaceAcceleratorReturn IOSurfaceAcceleratorCreate(CFAllocatorRef allocator, uint32_t type, IOSurfaceAcceleratorRef *outAccelerator);IOSurfaceAcceleratorReturn IOSurfaceAcceleratorTransferSurface(IOSurfaceAcceleratorRef accelerator, IOSurfaceRef sourceSurface, IOSurfaceRef destSurface, CFDictionaryRef dict, void *unknown);#if __cplusplus}#endif#endif就是它了,把它拷贝下去,写到IOSurfaceAccelerator.h中,并且放到headers/IOSurface目录下,修改一下IOSurface.h文件,在文件最后添加上,
#include <IOSurface/IOSurfaceAccelerator.h>
就算完工了。剩下的就是编译了连接了。
连接的时候,你需要添加IOKit.framework,IOMobileFramebuffer.framework和IOSurface.framework这三个包,才能够顺利的编译过去。
文章前半部分引用了这个shenyi0106文章解决了我的
IOSurfaceAcceleratorRef找不到的问题。代码是我目前正在使用的内容。希望能对你们遇到同样问题的人有点帮助
稍后给上修改过的头文件
<pre name="code" class="html"><a target=_blank href="http://download.csdn.net/detail/benyoulai5/9058913" target="_blank">这里给上头文件</a>
- IOS后台截取手机屏幕的实现(录屏)
- 一种非AirPlay的方法来实现IOS录屏
- Android 截取手机屏幕两种实现方案解析
- Android 截取手机屏幕两种实现方案解析
- ios后台运行的实现
- 求IOS录屏并录声音的方案
- AndroidStudio 截取手机屏幕
- Android studio 截取手机屏幕
- 手机屏幕窗口抖动的实现
- 在搭建好Android SDK的Eclipse中截取手机屏幕
- 在搭建好Android SDK的Eclipse中截取手机屏幕
- IOS通过加速感应器实现手机实现手机屏幕上的足球可以来回的滚动反弹
- 图像截取的后台处理
- 后台截取字符串的长度
- (iOS开发) 录屏功能的实现~包括暂停和继续功能
- iOS之短信,邮件,通信录技术的完美实现
- 【iOS沉思录】GCD实现线程同步的方法
- IOS的各种后台情况的实现
- Vm -This host supports Intel VT-x, but Intel VT-x is disabled.
- 枚举类型
- 【UML】——九种图总结
- 使用Handler机制建立图片加载框架(笔记)
- android深入解析Activity的launchMode启动模式,Intent Flag,taskAffinity
- IOS后台截取手机屏幕的实现(录屏)
- 【help of python】range函数
- 工作总结1
- 二叉树的深度
- swift 中UICollection的一些简单的用法
- 关注应用程序的支持和维护
- 重装Ubuntu后要装的软件
- 迷你MVVM框架 avalonjs 入门教程
- 把1到10顺序排列的数随机打乱顺序(Java版)