| #! /usr/bin/env python |
| ''' |
| Copyright (C) 2012-2015 Diego Torres Milano |
| Created on Feb 3, 2012 |
| |
| @author: diego |
| ''' |
| |
| __version__ = '11.5.9' |
| |
| import sys |
| import os |
| import getopt |
| |
| try: |
| sys.path.insert(0, os.path.join(os.environ['ANDROID_VIEW_CLIENT_HOME'], 'src')) |
| except: |
| pass |
| |
| from com.dtmilano.android.viewclient import ViewClient, View, ViewClientOptions |
| |
| HELP = 'help' |
| VERBOSE = 'verbose' |
| VERSION = 'version' |
| IGNORE_SECURE_DEVICE = 'ignore-secure-device' |
| IGNORE_VERSION_CHECK = 'ignore-version-check' |
| FORCE_VIEW_SERVER_USE = 'force-view-server-use' |
| DO_NOT_START_VIEW_SERVER = 'do-not-start-view-server' |
| DO_NOT_IGNORE_UIAUTOMATOR_KILLED = 'do-not-ignore-uiautomator-killed' |
| WINDOW = 'window' |
| ALL = 'all' |
| UNIQUE_ID = 'uniqueId' |
| POSITION = 'position' |
| BOUNDS = 'bounds' |
| CONTENT_DESCRIPTION = 'content-description' |
| TAG = 'tag' |
| CENTER = 'center' |
| SAVE_SCREENSHOT = 'save-screenshot' |
| SAVE_VIEW_SCREENSHOTS = 'save-view-screenshots' |
| DO_NOT_DUMP_VIEWS = 'do-not-dump-views' |
| DEVICE_ART = 'device-art' |
| DROP_SHADOW = 'drop-shadow' |
| SCREEN_GLARE = 'glare' |
| USE_UIAUTOMATOR_HELPER = 'use-uiautomator-helper' |
| |
| MAP = { |
| 'a':View.__str__, ALL:View.__str__, |
| 'i':ViewClient.TRAVERSE_CITUI, UNIQUE_ID:ViewClient.TRAVERSE_CITUI, |
| 'x':ViewClient.TRAVERSE_CITPS, POSITION:ViewClient.TRAVERSE_CITPS, |
| 'b':ViewClient.TRAVERSE_CITB, BOUNDS:ViewClient.TRAVERSE_CITB, |
| 'd':ViewClient.TRAVERSE_CITCD, CONTENT_DESCRIPTION:ViewClient.TRAVERSE_CITCD, |
| 'g':ViewClient.TRAVERSE_CITG, TAG:ViewClient.TRAVERSE_CITG, |
| 'c':ViewClient.TRAVERSE_CITC, CENTER:ViewClient.TRAVERSE_CITC, |
| 'W':ViewClient.TRAVERSE_CITCDS, SAVE_VIEW_SCREENSHOTS:ViewClient.TRAVERSE_CITCDS, |
| 'D':ViewClient.TRAVERSE_S, DO_NOT_DUMP_VIEWS:ViewClient.TRAVERSE_S |
| } |
| |
| USAGE = 'usage: %s [OPTION]... [serialno]' |
| SHORT_OPTS = 'HVvIEFSkw:aixbdgcf:W:DA:ZBh' |
| LONG_OPTS = [HELP, VERBOSE, VERSION, IGNORE_SECURE_DEVICE, IGNORE_VERSION_CHECK, FORCE_VIEW_SERVER_USE, |
| DO_NOT_START_VIEW_SERVER, DO_NOT_IGNORE_UIAUTOMATOR_KILLED, WINDOW + '=', |
| ALL, UNIQUE_ID, POSITION, BOUNDS, CONTENT_DESCRIPTION, TAG, CENTER, |
| SAVE_SCREENSHOT + '=', SAVE_VIEW_SCREENSHOTS + '=', |
| DO_NOT_DUMP_VIEWS, |
| DEVICE_ART + '=', DROP_SHADOW, SCREEN_GLARE, |
| USE_UIAUTOMATOR_HELPER, |
| ] |
| LONG_OPTS_ARG = {WINDOW: 'WINDOW', SAVE_SCREENSHOT: 'FILE', SAVE_VIEW_SCREENSHOTS: 'DIR', DEVICE_ART: 'MODEL'} |
| OPTS_HELP = { |
| 'H': 'prints this help', |
| 'V': 'verbose comments', |
| 'I': 'ignore secure device', |
| 'F': 'force view server use (even if UiAutomator present)', |
| 'S': 'don\'t start ViewServer', |
| 'k': 'don\'t ignore UiAutomator killed', |
| 'w': 'dump WINDOW content (default: -1, all windows)', |
| 'a': 'dump all information about Views', |
| 'i': 'dump View unique IDs', |
| 'x': 'dump View positions', |
| 'b': 'dump View bounds', |
| 'd': 'dump View content descriptions', |
| 'g': 'dump View tags', |
| 'c': 'dump View centers', |
| 'f': 'save screenshot to file', |
| 'W': 'save View screenshots to files in directory', |
| 'E': 'ignores ADB version check', |
| 'D': 'don\'t dump views, only useful if you specified -f or -W', |
| 'A': 'device art model to frame screenshot (auto: autodetected)', |
| 'Z': 'drop shadow for device art screenshot', |
| 'B': 'screen glare over screenshot', |
| 'h': 'use UiAutomatorHelper Android app', |
| } |
| |
| def shortAndLongOptions(): |
| ''' |
| @return: the list of corresponding (short-option, long-option) tuples |
| ''' |
| |
| short_opts = SHORT_OPTS.replace(':', '') |
| if len(short_opts) != len(LONG_OPTS): |
| raise Exception('There is a mismatch between short and long options') |
| t = tuple(short_opts) + tuple(LONG_OPTS) |
| l2 = len(t)/2 |
| sl = [] |
| for i in range(l2): |
| sl.append((t[i], t[i+l2])) |
| return sl |
| |
| def usage(exitVal=1): |
| print >> sys.stderr, USAGE % progname |
| print >> sys.stderr, "Try '%s --help' for more information." % progname |
| sys.exit(exitVal) |
| |
| def help(): |
| print >> sys.stderr, USAGE % progname |
| print >> sys.stderr |
| print >> sys.stderr, "Options:" |
| for so, lo in shortAndLongOptions(): |
| o = ' -%c, --%s' % (so, lo) |
| if lo[-1] == '=': |
| o += LONG_OPTS_ARG[lo[:-1]] |
| try: |
| o = '%-34s %-45s' % (o, OPTS_HELP[so]) |
| except: |
| pass |
| print >> sys.stderr, o |
| sys.exit(0) |
| |
| def version(): |
| print progname, __version__ |
| sys.exit(0) |
| |
| # __main__ |
| progname = os.path.basename(sys.argv[0]) |
| try: |
| opts, args = getopt.getopt(sys.argv[1:], SHORT_OPTS, LONG_OPTS) |
| sys.argv[1:] = args |
| except getopt.GetoptError, e: |
| print >>sys.stderr, 'ERROR:', str(e) |
| usage() |
| |
| kwargs1 = {VERBOSE: False, 'ignoresecuredevice': False, 'ignoreversioncheck': False} |
| kwargs2 = {ViewClientOptions.FORCE_VIEW_SERVER_USE: False, ViewClientOptions.START_VIEW_SERVER: True, |
| ViewClientOptions.AUTO_DUMP: False, ViewClientOptions.IGNORE_UIAUTOMATOR_KILLED: True, |
| ViewClientOptions.COMPRESSED_DUMP: True, |
| ViewClientOptions.USE_UIAUTOMATOR_HELPER: False, |
| } |
| options = {WINDOW: -1, SAVE_SCREENSHOT: None, SAVE_VIEW_SCREENSHOTS: None, DO_NOT_DUMP_VIEWS: False, |
| DEVICE_ART: None, DROP_SHADOW: False, SCREEN_GLARE: False} |
| transform = ViewClient.TRAVERSE_CIT |
| for o, a in opts: |
| o = o.strip('-') |
| if o in ['H', HELP]: |
| help() |
| elif o in ['V', VERBOSE]: |
| kwargs1[VERBOSE] = True |
| elif o in ['v', VERSION]: |
| version() |
| elif o in ['I', IGNORE_SECURE_DEVICE]: |
| kwargs1['ignoresecuredevice'] = True |
| elif o in ['E', IGNORE_VERSION_CHECK]: |
| kwargs1['ignoreversioncheck'] = True |
| elif o in ['F', FORCE_VIEW_SERVER_USE]: |
| kwargs2[ViewClientOptions.FORCE_VIEW_SERVER_USE] = True |
| elif o in ['S', DO_NOT_START_VIEW_SERVER]: |
| kwargs2[ViewClientOptions.START_VIEW_SERVER] = False |
| elif o in ['k', DO_NOT_IGNORE_UIAUTOMATOR_KILLED]: |
| kwargs2[ViewClientOptions.IGNORE_UIAUTOMATOR_KILLED] = False |
| elif o in ['w', WINDOW]: |
| options[WINDOW] = a |
| elif o in ['f', SAVE_SCREENSHOT]: |
| options[SAVE_SCREENSHOT] = a |
| elif o in ['W', SAVE_VIEW_SCREENSHOTS]: |
| options[SAVE_VIEW_SCREENSHOTS] = a |
| transform = MAP[o] |
| elif o in ['A', DEVICE_ART]: |
| options[DEVICE_ART] = a |
| elif o in ['Z', DROP_SHADOW]: |
| options[DROP_SHADOW] = True |
| elif o in ['B', SCREEN_GLARE]: |
| options[SCREEN_GLARE] = True |
| elif o in ['h', USE_UIAUTOMATOR_HELPER]: |
| kwargs2[ViewClientOptions.USE_UIAUTOMATOR_HELPER] = True |
| elif o in ['D', DO_NOT_DUMP_VIEWS]: |
| options[DO_NOT_DUMP_VIEWS] = True |
| transform = MAP[o] |
| else: |
| transform = MAP[o] |
| |
| if options[DO_NOT_DUMP_VIEWS]: |
| transform = MAP[DO_NOT_DUMP_VIEWS] |
| |
| vc = ViewClient(*ViewClient.connectToDeviceOrExit(**kwargs1), **kwargs2) |
| if options[SAVE_SCREENSHOT]: |
| vc.device.reconnect = True #(not options[DO_NOT_DUMP_VIEWS]) |
| vc.writeImageToFile(options[SAVE_SCREENSHOT], deviceart=options[DEVICE_ART], dropshadow=options[DROP_SHADOW], screenglare=options[SCREEN_GLARE]) |
| if not options[DO_NOT_DUMP_VIEWS] or options[SAVE_VIEW_SCREENSHOTS]: |
| vc.dump(window=options[WINDOW]) |
| ViewClient.imageDirectory = options[SAVE_VIEW_SCREENSHOTS] |
| vc.traverse(transform=transform) |
| if kwargs2[ViewClientOptions.USE_UIAUTOMATOR_HELPER]: |
| try: |
| vc.uiAutomatorHelper.quit() |
| except: |
| pass |