#!C:\tools\Python27\python.exe ''' Copyright (C) 2012-2015 Diego Torres Milano Created on Feb 3, 2012 @author: diego ''' __version__ = '10.3.0' 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 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' 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:ZB' 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, ] 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', } 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 = {'forceviewserveruse': False, 'startviewserver': True, 'autodump': False, 'ignoreuiautomatorkilled': True} 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['forceviewserveruse'] = True elif o in ['S', DO_NOT_START_VIEW_SERVER]: kwargs2['startviewserver'] = False elif o in ['k', DO_NOT_IGNORE_UIAUTOMATOR_KILLED]: kwargs2['ignoreuiautomatorkilled'] = 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 ['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)