Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
249 views
in Technique[技术] by (71.8m points)

jailbreak - Taking Screenshots from iOS app - emulating Display recorder (query on the internals)

I need to create an iOS app which can take screenshots of other apps, videos etc. as a part of an experiment. I am open to using Private API's since I won't be publishing the app to the app store. I could successfully use the method GetUIScreenImage() to take snapshots of the current screen (app screen).

However, due to sandbox restrictions I am not able to take screenshots while in the background. I get the error - "Cannot call CreateUIScreenImage() while the app is in background".

I referred to this article - How does the iOS app Display Recorder record the screen without using private API? which suggested use of IOMobileFramebuffer and IOSurface to bypass sandbox restrictions, also this link - http://www.iphonesheep.com/2009/11/25/iphone%E2%80%99s-framebuffer-secrets-revealed/. But I am unable to get the flow of creating and transferring surfaces. Any help on this topic is highly appreciated.

Also, is there a way to call UIGetScreenImage() in the background on a jailbroken device ?

Update:
I am able to get hold of the main screen surface and put it on the app layer, but my use case is to be able to open up other apps and be able to record them via the app I create. The surface I paste over my app layer is however static.

edit
Here is what I understand - the main screen surface attached to the main display layer needs to be put on the current layer. After doing so, I should be able to browse through other apps, open them from the surface just pasted.

Here is the code (It puts the main screen surface on top of app layer but I am unable to use that surface i.e, open up apps etc.):

IOMobileFramebufferConnection connect;
kern_return_t result;
CoreSurfacebufferRef screenSurface = NULL;
io_service_t framebufferService = IOServiceGetMatchingService (kIOMasterPortDefault, IOServiceMatching ("AppleH1CLCD"));
if(!framebufferService)
        io_service_t framebufferService = IOServiceGetMatchingService (kIOMasterPortDefault, IOServiceMatching ("AppleM2CLCD"));
if(!framebufferService)
        io_service_t framebufferService = IOServiceGetMatchingService (kIOMasterPortDefault, IOServiceMatching ("AppleCLCD"));
result = IOMobileFramebufferOpen( framebufferService, mach_task_self(), 0 , &connect);
result = IOMobileFramebufferGetLayerDefaultSurface(connect, 0, &screenSurface);

CALayer *Layer;
Layer = [CALayer layer];
[Layer setFrame: CGRectMake(0, 0, 768, 1024)];
[Layer setOpaque:YES];
IOSurfaceLock(screenSurface, 0, NULL);
[Layer setContents: (_bridge id)(screenSurface)];
IOSurfaceUnlock(screenSurface, 0, NULL);
[self.view.layer addSublayer:Layer];

I know i am missing out something and doing something wrong. It would be great help if you could point that out.

update
I think I may be wrong in my fundamental assumption.
1. What I assume -> The app swaps the surfaces (or layers) so that the user can now browse on the main screen. The app never moves to the background.
2. What sounds more correct -> The app moves to the background. Gets the topmost surface on screen, creates an image out of it and saves it. Please clarify.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

What is exactly the problem with "get the flow of creating and transferring surface"? Can you post the code which are using and point out which line doesn't work.

For the jailbroken devices:

Go to /Application/XCode/Content/Developer/Platforms and grep it for the sentence "Cannot call CreateUIScreenImage() while the app is in background". You will find it in some framework (I assume UIKit). Next, you can disassemble it and you will find some entitlement which is required to do screenshots in the background.

And you can look here how to use entitlements with ldid for jailbroken device: iOS How to use Entitlement.plist to specify property of my app


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...