自动化iPhone模拟器上的截图?

时间:2009-09-01 04:40:41

标签: iphone

每次我为iPhone应用程序更改UI时,我都厌倦了拍摄新的屏幕截图。我希望能够运行脚本/程序/无论在模拟器上加载我的二进制文件,然后拍摄一些截图。

解决方案可以是任何语言......对我来说无关紧要。

谢谢!

6 个答案:

答案 0 :(得分:25)

使用iPhone SDK 4,您可以自动执行GUI测试,并且可以为您截取屏幕截图。

基本上,您编写了一个Javascript脚本,然后Instruments(使用自动化模板)可以在设备上运行它来测试UI,并且可以记录数据,屏幕截图等,并且还可以在出现故障时发出警报。

我找不到它的参考指南,但在SDK参考库中搜索UIA*类(如UIAElement)。

还有一个视频演示来自WWDC,会话306。

答案 1 :(得分:12)

我有同样的愿望。我希望能够在我的应用程序中保存几个屏幕的屏幕截图,而无需所有手动工作。我还没有,但我已经开始了。

想法是尾随/var/log/system.log,其中NSLog语句的输出去。我将输出传递给python程序。 python程序从stdin读取所有行,当行匹配特定模式时,它调用screencapture。

NSLog(@"screenshot mainmenu.png");

这将导致每次调用时都会创建一个名为“XX.mainmenu YY.png”的屏幕截图。 XX是程序启动后的屏幕截图编号。 YY是“mainmenu”屏幕截图的编号。

我甚至添加了一些不必要的功能:

NSLog(@"screenshot -once mainmenu.png");

这只会保存一次“XX.mainmenu.png”。

NSLog(@"screenshot -T 4 mainmenu.png");

这将在延迟4秒后制作屏幕截图。

使用正确的日志记录运行应用程序后,可能已创建具有以下名称的屏幕截图:

00. SplashScreen.png
01. MainMenu 01.png
03. StartLevel 01.png
04. GameOver 01.png
05. MainMenu 02.png

试一试:

  1. 在代码中添加一些NSLog语句

  2. $ tail -f -n0 /var/log/system.log | ./grab.py

  3. 在模拟器中启动您的iPhone应用程序

  4. 使用您的应用

  5. 查看显示启动grab.py程序的屏幕截图

  6. grab.py:

    #!/usr/bin/python
    
    import re
    import os
    from collections import defaultdict
    
    def screenshot(filename, select_window=False, delay_s=0):
        flags = []
        if select_window:
            flags.append('-w')
        if delay_s:
            flags.append('-T %d' % delay_s)
        command_line = 'screencapture %s "%s"' % (' '.join(flags), filename)
        #print command_line
        os.system(command_line)
    
    def handle_line(line, count=defaultdict(int)):
        params = parse_line(line)
        if params:
            filebase, fileextension, once, delay_s = params
            if once and count[filebase] == 1:
                print 'Skipping taking %s screenshot, already done once' % filebase
            else:
                count[filebase] += 1
                number = count[filebase]
                count[None] += 1
                global_count = count[None]
                file_count_string = (' %02d' % number) if not once else ''
    
                filename = '%02d. %s%s.%s' % (global_count, filebase, file_count_string, fileextension)
                print 'Taking screenshot: %s%s' % (filename, '' if delay_s == 0 else (' in %d seconds' % delay_s))
                screenshot(filename, select_window=False, delay_s=delay_s)
    
    def parse_line(line):
        expression = r'.*screenshot\s*(?P<once>-once)?\s*(-delay\s*(?P<delay_s>\d+))?\s*(?P<filebase>\w+)?.?(?P<fileextension>\w+)?'
        m = re.match(expression, line)
        if m:
            params = m.groupdict()
            #print params
            filebase = params['filebase'] or 'screenshot'
            fileextension = params['fileextension'] or 'png'
            once = params['once'] is not None
            delay_s = int(params['delay_s'] or 0)
            return filebase, fileextension, once, delay_s
        else:
            #print 'Ignore: %s' % line
            return None
    
    def main():
        try:
            while True:
                handle_line(raw_input())
        except (EOFError, KeyboardInterrupt):
            pass
    
    if __name__ == '__main__':
        main()
    

    此版本的问题:

    如果您只想截取iPhone模拟器窗口的屏幕截图,则必须单击每个屏幕截图的iPhone模拟器窗口。 screencapture拒绝捕获单个窗口,除非您愿意与它进行交互,这是命令行工具的一个奇怪的设计决策。

    更新:现在,iPhone模拟器裁剪器(http://www.curioustimes.de/iphonesimulatorcropper/index.html)可以在命令行中运行。因此,不要使用内置的screencapture,而是下载并使用它。所以现在这个过程是完全自动的。

答案 2 :(得分:7)

在iPhone模拟器中,有一个“复制屏幕”菜单项。按住Control时,它将替换编辑菜单中的“复制”菜单项。 键击是Ctrl-Cmd-C 一个简单的AppleScript可以复制ScreenShot并保存它。有点像(它对我有用,即使它 hacky):

tell application "iPhone Simulator" to activate
tell application "System Events"
    keystroke "c" using {command down, control down}
end tell
tell application "Preview" to activate
tell application "System Events"
    keystroke "n" using {command down}
    keystroke "w" using {command down}
    delay 1
    keystroke return
    delay 1
    keystroke "File Name"
    keystroke return
end tell

如果你没有得到它,请评论......

答案 3 :(得分:6)

私有UIGetScreenImage(void) API可用于捕获屏幕内容:

CGImageRef UIGetScreenImage();
void SaveScreenImage(NSString *path)
{
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    CGImageRef cgImage = UIGetScreenImage();
    void *imageBytes = NULL;
    if (cgImage == NULL) {
        CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB();
        imageBytes = malloc(320 * 480 * 4);
        CGContextRef context = CGBitmapContextCreate(imageBytes, 320, 480, 8, 320 * 4, colorspace, kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Big);
        CGColorSpaceRelease(colorspace);
        for (UIWindow *window in [[UIApplication sharedApplication] windows]) {
            CGRect bounds = [window bounds];
            CALayer *layer = [window layer];
            CGContextSaveGState(context);
            if ([layer contentsAreFlipped]) {
                CGContextTranslateCTM(context, 0.0f, bounds.size.height);
                CGContextScaleCTM(context, 1.0f, -1.0f);
            }
            [layer renderInContext:(CGContextRef)context];
            CGContextRestoreGState(context);
        }
        cgImage = CGBitmapContextCreateImage(context);
        CGContextRelease(context);
    }
    NSData *pngData = UIImagePNGRepresentation([UIImage imageWithCGImage:cgImage]);
    CGImageRelease(cgImage);
    if (imageBytes)
        free(imageBytes);
    [pngData writeToFile:path atomically:YES];
    [pool release];
}

请务必将其包装在#ifdef内,以便它不会出现在发布版本中。

答案 4 :(得分:1)

如果您对自动更改模拟器语言和设备类型感兴趣,我开发了一些脚本:http://github.com/toursprung/iOS-Screenshot-Automator

答案 5 :(得分:0)

您也可以使用某些屏幕捕获应用程序在模拟器的屏幕上捕获视频。

我经常使用Jing应用程序。

我甚至用它来发送一个向客户提供应用程序的视频......